cpp/ 0000755 0001750 0001750 00000000000 13576650314 011230 5 ustar sergey sergey cpp/gpl3.txt 0000755 0001750 0001750 00000105753 13576650314 012654 0 ustar sergey sergey GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
Copyright (C)
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
. cpp/tests/ 0000755 0001750 0001750 00000000000 13576650314 012372 5 ustar sergey sergey cpp/tests/test_i.cpp 0000755 0001750 0001750 00002107075 13576650313 014403 0 ustar sergey sergey #include "stdafx.h"
#include
#include "alglibinternal.h"
#include "alglibmisc.h"
#include "diffequations.h"
#include "linalg.h"
#include "optimization.h"
#include "solvers.h"
#include "statistics.h"
#include "dataanalysis.h"
#include "specialfunctions.h"
#include "integration.h"
#include "fasttransforms.h"
#include "interpolation.h"
using namespace alglib;
bool doc_test_bool(bool v, bool t)
{ return (v && t) || (!v && !t); }
bool doc_test_int(ae_int_t v, ae_int_t t)
{ return v==t; }
bool doc_test_real(double v, double t, double _threshold)
{
double s = _threshold>=0 ? 1.0 : fabs(t);
double threshold = fabs(_threshold);
return fabs(v-t)/s<=threshold;
}
bool doc_test_complex(alglib::complex v, alglib::complex t, double _threshold)
{
double s = _threshold>=0 ? 1.0 : alglib::abscomplex(t);
double threshold = fabs(_threshold);
return abscomplex(v-t)/s<=threshold;
}
bool doc_test_bool_vector(const boolean_1d_array &v, const boolean_1d_array &t)
{
ae_int_t i;
if( v.length()!=t.length() )
return false;
for(i=0; i=0 ? 1.0 : fabs(t(i));
double threshold = fabs(_threshold);
if( fabs(v(i)-t(i))/s>threshold )
return false;
}
return true;
}
bool doc_test_real_matrix(const real_2d_array &v, const real_2d_array &t, double _threshold)
{
ae_int_t i, j;
if( v.rows()!=t.rows() )
return false;
if( v.cols()!=t.cols() )
return false;
for(i=0; i=0 ? 1.0 : fabs(t(i,j));
double threshold = fabs(_threshold);
if( fabs(v(i,j)-t(i,j))/s>threshold )
return false;
}
return true;
}
bool doc_test_complex_vector(const complex_1d_array &v, const complex_1d_array &t, double _threshold)
{
ae_int_t i;
if( v.length()!=t.length() )
return false;
for(i=0; i=0 ? 1.0 : alglib::abscomplex(t(i));
double threshold = fabs(_threshold);
if( abscomplex(v(i)-t(i))/s>threshold )
return false;
}
return true;
}
bool doc_test_complex_matrix(const complex_2d_array &v, const complex_2d_array &t, double _threshold)
{
ae_int_t i, j;
if( v.rows()!=t.rows() )
return false;
if( v.cols()!=t.cols() )
return false;
for(i=0; i=0 ? 1.0 : alglib::abscomplex(t(i,j));
double threshold = fabs(_threshold);
if( abscomplex(v(i,j)-t(i,j))/s>threshold )
return false;
}
return true;
}
template
void spoil_vector_by_adding_element(T &x)
{
ae_int_t i;
T y = x;
x.setlength(y.length()+1);
for(i=0; i
void spoil_vector_by_deleting_element(T &x)
{
ae_int_t i;
T y = x;
x.setlength(y.length()-1);
for(i=0; i
void spoil_matrix_by_adding_row(T &x)
{
ae_int_t i, j;
T y = x;
x.setlength(y.rows()+1, y.cols());
for(i=0; i
void spoil_matrix_by_deleting_row(T &x)
{
ae_int_t i, j;
T y = x;
x.setlength(y.rows()-1, y.cols());
for(i=0; i
void spoil_matrix_by_adding_col(T &x)
{
ae_int_t i, j;
T y = x;
x.setlength(y.rows(), y.cols()+1);
for(i=0; i
void spoil_matrix_by_deleting_col(T &x)
{
ae_int_t i, j;
T y = x;
x.setlength(y.rows(), y.cols()-1);
for(i=0; i
void spoil_vector_by_nan(T &x)
{
if( x.length()!=0 )
x(randominteger(x.length())) = fp_nan;
}
template
void spoil_vector_by_posinf(T &x)
{
if( x.length()!=0 )
x(randominteger(x.length())) = fp_posinf;
}
template
void spoil_vector_by_neginf(T &x)
{
if( x.length()!=0 )
x(randominteger(x.length())) = fp_neginf;
}
template
void spoil_matrix_by_nan(T &x)
{
if( x.rows()!=0 && x.cols()!=0 )
x(randominteger(x.rows()),randominteger(x.cols())) = fp_nan;
}
template
void spoil_matrix_by_posinf(T &x)
{
if( x.rows()!=0 && x.cols()!=0 )
x(randominteger(x.rows()),randominteger(x.cols())) = fp_posinf;
}
template
void spoil_matrix_by_neginf(T &x)
{
if( x.rows()!=0 && x.cols()!=0 )
x(randominteger(x.rows()),randominteger(x.cols())) = fp_neginf;
}
void function1_func(const real_1d_array &x, double &func, void *ptr)
{
//
// this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4
//
func = 100*pow(x[0]+3,4) + pow(x[1]-3,4);
}
void function1_grad(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr)
{
//
// this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4
// and its derivatives df/d0 and df/dx1
//
func = 100*pow(x[0]+3,4) + pow(x[1]-3,4);
grad[0] = 400*pow(x[0]+3,3);
grad[1] = 4*pow(x[1]-3,3);
}
void function1_hess(const real_1d_array &x, double &func, real_1d_array &grad, real_2d_array &hess, void *ptr)
{
//
// this callback calculates f(x0,x1) = 100*(x0+3)^4 + (x1-3)^4
// its derivatives df/d0 and df/dx1
// and its Hessian.
//
func = 100*pow(x[0]+3,4) + pow(x[1]-3,4);
grad[0] = 400*pow(x[0]+3,3);
grad[1] = 4*pow(x[1]-3,3);
hess[0][0] = 1200*pow(x[0]+3,2);
hess[0][1] = 0;
hess[1][0] = 0;
hess[1][1] = 12*pow(x[1]-3,2);
}
void function1_fvec(const real_1d_array &x, real_1d_array &fi, void *ptr)
{
//
// this callback calculates
// f0(x0,x1) = 100*(x0+3)^4,
// f1(x0,x1) = (x1-3)^4
//
fi[0] = 10*pow(x[0]+3,2);
fi[1] = pow(x[1]-3,2);
}
void function1_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr)
{
//
// this callback calculates
// f0(x0,x1) = 100*(x0+3)^4,
// f1(x0,x1) = (x1-3)^4
// and Jacobian matrix J = [dfi/dxj]
//
fi[0] = 10*pow(x[0]+3,2);
fi[1] = pow(x[1]-3,2);
jac[0][0] = 20*(x[0]+3);
jac[0][1] = 0;
jac[1][0] = 0;
jac[1][1] = 2*(x[1]-3);
}
void function2_func(const real_1d_array &x, double &func, void *ptr)
{
//
// this callback calculates f(x0,x1) = (x0^2+1)^2 + (x1-1)^2
//
func = pow(x[0]*x[0]+1,2) + pow(x[1]-1,2);
}
void function2_grad(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr)
{
//
// this callback calculates f(x0,x1) = (x0^2+1)^2 + (x1-1)^2
// and its derivatives df/d0 and df/dx1
//
func = pow(x[0]*x[0]+1,2) + pow(x[1]-1,2);
grad[0] = 4*(x[0]*x[0]+1)*x[0];
grad[1] = 2*(x[1]-1);
}
void function2_hess(const real_1d_array &x, double &func, real_1d_array &grad, real_2d_array &hess, void *ptr)
{
//
// this callback calculates f(x0,x1) = (x0^2+1)^2 + (x1-1)^2
// its gradient and Hessian
//
func = pow(x[0]*x[0]+1,2) + pow(x[1]-1,2);
grad[0] = 4*(x[0]*x[0]+1)*x[0];
grad[1] = 2*(x[1]-1);
hess[0][0] = 12*x[0]*x[0]+4;
hess[0][1] = 0;
hess[1][0] = 0;
hess[1][1] = 2;
}
void function2_fvec(const real_1d_array &x, real_1d_array &fi, void *ptr)
{
//
// this callback calculates
// f0(x0,x1) = x0^2+1
// f1(x0,x1) = x1-1
//
fi[0] = x[0]*x[0]+1;
fi[1] = x[1]-1;
}
void function2_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr)
{
//
// this callback calculates
// f0(x0,x1) = x0^2+1
// f1(x0,x1) = x1-1
// and Jacobian matrix J = [dfi/dxj]
//
fi[0] = x[0]*x[0]+1;
fi[1] = x[1]-1;
jac[0][0] = 2*x[0];
jac[0][1] = 0;
jac[1][0] = 0;
jac[1][1] = 1;
}
void nlcfunc1_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr)
{
//
// this callback calculates
//
// f0(x0,x1) = -x0+x1
// f1(x0,x1) = x0^2+x1^2-1
//
// and Jacobian matrix J = [dfi/dxj]
//
fi[0] = -x[0]+x[1];
fi[1] = x[0]*x[0] + x[1]*x[1] - 1.0;
jac[0][0] = -1.0;
jac[0][1] = +1.0;
jac[1][0] = 2*x[0];
jac[1][1] = 2*x[1];
}
void nlcfunc2_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr)
{
//
// this callback calculates
//
// f0(x0,x1,x2) = x0+x1
// f1(x0,x1,x2) = x2-exp(x0)
// f2(x0,x1,x2) = x0^2+x1^2-1
//
// and Jacobian matrix J = [dfi/dxj]
//
fi[0] = x[0]+x[1];
fi[1] = x[2]-exp(x[0]);
fi[2] = x[0]*x[0] + x[1]*x[1] - 1.0;
jac[0][0] = 1.0;
jac[0][1] = 1.0;
jac[0][2] = 0.0;
jac[1][0] = -exp(x[0]);
jac[1][1] = 0.0;
jac[1][2] = 1.0;
jac[2][0] = 2*x[0];
jac[2][1] = 2*x[1];
jac[2][2] = 0.0;
}
void nsfunc1_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr)
{
//
// this callback calculates
//
// f0(x0,x1) = 2*|x0|+x1
//
// and Jacobian matrix J = [df0/dx0 df0/dx1]
//
fi[0] = 2*fabs(double(x[0]))+fabs(double(x[1]));
jac[0][0] = 2*alglib::sign(x[0]);
jac[0][1] = alglib::sign(x[1]);
}
void nsfunc1_fvec(const real_1d_array &x, real_1d_array &fi, void *ptr)
{
//
// this callback calculates
//
// f0(x0,x1) = 2*|x0|+x1
//
fi[0] = 2*fabs(double(x[0]))+fabs(double(x[1]));
}
void nsfunc2_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr)
{
//
// this callback calculates function vector
//
// f0(x0,x1) = 2*|x0|+x1
// f1(x0,x1) = x0-1
// f2(x0,x1) = -x1-1
//
// and Jacobian matrix J
//
// [ df0/dx0 df0/dx1 ]
// J = [ df1/dx0 df1/dx1 ]
// [ df2/dx0 df2/dx1 ]
//
fi[0] = 2*fabs(double(x[0]))+fabs(double(x[1]));
jac[0][0] = 2*alglib::sign(x[0]);
jac[0][1] = alglib::sign(x[1]);
fi[1] = x[0]-1;
jac[1][0] = 1;
jac[1][1] = 0;
fi[2] = -x[1]-1;
jac[2][0] = 0;
jac[2][1] = -1;
}
void bad_func(const real_1d_array &x, double &func, void *ptr)
{
//
// this callback calculates 'bad' function,
// i.e. function with incorrectly calculated derivatives
//
func = 100*pow(x[0]+3,4) + pow(x[1]-3,4);
}
void bad_grad(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr)
{
//
// this callback calculates 'bad' function,
// i.e. function with incorrectly calculated derivatives
//
func = 100*pow(x[0]+3,4) + pow(x[1]-3,4);
grad[0] = 40*pow(x[0]+3,3);
grad[1] = 40*pow(x[1]-3,3);
}
void bad_hess(const real_1d_array &x, double &func, real_1d_array &grad, real_2d_array &hess, void *ptr)
{
//
// this callback calculates 'bad' function,
// i.e. function with incorrectly calculated derivatives
//
func = 100*pow(x[0]+3,4) + pow(x[1]-3,4);
grad[0] = 40*pow(x[0]+3,3);
grad[1] = 40*pow(x[1]-3,3);
hess[0][0] = 120*pow(x[0]+3,2);
hess[0][1] = 0;
hess[1][0] = 0;
hess[1][1] = 120*pow(x[1]-3,2);
}
void bad_fvec(const real_1d_array &x, real_1d_array &fi, void *ptr)
{
//
// this callback calculates 'bad' function,
// i.e. function with incorrectly calculated derivatives
//
fi[0] = 10*pow(x[0]+3,2);
fi[1] = pow(x[1]-3,2);
}
void bad_jac(const real_1d_array &x, real_1d_array &fi, real_2d_array &jac, void *ptr)
{
//
// this callback calculates 'bad' function,
// i.e. function with incorrectly calculated derivatives
//
fi[0] = 10*pow(x[0]+3,2);
fi[1] = pow(x[1]-3,2);
jac[0][0] = 2*(x[0]+3);
jac[0][1] = 1;
jac[1][0] = 0;
jac[1][1] = 20*(x[1]-3);
}
void function_cx_1_func(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr)
{
// this callback calculates f(c,x)=exp(-c0*sqr(x0))
// where x is a position on X-axis and c is adjustable parameter
func = exp(-c[0]*pow(x[0],2));
}
void function_cx_1_grad(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, void *ptr)
{
// this callback calculates f(c,x)=exp(-c0*sqr(x0)) and gradient G={df/dc[i]}
// where x is a position on X-axis and c is adjustable parameter.
// IMPORTANT: gradient is calculated with respect to C, not to X
func = exp(-c[0]*pow(x[0],2));
grad[0] = -pow(x[0],2)*func;
}
void function_cx_1_hess(const real_1d_array &c, const real_1d_array &x, double &func, real_1d_array &grad, real_2d_array &hess, void *ptr)
{
// this callback calculates f(c,x)=exp(-c0*sqr(x0)), gradient G={df/dc[i]} and Hessian H={d2f/(dc[i]*dc[j])}
// where x is a position on X-axis and c is adjustable parameter.
// IMPORTANT: gradient/Hessian are calculated with respect to C, not to X
func = exp(-c[0]*pow(x[0],2));
grad[0] = -pow(x[0],2)*func;
hess[0][0] = pow(x[0],4)*func;
}
void ode_function_1_diff(const real_1d_array &y, double x, real_1d_array &dy, void *ptr)
{
// this callback calculates f(y[],x)=-y[0]
dy[0] = -y[0];
}
void int_function_1_func(double x, double xminusa, double bminusx, double &y, void *ptr)
{
// this callback calculates f(x)=exp(x)
y = exp(x);
}
void function_debt_func(const real_1d_array &c, const real_1d_array &x, double &func, void *ptr)
{
//
// this callback calculates f(c,x)=c[0]*(1+c[1]*(pow(x[0]-1999,c[2])-1))
//
func = c[0]*(1+c[1]*(pow(x[0]-1999,c[2])-1));
}
void s1_grad(const real_1d_array &x, double &func, real_1d_array &grad, void *ptr)
{
//
// this callback calculates f(x) = (1+x)^(-0.2) + (1-x)^(-0.3) + 1000*x and its gradient.
//
// function is trimmed when we calculate it near the singular points or outside of the [-1,+1].
// Note that we do NOT calculate gradient in this case.
//
if( (x[0]<=-0.999999999999) || (x[0]>=+0.999999999999) )
{
func = 1.0E+300;
return;
}
func = pow(1+x[0],-0.2) + pow(1-x[0],-0.3) + 1000*x[0];
grad[0] = -0.2*pow(1+x[0],-1.2) +0.3*pow(1-x[0],-1.3) + 1000;
}
int main()
{
bool _TotalResult = true;
bool _TestResult;
int _spoil_scenario;
printf("C++ tests. Please wait...\n");
#if AE_MALLOC==AE_BASIC_STATIC_MALLOC
const ae_int_t _static_pool_size = 1000000;
ae_int_t _static_pool_used = 0, _static_pool_free = 0;
void *_static_pool = malloc(_static_pool_size);
alglib_impl::set_memory_pool(_static_pool, _static_pool_size);
alglib_impl::memory_pool_stats(&_static_pool_used, &_static_pool_free);
if( _static_pool_used!=0 || _static_pool_free<0.95*_static_pool_size || _static_pool_free>_static_pool_size )
{
_TotalResult = false;
printf("FAILURE: memory pool usage stats are inconsistent!\n");
return 1;
}
{
alglib::real_2d_array a("[[1,2],[3,4]]");
ae_int_t _static_pool_used2 = 0, _static_pool_free2 = 0;
alglib_impl::memory_pool_stats(&_static_pool_used2, &_static_pool_free2);
if( _static_pool_used2<=_static_pool_used ||
_static_pool_free2>=_static_pool_free ||
_static_pool_used+_static_pool_free!=_static_pool_used2+_static_pool_free2 )
{
_TotalResult = false;
printf("FAILURE: memory pool usage stats are inconsistent!\n");
return 1;
}
a.setlength(1,1); // make sure that destructor of /a/ is never called prior to this point
}
#endif
#ifdef AE_USE_ALLOC_COUNTER
printf("Allocation counter activated...\n");
alglib_impl::_use_alloc_counter = ae_true;
if( alglib_impl::_alloc_counter!=0 )
{
_TotalResult = false;
printf("FAILURE: alloc_counter is non-zero on start!\n");
}
{
{
alglib::real_1d_array x;
x.setlength(1);
if( alglib_impl::_alloc_counter==0 )
printf(":::: WARNING: ALLOC_COUNTER IS INACTIVE!!! :::::\n");
}
if( alglib_impl::_alloc_counter!=0 )
{
printf("FAILURE: alloc_counter does not decrease!\n");
return 1;
}
}
#endif
try
{
//
// TEST nneighbor_d_1
// Nearest neighbor search, KNN queries
//
printf("0/151\n");
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
real_2d_array a = "[[0,0],[0,1],[1,0],[1,1]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(a);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(a);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(a);
ae_int_t nx = 2;
ae_int_t ny = 0;
ae_int_t normtype = 2;
kdtree kdt;
real_1d_array x;
real_2d_array r = "[[]]";
ae_int_t k;
kdtreebuild(a, nx, ny, normtype, kdt);
x = "[-1,0]";
k = kdtreequeryknn(kdt, x, 1);
_TestResult = _TestResult && doc_test_int(k, 1);
kdtreequeryresultsx(kdt, r);
_TestResult = _TestResult && doc_test_real_matrix(r, "[[0,0]]", 0.05);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "nneighbor_d_1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST nneighbor_t_2
// Subsequent queries; buffered functions must use previously allocated storage (if large enough), so buffer may contain some info from previous call
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
real_2d_array a = "[[0,0],[0,1],[1,0],[1,1]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(a);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(a);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(a);
ae_int_t nx = 2;
ae_int_t ny = 0;
ae_int_t normtype = 2;
kdtree kdt;
real_1d_array x;
real_2d_array rx = "[[]]";
ae_int_t k;
kdtreebuild(a, nx, ny, normtype, kdt);
x = "[+2,0]";
k = kdtreequeryknn(kdt, x, 2, true);
_TestResult = _TestResult && doc_test_int(k, 2);
kdtreequeryresultsx(kdt, rx);
_TestResult = _TestResult && doc_test_real_matrix(rx, "[[1,0],[1,1]]", 0.05);
x = "[-2,0]";
k = kdtreequeryknn(kdt, x, 1, true);
_TestResult = _TestResult && doc_test_int(k, 1);
kdtreequeryresultsx(kdt, rx);
_TestResult = _TestResult && doc_test_real_matrix(rx, "[[0,0],[1,1]]", 0.05);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "nneighbor_t_2");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST nneighbor_d_2
// Serialization of KD-trees
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
real_2d_array a = "[[0,0],[0,1],[1,0],[1,1]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(a);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(a);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(a);
ae_int_t nx = 2;
ae_int_t ny = 0;
ae_int_t normtype = 2;
kdtree kdt0;
kdtree kdt1;
std::string s;
real_1d_array x;
real_2d_array r0 = "[[]]";
real_2d_array r1 = "[[]]";
//
// Build tree and serialize it
//
kdtreebuild(a, nx, ny, normtype, kdt0);
alglib::kdtreeserialize(kdt0, s);
alglib::kdtreeunserialize(s, kdt1);
//
// Compare results from KNN queries
//
x = "[-1,0]";
kdtreequeryknn(kdt0, x, 1);
kdtreequeryresultsx(kdt0, r0);
kdtreequeryknn(kdt1, x, 1);
kdtreequeryresultsx(kdt1, r1);
_TestResult = _TestResult && doc_test_real_matrix(r0, "[[0,0]]", 0.05);
_TestResult = _TestResult && doc_test_real_matrix(r1, "[[0,0]]", 0.05);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "nneighbor_d_2");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST odesolver_d1
// Solving y'=-y with ODE solver
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<13; _spoil_scenario++)
{
try
{
real_1d_array y = "[1]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(y);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(y);
real_1d_array x = "[0, 1, 2, 3]";
if( _spoil_scenario==4 )
spoil_vector_by_nan(x);
if( _spoil_scenario==5 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==6 )
spoil_vector_by_neginf(x);
double eps = 0.00001;
if( _spoil_scenario==7 )
eps = fp_nan;
if( _spoil_scenario==8 )
eps = fp_posinf;
if( _spoil_scenario==9 )
eps = fp_neginf;
double h = 0;
if( _spoil_scenario==10 )
h = fp_nan;
if( _spoil_scenario==11 )
h = fp_posinf;
if( _spoil_scenario==12 )
h = fp_neginf;
odesolverstate s;
ae_int_t m;
real_1d_array xtbl;
real_2d_array ytbl;
odesolverreport rep;
odesolverrkck(y, x, eps, h, s);
alglib::odesolversolve(s, ode_function_1_diff);
odesolverresults(s, m, xtbl, ytbl, rep);
_TestResult = _TestResult && doc_test_int(m, 4);
_TestResult = _TestResult && doc_test_real_vector(xtbl, "[0, 1, 2, 3]", 0.005);
_TestResult = _TestResult && doc_test_real_matrix(ytbl, "[[1], [0.367], [0.135], [0.050]]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "odesolver_d1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST sparse_d_1
// Basic operations with sparse matrices
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<1; _spoil_scenario++)
{
try
{
//
// This example demonstrates creation/initialization of the sparse matrix
// and matrix-vector multiplication.
//
// First, we have to create matrix and initialize it. Matrix is initially created
// in the Hash-Table format, which allows convenient initialization. We can modify
// Hash-Table matrix with sparseset() and sparseadd() functions.
//
// NOTE: Unlike CRS format, Hash-Table representation allows you to initialize
// elements in the arbitrary order. You may see that we initialize a[0][0] first,
// then move to the second row, and then move back to the first row.
//
sparsematrix s;
sparsecreate(2, 2, s);
sparseset(s, 0, 0, 2.0);
sparseset(s, 1, 1, 1.0);
sparseset(s, 0, 1, 1.0);
sparseadd(s, 1, 1, 4.0);
//
// Now S is equal to
// [ 2 1 ]
// [ 5 ]
// Lets check it by reading matrix contents with sparseget().
// You may see that with sparseget() you may read both non-zero
// and zero elements.
//
double v;
v = sparseget(s, 0, 0);
_TestResult = _TestResult && doc_test_real(v, 2.0000, 0.005);
v = sparseget(s, 0, 1);
_TestResult = _TestResult && doc_test_real(v, 1.0000, 0.005);
v = sparseget(s, 1, 0);
_TestResult = _TestResult && doc_test_real(v, 0.0000, 0.005);
v = sparseget(s, 1, 1);
_TestResult = _TestResult && doc_test_real(v, 5.0000, 0.005);
//
// After successful creation we can use our matrix for linear operations.
//
// However, there is one more thing we MUST do before using S in linear
// operations: we have to convert it from HashTable representation (used for
// initialization and dynamic operations) to CRS format with sparseconverttocrs()
// call. If you omit this call, ALGLIB will generate exception on the first
// attempt to use S in linear operations.
//
sparseconverttocrs(s);
//
// Now S is in the CRS format and we are ready to do linear operations.
// Lets calculate A*x for some x.
//
real_1d_array x = "[1,-1]";
if( _spoil_scenario==0 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[]";
sparsemv(s, x, y);
_TestResult = _TestResult && doc_test_real_vector(y, "[1.000,-5.000]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "sparse_d_1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST sparse_d_crs
// Advanced topic: creation in the CRS format.
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<2; _spoil_scenario++)
{
try
{
//
// This example demonstrates creation/initialization of the sparse matrix in the
// CRS format.
//
// Hash-Table format used by default is very convenient (it allows easy
// insertion of elements, automatic memory reallocation), but has
// significant memory and performance overhead. Insertion of one element
// costs hundreds of CPU cycles, and memory consumption is several times
// higher than that of CRS.
//
// When you work with really large matrices and when you can tell in
// advance how many elements EXACTLY you need, it can be beneficial to
// create matrix in the CRS format from the very beginning.
//
// If you want to create matrix in the CRS format, you should:
// * use sparsecreatecrs() function
// * know row sizes in advance (number of non-zero entries in the each row)
// * initialize matrix with sparseset() - another function, sparseadd(), is not allowed
// * initialize elements from left to right, from top to bottom, each
// element is initialized only once.
//
sparsematrix s;
integer_1d_array row_sizes = "[2,2,2,1]";
if( _spoil_scenario==0 )
spoil_vector_by_deleting_element(row_sizes);
sparsecreatecrs(4, 4, row_sizes, s);
sparseset(s, 0, 0, 2.0);
sparseset(s, 0, 1, 1.0);
sparseset(s, 1, 1, 4.0);
sparseset(s, 1, 2, 2.0);
sparseset(s, 2, 2, 3.0);
sparseset(s, 2, 3, 1.0);
sparseset(s, 3, 3, 9.0);
//
// Now S is equal to
// [ 2 1 ]
// [ 4 2 ]
// [ 3 1 ]
// [ 9 ]
//
// We should point that we have initialized S elements from left to right,
// from top to bottom. CRS representation does NOT allow you to do so in
// the different order. Try to change order of the sparseset() calls above,
// and you will see that your program generates exception.
//
// We can check it by reading matrix contents with sparseget().
// However, you should remember that sparseget() is inefficient on
// CRS matrices (it may have to pass through all elements of the row
// until it finds element you need).
//
double v;
v = sparseget(s, 0, 0);
_TestResult = _TestResult && doc_test_real(v, 2.0000, 0.005);
v = sparseget(s, 2, 3);
_TestResult = _TestResult && doc_test_real(v, 1.0000, 0.005);
// you may see that you can read zero elements (which are not stored) with sparseget()
v = sparseget(s, 3, 2);
_TestResult = _TestResult && doc_test_real(v, 0.0000, 0.005);
//
// After successful creation we can use our matrix for linear operations.
// Lets calculate A*x for some x.
//
real_1d_array x = "[1,-1,1,-1]";
if( _spoil_scenario==1 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[]";
sparsemv(s, x, y);
_TestResult = _TestResult && doc_test_real_vector(y, "[1.000,-2.000,2.000,-9]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "sparse_d_crs");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST ablas_d_gemm
// Matrix multiplication (single-threaded)
//
_TestResult = true;
try
{
real_2d_array a = "[[2,1],[1,3]]";
real_2d_array b = "[[2,1],[0,1]]";
real_2d_array c = "[[0,0],[0,0]]";
//
// rmatrixgemm() function allows us to calculate matrix product C:=A*B or
// to perform more general operation, C:=alpha*op1(A)*op2(B)+beta*C,
// where A, B, C are rectangular matrices, op(X) can be X or X^T,
// alpha and beta are scalars.
//
// This function:
// * can apply transposition and/or multiplication by scalar to operands
// * can use arbitrary part of matrices A/B (given by submatrix offset)
// * can store result into arbitrary part of C
// * for performance reasons requires C to be preallocated
//
// Parameters of this function are:
// * M, N, K - sizes of op1(A) (which is MxK), op2(B) (which
// is KxN) and C (which is MxN)
// * Alpha - coefficient before A*B
// * A, IA, JA - matrix A and offset of the submatrix
// * OpTypeA - transformation type:
// 0 - no transformation
// 1 - transposition
// * B, IB, JB - matrix B and offset of the submatrix
// * OpTypeB - transformation type:
// 0 - no transformation
// 1 - transposition
// * Beta - coefficient before C
// * C, IC, JC - preallocated matrix C and offset of the submatrix
//
// Below we perform simple product C:=A*B (alpha=1, beta=0)
//
// IMPORTANT: this function works with preallocated C, which must be large
// enough to store multiplication result.
//
ae_int_t m = 2;
ae_int_t n = 2;
ae_int_t k = 2;
double alpha = 1.0;
ae_int_t ia = 0;
ae_int_t ja = 0;
ae_int_t optypea = 0;
ae_int_t ib = 0;
ae_int_t jb = 0;
ae_int_t optypeb = 0;
double beta = 0.0;
ae_int_t ic = 0;
ae_int_t jc = 0;
rmatrixgemm(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc);
_TestResult = _TestResult && doc_test_real_matrix(c, "[[4,3],[2,4]]", 0.0001);
//
// Now we try to apply some simple transformation to operands: C:=A*B^T
//
optypeb = 1;
rmatrixgemm(m, n, k, alpha, a, ia, ja, optypea, b, ib, jb, optypeb, beta, c, ic, jc);
_TestResult = _TestResult && doc_test_real_matrix(c, "[[5,1],[5,3]]", 0.0001);
}
catch(ap_error)
{ _TestResult = false; }
if( !_TestResult)
{
printf("%-32s FAILED\n", "ablas_d_gemm");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST ablas_d_syrk
// Symmetric rank-K update (single-threaded)
//
_TestResult = true;
try
{
//
// rmatrixsyrk() function allows us to calculate symmetric rank-K update
// C := beta*C + alpha*A'*A, where C is square N*N matrix, A is square K*N
// matrix, alpha and beta are scalars. It is also possible to update by
// adding A*A' instead of A'*A.
//
// Parameters of this function are:
// * N, K - matrix size
// * Alpha - coefficient before A
// * A, IA, JA - matrix and submatrix offsets
// * OpTypeA - multiplication type:
// * 0 - A*A^T is calculated
// * 2 - A^T*A is calculated
// * Beta - coefficient before C
// * C, IC, JC - preallocated input/output matrix and submatrix offsets
// * IsUpper - whether upper or lower triangle of C is updated;
// this function updates only one half of C, leaving
// other half unchanged (not referenced at all).
//
// Below we will show how to calculate simple product C:=A'*A
//
// NOTE: beta=0 and we do not use previous value of C, but still it
// MUST be preallocated.
//
ae_int_t n = 2;
ae_int_t k = 1;
double alpha = 1.0;
ae_int_t ia = 0;
ae_int_t ja = 0;
ae_int_t optypea = 2;
double beta = 0.0;
ae_int_t ic = 0;
ae_int_t jc = 0;
bool isupper = true;
real_2d_array a = "[[1,2]]";
// preallocate space to store result
real_2d_array c = "[[0,0],[0,0]]";
// calculate product, store result into upper part of c
rmatrixsyrk(n, k, alpha, a, ia, ja, optypea, beta, c, ic, jc, isupper);
// output result.
// IMPORTANT: lower triangle of C was NOT updated!
_TestResult = _TestResult && doc_test_real_matrix(c, "[[1,2],[0,4]]", 0.0001);
}
catch(ap_error)
{ _TestResult = false; }
if( !_TestResult)
{
printf("%-32s FAILED\n", "ablas_d_syrk");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST ablas_t_complex
// Basis test for complex matrix functions (correctness and presence of SMP support)
//
_TestResult = true;
try
{
complex_2d_array a;
complex_2d_array b;
complex_2d_array c;
// test cmatrixgemm()
a = "[[2i,1i],[1,3]]";
b = "[[2,1],[0,1]]";
c = "[[0,0],[0,0]]";
cmatrixgemm(2, 2, 2, 1.0, a, 0, 0, 0, b, 0, 0, 0, 0.0, c, 0, 0);
_TestResult = _TestResult && doc_test_complex_matrix(c, "[[4i,3i],[2,4]]", 0.0001);
}
catch(ap_error)
{ _TestResult = false; }
if( !_TestResult)
{
printf("%-32s FAILED\n", "ablas_t_complex");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST matinv_d_r1
// Real matrix inverse
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<7; _spoil_scenario++)
{
try
{
real_2d_array a = "[[1,-1],[1,1]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(a);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(a);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(a);
if( _spoil_scenario==3 )
spoil_matrix_by_adding_row(a);
if( _spoil_scenario==4 )
spoil_matrix_by_adding_col(a);
if( _spoil_scenario==5 )
spoil_matrix_by_deleting_row(a);
if( _spoil_scenario==6 )
spoil_matrix_by_deleting_col(a);
ae_int_t info;
matinvreport rep;
rmatrixinverse(a, info, rep);
_TestResult = _TestResult && doc_test_int(info, 1);
_TestResult = _TestResult && doc_test_real_matrix(a, "[[0.5,0.5],[-0.5,0.5]]", 0.00005);
_TestResult = _TestResult && doc_test_real(rep.r1, 0.5, 0.00005);
_TestResult = _TestResult && doc_test_real(rep.rinf, 0.5, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "matinv_d_r1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST matinv_d_c1
// Complex matrix inverse
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<7; _spoil_scenario++)
{
try
{
complex_2d_array a = "[[1i,-1],[1i,1]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(a);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(a);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(a);
if( _spoil_scenario==3 )
spoil_matrix_by_adding_row(a);
if( _spoil_scenario==4 )
spoil_matrix_by_adding_col(a);
if( _spoil_scenario==5 )
spoil_matrix_by_deleting_row(a);
if( _spoil_scenario==6 )
spoil_matrix_by_deleting_col(a);
ae_int_t info;
matinvreport rep;
cmatrixinverse(a, info, rep);
_TestResult = _TestResult && doc_test_int(info, 1);
_TestResult = _TestResult && doc_test_complex_matrix(a, "[[-0.5i,-0.5i],[-0.5,0.5]]", 0.00005);
_TestResult = _TestResult && doc_test_real(rep.r1, 0.5, 0.00005);
_TestResult = _TestResult && doc_test_real(rep.rinf, 0.5, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "matinv_d_c1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST matinv_d_spd1
// SPD matrix inverse
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<7; _spoil_scenario++)
{
try
{
real_2d_array a = "[[2,1],[1,2]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(a);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(a);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(a);
if( _spoil_scenario==3 )
spoil_matrix_by_adding_row(a);
if( _spoil_scenario==4 )
spoil_matrix_by_adding_col(a);
if( _spoil_scenario==5 )
spoil_matrix_by_deleting_row(a);
if( _spoil_scenario==6 )
spoil_matrix_by_deleting_col(a);
ae_int_t info;
matinvreport rep;
spdmatrixinverse(a, info, rep);
_TestResult = _TestResult && doc_test_int(info, 1);
_TestResult = _TestResult && doc_test_real_matrix(a, "[[0.666666,-0.333333],[-0.333333,0.666666]]", 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "matinv_d_spd1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST matinv_d_hpd1
// HPD matrix inverse
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<7; _spoil_scenario++)
{
try
{
complex_2d_array a = "[[2,1],[1,2]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(a);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(a);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(a);
if( _spoil_scenario==3 )
spoil_matrix_by_adding_row(a);
if( _spoil_scenario==4 )
spoil_matrix_by_adding_col(a);
if( _spoil_scenario==5 )
spoil_matrix_by_deleting_row(a);
if( _spoil_scenario==6 )
spoil_matrix_by_deleting_col(a);
ae_int_t info;
matinvreport rep;
hpdmatrixinverse(a, info, rep);
_TestResult = _TestResult && doc_test_int(info, 1);
_TestResult = _TestResult && doc_test_complex_matrix(a, "[[0.666666,-0.333333],[-0.333333,0.666666]]", 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "matinv_d_hpd1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST matinv_t_r1
// Real matrix inverse: singular matrix
//
_TestResult = true;
try
{
real_2d_array a = "[[1,-1],[-2,2]]";
ae_int_t info;
matinvreport rep;
rmatrixinverse(a, info, rep);
_TestResult = _TestResult && doc_test_int(info, -3);
_TestResult = _TestResult && doc_test_real(rep.r1, 0.0, 0.00005);
_TestResult = _TestResult && doc_test_real(rep.rinf, 0.0, 0.00005);
}
catch(ap_error)
{ _TestResult = false; }
if( !_TestResult)
{
printf("%-32s FAILED\n", "matinv_t_r1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST matinv_t_c1
// Complex matrix inverse: singular matrix
//
_TestResult = true;
try
{
complex_2d_array a = "[[1i,-1i],[-2,2]]";
ae_int_t info;
matinvreport rep;
cmatrixinverse(a, info, rep);
_TestResult = _TestResult && doc_test_int(info, -3);
_TestResult = _TestResult && doc_test_real(rep.r1, 0.0, 0.00005);
_TestResult = _TestResult && doc_test_real(rep.rinf, 0.0, 0.00005);
}
catch(ap_error)
{ _TestResult = false; }
if( !_TestResult)
{
printf("%-32s FAILED\n", "matinv_t_c1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST matinv_e_spd1
// Attempt to use SPD function on nonsymmetrix matrix
//
_TestResult = true;
try
{
real_2d_array a = "[[1,0],[1,1]]";
ae_int_t info;
matinvreport rep;
spdmatrixinverse(a, info, rep);
_TestResult = false;
}
catch(ap_error)
{}
if( !_TestResult)
{
printf("%-32s FAILED\n", "matinv_e_spd1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST matinv_e_hpd1
// Attempt to use SPD function on nonsymmetrix matrix
//
_TestResult = true;
try
{
complex_2d_array a = "[[1,0],[1,1]]";
ae_int_t info;
matinvreport rep;
hpdmatrixinverse(a, info, rep);
_TestResult = false;
}
catch(ap_error)
{}
if( !_TestResult)
{
printf("%-32s FAILED\n", "matinv_e_hpd1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minlbfgs_d_1
// Nonlinear optimization by L-BFGS
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<15; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of
//
// f(x,y) = 100*(x+3)^4+(y-3)^4
//
// using LBFGS method, with:
// * initial point x=[0,0]
// * unit scale being set for all variables (see minlbfgssetscale for more info)
// * stopping criteria set to "terminate after short enough step"
// * OptGuard integrity check being used to check problem statement
// for some common errors like nonsmoothness or bad analytic gradient
//
// First, we create optimizer object and tune its properties
//
real_1d_array x = "[0,0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
real_1d_array s = "[1,1]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(s);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(s);
double epsg = 0;
if( _spoil_scenario==6 )
epsg = fp_nan;
if( _spoil_scenario==7 )
epsg = fp_posinf;
if( _spoil_scenario==8 )
epsg = fp_neginf;
double epsf = 0;
if( _spoil_scenario==9 )
epsf = fp_nan;
if( _spoil_scenario==10 )
epsf = fp_posinf;
if( _spoil_scenario==11 )
epsf = fp_neginf;
double epsx = 0.0000000001;
if( _spoil_scenario==12 )
epsx = fp_nan;
if( _spoil_scenario==13 )
epsx = fp_posinf;
if( _spoil_scenario==14 )
epsx = fp_neginf;
ae_int_t maxits = 0;
minlbfgsstate state;
minlbfgscreate(1, x, state);
minlbfgssetcond(state, epsg, epsf, epsx, maxits);
minlbfgssetscale(state, s);
//
// Activate OptGuard integrity checking.
//
// OptGuard monitor helps to catch common coding and problem statement
// issues, like:
// * discontinuity of the target function (C0 continuity violation)
// * nonsmoothness of the target function (C1 continuity violation)
// * erroneous analytic gradient, i.e. one inconsistent with actual
// change in the target/constraints
//
// OptGuard is essential for early prototyping stages because such
// problems often result in premature termination of the optimizer
// which is really hard to distinguish from the correct termination.
//
// IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL
// DIFFERENTIATION. DO NOT USE IT IN PRODUCTION CODE!!!!!!!
//
// Other OptGuard checks add moderate overhead, but anyway
// it is better to turn them off when they are not needed.
//
minlbfgsoptguardsmoothness(state);
minlbfgsoptguardgradient(state, 0.001);
//
// Optimize and examine results.
//
minlbfgsreport rep;
alglib::minlbfgsoptimize(state, function1_grad);
minlbfgsresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[-3,3]", 0.005);
//
// Check that OptGuard did not report errors
//
// NOTE: want to test OptGuard? Try breaking the gradient - say, add
// 1.0 to some of its components.
//
optguardreport ogrep;
minlbfgsoptguardresults(state, ogrep);
_TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minlbfgs_d_1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minlbfgs_d_2
// Nonlinear optimization with additional settings and restarts
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<21; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of f(x,y) = 100*(x+3)^4+(y-3)^4
// using LBFGS method.
//
// Several advanced techniques are demonstrated:
// * upper limit on step size
// * restart from new point
//
real_1d_array x = "[0,0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
real_1d_array s = "[1,1]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(s);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(s);
double epsg = 0;
if( _spoil_scenario==6 )
epsg = fp_nan;
if( _spoil_scenario==7 )
epsg = fp_posinf;
if( _spoil_scenario==8 )
epsg = fp_neginf;
double epsf = 0;
if( _spoil_scenario==9 )
epsf = fp_nan;
if( _spoil_scenario==10 )
epsf = fp_posinf;
if( _spoil_scenario==11 )
epsf = fp_neginf;
double epsx = 0.0000000001;
if( _spoil_scenario==12 )
epsx = fp_nan;
if( _spoil_scenario==13 )
epsx = fp_posinf;
if( _spoil_scenario==14 )
epsx = fp_neginf;
double stpmax = 0.1;
if( _spoil_scenario==15 )
stpmax = fp_nan;
if( _spoil_scenario==16 )
stpmax = fp_posinf;
if( _spoil_scenario==17 )
stpmax = fp_neginf;
ae_int_t maxits = 0;
minlbfgsstate state;
minlbfgsreport rep;
// create and tune optimizer
minlbfgscreate(1, x, state);
minlbfgssetcond(state, epsg, epsf, epsx, maxits);
minlbfgssetstpmax(state, stpmax);
minlbfgssetscale(state, s);
// Set up OptGuard integrity checker which catches errors
// like nonsmooth targets or errors in the analytic gradient.
//
// OptGuard is essential at the early prototyping stages.
//
// NOTE: gradient verification needs 3*N additional function
// evaluations; DO NOT USE IT IN THE PRODUCTION CODE
// because it leads to unnecessary slowdown of your app.
minlbfgsoptguardsmoothness(state);
minlbfgsoptguardgradient(state, 0.001);
// first run
alglib::minlbfgsoptimize(state, function1_grad);
minlbfgsresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[-3,3]", 0.005);
// second run - algorithm is restarted
x = "[10,10]";
if( _spoil_scenario==18 )
spoil_vector_by_nan(x);
if( _spoil_scenario==19 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==20 )
spoil_vector_by_neginf(x);
minlbfgsrestartfrom(state, x);
alglib::minlbfgsoptimize(state, function1_grad);
minlbfgsresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[-3,3]", 0.005);
// check OptGuard integrity report. Why do we need it at all?
// Well, try breaking the gradient by adding 1.0 to some
// of its components - OptGuard should report it as error.
// And it may also catch unintended errors too :)
optguardreport ogrep;
minlbfgsoptguardresults(state, ogrep);
_TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minlbfgs_d_2");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minlbfgs_numdiff
// Nonlinear optimization by L-BFGS with numerical differentiation
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<15; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of f(x,y) = 100*(x+3)^4+(y-3)^4
// using numerical differentiation to calculate gradient.
//
real_1d_array x = "[0,0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
double epsg = 0.0000000001;
if( _spoil_scenario==3 )
epsg = fp_nan;
if( _spoil_scenario==4 )
epsg = fp_posinf;
if( _spoil_scenario==5 )
epsg = fp_neginf;
double epsf = 0;
if( _spoil_scenario==6 )
epsf = fp_nan;
if( _spoil_scenario==7 )
epsf = fp_posinf;
if( _spoil_scenario==8 )
epsf = fp_neginf;
double epsx = 0;
if( _spoil_scenario==9 )
epsx = fp_nan;
if( _spoil_scenario==10 )
epsx = fp_posinf;
if( _spoil_scenario==11 )
epsx = fp_neginf;
double diffstep = 1.0e-6;
if( _spoil_scenario==12 )
diffstep = fp_nan;
if( _spoil_scenario==13 )
diffstep = fp_posinf;
if( _spoil_scenario==14 )
diffstep = fp_neginf;
ae_int_t maxits = 0;
minlbfgsstate state;
minlbfgsreport rep;
minlbfgscreatef(1, x, diffstep, state);
minlbfgssetcond(state, epsg, epsf, epsx, maxits);
alglib::minlbfgsoptimize(state, function1_func);
minlbfgsresults(state, x, rep);
_TestResult = _TestResult && doc_test_int(rep.terminationtype, 4);
_TestResult = _TestResult && doc_test_real_vector(x, "[-3,3]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minlbfgs_numdiff");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST linlsqr_d_1
// Solution of sparse linear systems with CG
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<4; _spoil_scenario++)
{
try
{
//
// This example illustrates solution of sparse linear least squares problem
// with LSQR algorithm.
//
// Suppose that we have least squares problem min|A*x-b| with sparse A
// represented by sparsematrix object
// [ 1 1 ]
// [ 1 1 ]
// A = [ 2 1 ]
// [ 1 ]
// [ 1 ]
// and right part b
// [ 4 ]
// [ 2 ]
// b = [ 4 ]
// [ 1 ]
// [ 2 ]
// and we want to solve this system in the least squares sense using
// LSQR algorithm. In order to do so, we have to create left part
// (sparsematrix object) and right part (dense array).
//
// Initially, sparse matrix is created in the Hash-Table format,
// which allows easy initialization, but do not allow matrix to be
// used in the linear solvers. So after construction you should convert
// sparse matrix to CRS format (one suited for linear operations).
//
sparsematrix a;
sparsecreate(5, 2, a);
sparseset(a, 0, 0, 1.0);
sparseset(a, 0, 1, 1.0);
sparseset(a, 1, 0, 1.0);
sparseset(a, 1, 1, 1.0);
sparseset(a, 2, 0, 2.0);
sparseset(a, 2, 1, 1.0);
sparseset(a, 3, 0, 1.0);
sparseset(a, 4, 1, 1.0);
//
// Now our matrix is fully initialized, but we have to do one more
// step - convert it from Hash-Table format to CRS format (see
// documentation on sparse matrices for more information about these
// formats).
//
// If you omit this call, ALGLIB will generate exception on the first
// attempt to use A in linear operations.
//
sparseconverttocrs(a);
//
// Initialization of the right part
//
real_1d_array b = "[4,2,4,1,2]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(b);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(b);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(b);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(b);
//
// Now we have to create linear solver object and to use it for the
// solution of the linear system.
//
linlsqrstate s;
linlsqrreport rep;
real_1d_array x;
linlsqrcreate(5, 2, s);
linlsqrsolvesparse(s, a, b);
linlsqrresults(s, x, rep);
_TestResult = _TestResult && doc_test_int(rep.terminationtype, 4);
_TestResult = _TestResult && doc_test_real_vector(x, "[1.000,2.000]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "linlsqr_d_1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minbleic_d_1
// Nonlinear optimization with bound constraints
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<20; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of
//
// f(x,y) = 100*(x+3)^4+(y-3)^4
//
// subject to box constraints
//
// -1<=x<=+1, -1<=y<=+1
//
// using BLEIC optimizer with:
// * initial point x=[0,0]
// * unit scale being set for all variables (see minbleicsetscale for more info)
// * stopping criteria set to "terminate after short enough step"
// * OptGuard integrity check being used to check problem statement
// for some common errors like nonsmoothness or bad analytic gradient
//
// First, we create optimizer object and tune its properties:
// * set box constraints
// * set variable scales
// * set stopping criteria
//
real_1d_array x = "[0,0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
real_1d_array s = "[1,1]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(s);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(s);
if( _spoil_scenario==6 )
spoil_vector_by_deleting_element(s);
real_1d_array bndl = "[-1,-1]";
if( _spoil_scenario==7 )
spoil_vector_by_nan(bndl);
if( _spoil_scenario==8 )
spoil_vector_by_deleting_element(bndl);
real_1d_array bndu = "[+1,+1]";
if( _spoil_scenario==9 )
spoil_vector_by_nan(bndu);
if( _spoil_scenario==10 )
spoil_vector_by_deleting_element(bndu);
double epsg = 0;
if( _spoil_scenario==11 )
epsg = fp_nan;
if( _spoil_scenario==12 )
epsg = fp_posinf;
if( _spoil_scenario==13 )
epsg = fp_neginf;
double epsf = 0;
if( _spoil_scenario==14 )
epsf = fp_nan;
if( _spoil_scenario==15 )
epsf = fp_posinf;
if( _spoil_scenario==16 )
epsf = fp_neginf;
double epsx = 0.000001;
if( _spoil_scenario==17 )
epsx = fp_nan;
if( _spoil_scenario==18 )
epsx = fp_posinf;
if( _spoil_scenario==19 )
epsx = fp_neginf;
ae_int_t maxits = 0;
minbleicstate state;
minbleiccreate(x, state);
minbleicsetbc(state, bndl, bndu);
minbleicsetscale(state, s);
minbleicsetcond(state, epsg, epsf, epsx, maxits);
//
// Then we activate OptGuard integrity checking.
//
// OptGuard monitor helps to catch common coding and problem statement
// issues, like:
// * discontinuity of the target function (C0 continuity violation)
// * nonsmoothness of the target function (C1 continuity violation)
// * erroneous analytic gradient, i.e. one inconsistent with actual
// change in the target/constraints
//
// OptGuard is essential for early prototyping stages because such
// problems often result in premature termination of the optimizer
// which is really hard to distinguish from the correct termination.
//
// IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL
// DIFFERENTIATION. DO NOT USE IT IN PRODUCTION CODE!!!!!!!
//
// Other OptGuard checks add moderate overhead, but anyway
// it is better to turn them off when they are not needed.
//
minbleicoptguardsmoothness(state);
minbleicoptguardgradient(state, 0.001);
//
// Optimize and evaluate results
//
minbleicreport rep;
alglib::minbleicoptimize(state, function1_grad);
minbleicresults(state, x, rep);
_TestResult = _TestResult && doc_test_int(rep.terminationtype, 4);
_TestResult = _TestResult && doc_test_real_vector(x, "[-1,1]", 0.005);
//
// Check that OptGuard did not report errors
//
// NOTE: want to test OptGuard? Try breaking the gradient - say, add
// 1.0 to some of its components.
//
optguardreport ogrep;
minbleicoptguardresults(state, ogrep);
_TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minbleic_d_1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minbleic_d_2
// Nonlinear optimization with linear inequality constraints
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<22; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of
//
// f(x,y) = 100*(x+3)^4+(y-3)^4
//
// subject to inequality constraints
//
// * x>=2 (posed as general linear constraint),
// * x+y>=6
//
// using BLEIC optimizer with
// * initial point x=[0,0]
// * unit scale being set for all variables (see minbleicsetscale for more info)
// * stopping criteria set to "terminate after short enough step"
// * OptGuard integrity check being used to check problem statement
// for some common errors like nonsmoothness or bad analytic gradient
//
// First, we create optimizer object and tune its properties:
// * set linear constraints
// * set variable scales
// * set stopping criteria
//
real_1d_array x = "[5,5]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
real_1d_array s = "[1,1]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(s);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(s);
if( _spoil_scenario==6 )
spoil_vector_by_deleting_element(s);
real_2d_array c = "[[1,0,2],[1,1,6]]";
if( _spoil_scenario==7 )
spoil_matrix_by_nan(c);
if( _spoil_scenario==8 )
spoil_matrix_by_posinf(c);
if( _spoil_scenario==9 )
spoil_matrix_by_neginf(c);
if( _spoil_scenario==10 )
spoil_matrix_by_deleting_row(c);
if( _spoil_scenario==11 )
spoil_matrix_by_deleting_col(c);
integer_1d_array ct = "[1,1]";
if( _spoil_scenario==12 )
spoil_vector_by_deleting_element(ct);
minbleicstate state;
double epsg = 0;
if( _spoil_scenario==13 )
epsg = fp_nan;
if( _spoil_scenario==14 )
epsg = fp_posinf;
if( _spoil_scenario==15 )
epsg = fp_neginf;
double epsf = 0;
if( _spoil_scenario==16 )
epsf = fp_nan;
if( _spoil_scenario==17 )
epsf = fp_posinf;
if( _spoil_scenario==18 )
epsf = fp_neginf;
double epsx = 0.000001;
if( _spoil_scenario==19 )
epsx = fp_nan;
if( _spoil_scenario==20 )
epsx = fp_posinf;
if( _spoil_scenario==21 )
epsx = fp_neginf;
ae_int_t maxits = 0;
minbleiccreate(x, state);
minbleicsetlc(state, c, ct);
minbleicsetscale(state, s);
minbleicsetcond(state, epsg, epsf, epsx, maxits);
//
// Then we activate OptGuard integrity checking.
//
// OptGuard monitor helps to catch common coding and problem statement
// issues, like:
// * discontinuity of the target function (C0 continuity violation)
// * nonsmoothness of the target function (C1 continuity violation)
// * erroneous analytic gradient, i.e. one inconsistent with actual
// change in the target/constraints
//
// OptGuard is essential for early prototyping stages because such
// problems often result in premature termination of the optimizer
// which is really hard to distinguish from the correct termination.
//
// IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL
// DIFFERENTIATION. DO NOT USE IT IN PRODUCTION CODE!!!!!!!
//
// Other OptGuard checks add moderate overhead, but anyway
// it is better to turn them off when they are not needed.
//
minbleicoptguardsmoothness(state);
minbleicoptguardgradient(state, 0.001);
//
// Optimize and evaluate results
//
minbleicreport rep;
alglib::minbleicoptimize(state, function1_grad);
minbleicresults(state, x, rep);
_TestResult = _TestResult && doc_test_int(rep.terminationtype, 4);
_TestResult = _TestResult && doc_test_real_vector(x, "[2,4]", 0.005);
//
// Check that OptGuard did not report errors
//
// NOTE: want to test OptGuard? Try breaking the gradient - say, add
// 1.0 to some of its components.
//
optguardreport ogrep;
minbleicoptguardresults(state, ogrep);
_TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minbleic_d_2");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minbleic_numdiff
// Nonlinear optimization with bound constraints and numerical differentiation
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<23; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of
//
// f(x,y) = 100*(x+3)^4+(y-3)^4
//
// subject to box constraints
//
// -1<=x<=+1, -1<=y<=+1
//
// using BLEIC optimizer with:
// * numerical differentiation being used
// * initial point x=[0,0]
// * unit scale being set for all variables (see minbleicsetscale for more info)
// * stopping criteria set to "terminate after short enough step"
// * OptGuard integrity check being used to check problem statement
// for some common errors like nonsmoothness or bad analytic gradient
//
// First, we create optimizer object and tune its properties:
// * set box constraints
// * set variable scales
// * set stopping criteria
//
real_1d_array x = "[0,0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
real_1d_array s = "[1,1]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(s);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(s);
if( _spoil_scenario==6 )
spoil_vector_by_deleting_element(s);
real_1d_array bndl = "[-1,-1]";
if( _spoil_scenario==7 )
spoil_vector_by_nan(bndl);
if( _spoil_scenario==8 )
spoil_vector_by_deleting_element(bndl);
real_1d_array bndu = "[+1,+1]";
if( _spoil_scenario==9 )
spoil_vector_by_nan(bndu);
if( _spoil_scenario==10 )
spoil_vector_by_deleting_element(bndu);
minbleicstate state;
double epsg = 0;
if( _spoil_scenario==11 )
epsg = fp_nan;
if( _spoil_scenario==12 )
epsg = fp_posinf;
if( _spoil_scenario==13 )
epsg = fp_neginf;
double epsf = 0;
if( _spoil_scenario==14 )
epsf = fp_nan;
if( _spoil_scenario==15 )
epsf = fp_posinf;
if( _spoil_scenario==16 )
epsf = fp_neginf;
double epsx = 0.000001;
if( _spoil_scenario==17 )
epsx = fp_nan;
if( _spoil_scenario==18 )
epsx = fp_posinf;
if( _spoil_scenario==19 )
epsx = fp_neginf;
ae_int_t maxits = 0;
double diffstep = 1.0e-6;
if( _spoil_scenario==20 )
diffstep = fp_nan;
if( _spoil_scenario==21 )
diffstep = fp_posinf;
if( _spoil_scenario==22 )
diffstep = fp_neginf;
minbleiccreatef(x, diffstep, state);
minbleicsetbc(state, bndl, bndu);
minbleicsetscale(state, s);
minbleicsetcond(state, epsg, epsf, epsx, maxits);
//
// Then we activate OptGuard integrity checking.
//
// Numerical differentiation always produces "correct" gradient
// (with some truncation error, but unbiased). Thus, we just have
// to check smoothness properties of the target: C0 and C1 continuity.
//
// Sometimes user accidentally tries to solve nonsmooth problems
// with smooth optimizer. OptGuard helps to detect such situations
// early, at the prototyping stage.
//
minbleicoptguardsmoothness(state);
//
// Optimize and evaluate results
//
minbleicreport rep;
alglib::minbleicoptimize(state, function1_func);
minbleicresults(state, x, rep);
_TestResult = _TestResult && doc_test_int(rep.terminationtype, 4);
_TestResult = _TestResult && doc_test_real_vector(x, "[-1,1]", 0.005);
//
// Check that OptGuard did not report errors
//
// Want to challenge OptGuard? Try to make your problem
// nonsmooth by replacing 100*(x+3)^4 by 100*|x+3| and
// re-run optimizer.
//
optguardreport ogrep;
minbleicoptguardresults(state, ogrep);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minbleic_numdiff");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minqp_d_u1
// Unconstrained dense quadratic programming
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<17; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of F(x0,x1) = x0^2 + x1^2 -6*x0 - 4*x1
//
// Exact solution is [x0,x1] = [3,2]
//
// We provide algorithm with starting point, although in this case
// (dense matrix, no constraints) it can work without such information.
//
// Several QP solvers are tried: QuickQP, BLEIC, DENSE-AUL.
//
// IMPORTANT: this solver minimizes following function:
// f(x) = 0.5*x'*A*x + b'*x.
// Note that quadratic term has 0.5 before it. So if you want to minimize
// quadratic function, you should rewrite it in such way that quadratic term
// is multiplied by 0.5 too.
//
// For example, our function is f(x)=x0^2+x1^2+..., but we rewrite it as
// f(x) = 0.5*(2*x0^2+2*x1^2) + ....
// and pass diag(2,2) as quadratic term - NOT diag(1,1)!
//
real_2d_array a = "[[2,0],[0,2]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(a);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(a);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(a);
if( _spoil_scenario==3 )
spoil_matrix_by_deleting_row(a);
if( _spoil_scenario==4 )
spoil_matrix_by_deleting_col(a);
real_1d_array b = "[-6,-4]";
if( _spoil_scenario==5 )
spoil_vector_by_nan(b);
if( _spoil_scenario==6 )
spoil_vector_by_posinf(b);
if( _spoil_scenario==7 )
spoil_vector_by_neginf(b);
if( _spoil_scenario==8 )
spoil_vector_by_deleting_element(b);
real_1d_array x0 = "[0,1]";
if( _spoil_scenario==9 )
spoil_vector_by_nan(x0);
if( _spoil_scenario==10 )
spoil_vector_by_posinf(x0);
if( _spoil_scenario==11 )
spoil_vector_by_neginf(x0);
if( _spoil_scenario==12 )
spoil_vector_by_deleting_element(x0);
real_1d_array s = "[1,1]";
if( _spoil_scenario==13 )
spoil_vector_by_nan(s);
if( _spoil_scenario==14 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==15 )
spoil_vector_by_neginf(s);
if( _spoil_scenario==16 )
spoil_vector_by_deleting_element(s);
real_1d_array x;
minqpstate state;
minqpreport rep;
// create solver, set quadratic/linear terms
minqpcreate(2, state);
minqpsetquadraticterm(state, a);
minqpsetlinearterm(state, b);
minqpsetstartingpoint(state, x0);
// Set scale of the parameters.
// It is strongly recommended that you set scale of your variables.
// Knowing their scales is essential for evaluation of stopping criteria
// and for preconditioning of the algorithm steps.
// You can find more information on scaling at http://www.alglib.net/optimization/scaling.php
//
// NOTE: for convex problems you may try using minqpsetscaleautodiag()
// which automatically determines variable scales.
minqpsetscale(state, s);
//
// Solve problem with QuickQP solver.
//
// This solver is intended for medium and large-scale problems with box
// constraints (general linear constraints are not supported), but it can
// also be efficiently used on unconstrained problems.
//
// Default stopping criteria are used, Newton phase is active.
//
minqpsetalgoquickqp(state, 0.0, 0.0, 0.0, 0, true);
minqpoptimize(state);
minqpresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[3,2]", 0.005);
//
// Solve problem with BLEIC-based QP solver.
//
// This solver is intended for problems with moderate (up to 50) number
// of general linear constraints and unlimited number of box constraints.
// Of course, unconstrained problems can be solved too.
//
// Default stopping criteria are used.
//
minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0);
minqpoptimize(state);
minqpresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[3,2]", 0.005);
//
// Solve problem with DENSE-AUL solver.
//
// This solver is optimized for problems with up to several thousands of
// variables and large amount of general linear constraints. Problems with
// less than 50 general linear constraints can be efficiently solved with
// BLEIC, problems with box-only constraints can be solved with QuickQP.
// However, DENSE-AUL will work in any (including unconstrained) case.
//
// Default stopping criteria are used.
//
minqpsetalgodenseaul(state, 1.0e-9, 1.0e+4, 5);
minqpoptimize(state);
minqpresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[3,2]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minqp_d_u1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minqp_d_bc1
// Bound constrained dense quadratic programming
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<21; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of F(x0,x1) = x0^2 + x1^2 -6*x0 - 4*x1
// subject to bound constraints 0<=x0<=2.5, 0<=x1<=2.5
//
// Exact solution is [x0,x1] = [2.5,2]
//
// We provide algorithm with starting point. With such small problem good starting
// point is not really necessary, but with high-dimensional problem it can save us
// a lot of time.
//
// Several QP solvers are tried: QuickQP, BLEIC, DENSE-AUL.
//
// IMPORTANT: this solver minimizes following function:
// f(x) = 0.5*x'*A*x + b'*x.
// Note that quadratic term has 0.5 before it. So if you want to minimize
// quadratic function, you should rewrite it in such way that quadratic term
// is multiplied by 0.5 too.
// For example, our function is f(x)=x0^2+x1^2+..., but we rewrite it as
// f(x) = 0.5*(2*x0^2+2*x1^2) + ....
// and pass diag(2,2) as quadratic term - NOT diag(1,1)!
//
real_2d_array a = "[[2,0],[0,2]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(a);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(a);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(a);
if( _spoil_scenario==3 )
spoil_matrix_by_deleting_row(a);
if( _spoil_scenario==4 )
spoil_matrix_by_deleting_col(a);
real_1d_array b = "[-6,-4]";
if( _spoil_scenario==5 )
spoil_vector_by_nan(b);
if( _spoil_scenario==6 )
spoil_vector_by_posinf(b);
if( _spoil_scenario==7 )
spoil_vector_by_neginf(b);
if( _spoil_scenario==8 )
spoil_vector_by_deleting_element(b);
real_1d_array x0 = "[0,1]";
if( _spoil_scenario==9 )
spoil_vector_by_nan(x0);
if( _spoil_scenario==10 )
spoil_vector_by_posinf(x0);
if( _spoil_scenario==11 )
spoil_vector_by_neginf(x0);
if( _spoil_scenario==12 )
spoil_vector_by_deleting_element(x0);
real_1d_array s = "[1,1]";
if( _spoil_scenario==13 )
spoil_vector_by_nan(s);
if( _spoil_scenario==14 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==15 )
spoil_vector_by_neginf(s);
if( _spoil_scenario==16 )
spoil_vector_by_deleting_element(s);
real_1d_array bndl = "[0.0,0.0]";
if( _spoil_scenario==17 )
spoil_vector_by_nan(bndl);
if( _spoil_scenario==18 )
spoil_vector_by_deleting_element(bndl);
real_1d_array bndu = "[2.5,2.5]";
if( _spoil_scenario==19 )
spoil_vector_by_nan(bndu);
if( _spoil_scenario==20 )
spoil_vector_by_deleting_element(bndu);
real_1d_array x;
minqpstate state;
minqpreport rep;
// create solver, set quadratic/linear terms
minqpcreate(2, state);
minqpsetquadraticterm(state, a);
minqpsetlinearterm(state, b);
minqpsetstartingpoint(state, x0);
minqpsetbc(state, bndl, bndu);
// Set scale of the parameters.
// It is strongly recommended that you set scale of your variables.
// Knowing their scales is essential for evaluation of stopping criteria
// and for preconditioning of the algorithm steps.
// You can find more information on scaling at http://www.alglib.net/optimization/scaling.php
//
// NOTE: for convex problems you may try using minqpsetscaleautodiag()
// which automatically determines variable scales.
minqpsetscale(state, s);
//
// Solve problem with QuickQP solver.
//
// This solver is intended for medium and large-scale problems with box
// constraints (general linear constraints are not supported).
//
// Default stopping criteria are used, Newton phase is active.
//
minqpsetalgoquickqp(state, 0.0, 0.0, 0.0, 0, true);
minqpoptimize(state);
minqpresults(state, x, rep);
_TestResult = _TestResult && doc_test_int(rep.terminationtype, 4);
_TestResult = _TestResult && doc_test_real_vector(x, "[2.5,2]", 0.005);
//
// Solve problem with BLEIC-based QP solver.
//
// This solver is intended for problems with moderate (up to 50) number
// of general linear constraints and unlimited number of box constraints.
//
// Default stopping criteria are used.
//
minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0);
minqpoptimize(state);
minqpresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[2.5,2]", 0.005);
//
// Solve problem with DENSE-AUL solver.
//
// This solver is optimized for problems with up to several thousands of
// variables and large amount of general linear constraints. Problems with
// less than 50 general linear constraints can be efficiently solved with
// BLEIC, problems with box-only constraints can be solved with QuickQP.
// However, DENSE-AUL will work in any (including unconstrained) case.
//
// Default stopping criteria are used.
//
minqpsetalgodenseaul(state, 1.0e-9, 1.0e+4, 5);
minqpoptimize(state);
minqpresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[2.5,2]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minqp_d_bc1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minqp_d_lc1
// Linearly constrained dense quadratic programming
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<16; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of F(x0,x1) = x0^2 + x1^2 -6*x0 - 4*x1
// subject to linear constraint x0+x1<=2
//
// Exact solution is [x0,x1] = [1.5,0.5]
//
// IMPORTANT: this solver minimizes following function:
// f(x) = 0.5*x'*A*x + b'*x.
// Note that quadratic term has 0.5 before it. So if you want to minimize
// quadratic function, you should rewrite it in such way that quadratic term
// is multiplied by 0.5 too.
// For example, our function is f(x)=x0^2+x1^2+..., but we rewrite it as
// f(x) = 0.5*(2*x0^2+2*x1^2) + ....
// and pass diag(2,2) as quadratic term - NOT diag(1,1)!
//
real_2d_array a = "[[2,0],[0,2]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(a);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(a);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(a);
if( _spoil_scenario==3 )
spoil_matrix_by_deleting_row(a);
if( _spoil_scenario==4 )
spoil_matrix_by_deleting_col(a);
real_1d_array b = "[-6,-4]";
if( _spoil_scenario==5 )
spoil_vector_by_nan(b);
if( _spoil_scenario==6 )
spoil_vector_by_posinf(b);
if( _spoil_scenario==7 )
spoil_vector_by_neginf(b);
if( _spoil_scenario==8 )
spoil_vector_by_deleting_element(b);
real_1d_array s = "[1,1]";
if( _spoil_scenario==9 )
spoil_vector_by_nan(s);
if( _spoil_scenario==10 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==11 )
spoil_vector_by_neginf(s);
if( _spoil_scenario==12 )
spoil_vector_by_deleting_element(s);
real_2d_array c = "[[1.0,1.0,2.0]]";
if( _spoil_scenario==13 )
spoil_matrix_by_nan(c);
if( _spoil_scenario==14 )
spoil_matrix_by_posinf(c);
if( _spoil_scenario==15 )
spoil_matrix_by_neginf(c);
integer_1d_array ct = "[-1]";
real_1d_array x;
minqpstate state;
minqpreport rep;
// create solver, set quadratic/linear terms
minqpcreate(2, state);
minqpsetquadraticterm(state, a);
minqpsetlinearterm(state, b);
minqpsetlc(state, c, ct);
// Set scale of the parameters.
// It is strongly recommended that you set scale of your variables.
// Knowing their scales is essential for evaluation of stopping criteria
// and for preconditioning of the algorithm steps.
// You can find more information on scaling at http://www.alglib.net/optimization/scaling.php
//
// NOTE: for convex problems you may try using minqpsetscaleautodiag()
// which automatically determines variable scales.
minqpsetscale(state, s);
//
// Solve problem with BLEIC-based QP solver.
//
// This solver is intended for problems with moderate (up to 50) number
// of general linear constraints and unlimited number of box constraints.
//
// Default stopping criteria are used.
//
minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0);
minqpoptimize(state);
minqpresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[1.500,0.500]", 0.05);
//
// Solve problem with DENSE-AUL solver.
//
// This solver is optimized for problems with up to several thousands of
// variables and large amount of general linear constraints. Problems with
// less than 50 general linear constraints can be efficiently solved with
// BLEIC, problems with box-only constraints can be solved with QuickQP.
// However, DENSE-AUL will work in any (including unconstrained) case.
//
// Default stopping criteria are used.
//
minqpsetalgodenseaul(state, 1.0e-9, 1.0e+4, 5);
minqpoptimize(state);
minqpresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[1.500,0.500]", 0.05);
//
// Solve problem with QuickQP solver.
//
// This solver is intended for medium and large-scale problems with box
// constraints, and...
//
// ...Oops! It does not support general linear constraints, -5 returned as completion code!
//
minqpsetalgoquickqp(state, 0.0, 0.0, 0.0, 0, true);
minqpoptimize(state);
minqpresults(state, x, rep);
_TestResult = _TestResult && doc_test_int(rep.terminationtype, -5);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minqp_d_lc1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minqp_d_u2
// Unconstrained sparse quadratic programming
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<12; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of F(x0,x1) = x0^2 + x1^2 -6*x0 - 4*x1,
// with quadratic term given by sparse matrix structure.
//
// Exact solution is [x0,x1] = [3,2]
//
// We provide algorithm with starting point, although in this case
// (dense matrix, no constraints) it can work without such information.
//
// IMPORTANT: this solver minimizes following function:
// f(x) = 0.5*x'*A*x + b'*x.
// Note that quadratic term has 0.5 before it. So if you want to minimize
// quadratic function, you should rewrite it in such way that quadratic term
// is multiplied by 0.5 too.
//
// For example, our function is f(x)=x0^2+x1^2+..., but we rewrite it as
// f(x) = 0.5*(2*x0^2+2*x1^2) + ....
// and pass diag(2,2) as quadratic term - NOT diag(1,1)!
//
sparsematrix a;
real_1d_array b = "[-6,-4]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(b);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(b);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(b);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(b);
real_1d_array x0 = "[0,1]";
if( _spoil_scenario==4 )
spoil_vector_by_nan(x0);
if( _spoil_scenario==5 )
spoil_vector_by_posinf(x0);
if( _spoil_scenario==6 )
spoil_vector_by_neginf(x0);
if( _spoil_scenario==7 )
spoil_vector_by_deleting_element(x0);
real_1d_array s = "[1,1]";
if( _spoil_scenario==8 )
spoil_vector_by_nan(s);
if( _spoil_scenario==9 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==10 )
spoil_vector_by_neginf(s);
if( _spoil_scenario==11 )
spoil_vector_by_deleting_element(s);
real_1d_array x;
minqpstate state;
minqpreport rep;
// initialize sparsematrix structure
sparsecreate(2, 2, 0, a);
sparseset(a, 0, 0, 2.0);
sparseset(a, 1, 1, 2.0);
// create solver, set quadratic/linear terms
minqpcreate(2, state);
minqpsetquadratictermsparse(state, a, true);
minqpsetlinearterm(state, b);
minqpsetstartingpoint(state, x0);
// Set scale of the parameters.
// It is strongly recommended that you set scale of your variables.
// Knowing their scales is essential for evaluation of stopping criteria
// and for preconditioning of the algorithm steps.
// You can find more information on scaling at http://www.alglib.net/optimization/scaling.php
//
// NOTE: for convex problems you may try using minqpsetscaleautodiag()
// which automatically determines variable scales.
minqpsetscale(state, s);
//
// Solve problem with BLEIC-based QP solver.
//
// This solver is intended for problems with moderate (up to 50) number
// of general linear constraints and unlimited number of box constraints.
// It also supports sparse problems.
//
// Default stopping criteria are used.
//
minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0);
minqpoptimize(state);
minqpresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[3,2]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minqp_d_u2");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minqp_d_nonconvex
// Nonconvex quadratic programming
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<21; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of nonconvex function
// F(x0,x1) = -(x0^2+x1^2)
// subject to constraints x0,x1 in [1.0,2.0]
// Exact solution is [x0,x1] = [2,2].
//
// Non-convex problems are harded to solve than convex ones, and they
// may have more than one local minimum. However, ALGLIB solves may deal
// with such problems (altough they do not guarantee convergence to
// global minimum).
//
// IMPORTANT: this solver minimizes following function:
// f(x) = 0.5*x'*A*x + b'*x.
// Note that quadratic term has 0.5 before it. So if you want to minimize
// quadratic function, you should rewrite it in such way that quadratic term
// is multiplied by 0.5 too.
//
// For example, our function is f(x)=-(x0^2+x1^2), but we rewrite it as
// f(x) = 0.5*(-2*x0^2-2*x1^2)
// and pass diag(-2,-2) as quadratic term - NOT diag(-1,-1)!
//
real_2d_array a = "[[-2,0],[0,-2]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(a);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(a);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(a);
if( _spoil_scenario==3 )
spoil_matrix_by_deleting_row(a);
if( _spoil_scenario==4 )
spoil_matrix_by_deleting_col(a);
real_1d_array x0 = "[1,1]";
if( _spoil_scenario==5 )
spoil_vector_by_nan(x0);
if( _spoil_scenario==6 )
spoil_vector_by_posinf(x0);
if( _spoil_scenario==7 )
spoil_vector_by_neginf(x0);
if( _spoil_scenario==8 )
spoil_vector_by_deleting_element(x0);
real_1d_array s = "[1,1]";
if( _spoil_scenario==9 )
spoil_vector_by_nan(s);
if( _spoil_scenario==10 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==11 )
spoil_vector_by_neginf(s);
if( _spoil_scenario==12 )
spoil_vector_by_deleting_element(s);
real_1d_array bndl = "[1.0,1.0]";
if( _spoil_scenario==13 )
spoil_vector_by_nan(bndl);
if( _spoil_scenario==14 )
spoil_vector_by_deleting_element(bndl);
real_1d_array bndu = "[2.0,2.0]";
if( _spoil_scenario==15 )
spoil_vector_by_nan(bndu);
if( _spoil_scenario==16 )
spoil_vector_by_deleting_element(bndu);
real_1d_array x;
minqpstate state;
minqpreport rep;
// create solver, set quadratic/linear terms, constraints
minqpcreate(2, state);
minqpsetquadraticterm(state, a);
minqpsetstartingpoint(state, x0);
minqpsetbc(state, bndl, bndu);
// Set scale of the parameters.
// It is strongly recommended that you set scale of your variables.
// Knowing their scales is essential for evaluation of stopping criteria
// and for preconditioning of the algorithm steps.
// You can find more information on scaling at http://www.alglib.net/optimization/scaling.php
//
// NOTE: there also exists minqpsetscaleautodiag() function
// which automatically determines variable scales; however,
// it does NOT work for non-convex problems.
minqpsetscale(state, s);
//
// Solve problem with BLEIC-based QP solver.
//
// This solver is intended for problems with moderate (up to 50) number
// of general linear constraints and unlimited number of box constraints.
//
// It may solve non-convex problems as long as they are bounded from
// below under constraints.
//
// Default stopping criteria are used.
//
minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0);
minqpoptimize(state);
minqpresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[2,2]", 0.005);
//
// Solve problem with DENSE-AUL solver.
//
// This solver is optimized for problems with up to several thousands of
// variables and large amount of general linear constraints. Problems with
// less than 50 general linear constraints can be efficiently solved with
// BLEIC, problems with box-only constraints can be solved with QuickQP.
// However, DENSE-AUL will work in any (including unconstrained) case.
//
// Algorithm convergence is guaranteed only for convex case, but you may
// expect that it will work for non-convex problems too (because near the
// solution they are locally convex).
//
// Default stopping criteria are used.
//
minqpsetalgodenseaul(state, 1.0e-9, 1.0e+4, 5);
minqpoptimize(state);
minqpresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[2,2]", 0.005);
// Hmm... this problem is bounded from below (has solution) only under constraints.
// What it we remove them?
//
// You may see that BLEIC algorithm detects unboundedness of the problem,
// -4 is returned as completion code. However, DENSE-AUL is unable to detect
// such situation and it will cycle forever (we do not test it here).
real_1d_array nobndl = "[-inf,-inf]";
if( _spoil_scenario==17 )
spoil_vector_by_nan(nobndl);
if( _spoil_scenario==18 )
spoil_vector_by_deleting_element(nobndl);
real_1d_array nobndu = "[+inf,+inf]";
if( _spoil_scenario==19 )
spoil_vector_by_nan(nobndu);
if( _spoil_scenario==20 )
spoil_vector_by_deleting_element(nobndu);
minqpsetbc(state, nobndl, nobndu);
minqpsetalgobleic(state, 0.0, 0.0, 0.0, 0);
minqpoptimize(state);
minqpresults(state, x, rep);
_TestResult = _TestResult && doc_test_int(rep.terminationtype, -4);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minqp_d_nonconvex");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minlp_basic
// Basic linear programming example
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<15; _spoil_scenario++)
{
try
{
//
// This example demonstrates how to minimize
//
// F(x0,x1) = -0.1*x0 - x1
//
// subject to box constraints
//
// -1 <= x0,x1 <= +1
//
// and general linear constraints
//
// x0 - x1 >= -1
// x0 + x1 <= 1
//
// We use dual simplex solver provided by ALGLIB for this task. Box
// constraints are specified by means of constraint vectors bndl and
// bndu (we have bndl<=x<=bndu). General linear constraints are
// specified as AL<=A*x<=AU, with AL/AU being 2x1 vectors and A being
// 2x2 matrix.
//
// NOTE: some/all components of AL/AU can be +-INF, same applies to
// bndl/bndu. You can also have AL[I]=AU[i] (as well as
// BndL[i]=BndU[i]).
//
real_2d_array a = "[[1,-1],[1,+1]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(a);
if( _spoil_scenario==1 )
spoil_matrix_by_deleting_row(a);
if( _spoil_scenario==2 )
spoil_matrix_by_deleting_col(a);
real_1d_array al = "[-1,-inf]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(al);
if( _spoil_scenario==4 )
spoil_vector_by_deleting_element(al);
real_1d_array au = "[+inf,+1]";
if( _spoil_scenario==5 )
spoil_vector_by_nan(au);
if( _spoil_scenario==6 )
spoil_vector_by_deleting_element(au);
real_1d_array c = "[-0.1,-1]";
if( _spoil_scenario==7 )
spoil_vector_by_nan(c);
if( _spoil_scenario==8 )
spoil_vector_by_deleting_element(c);
real_1d_array s = "[1,1]";
if( _spoil_scenario==9 )
spoil_vector_by_nan(s);
if( _spoil_scenario==10 )
spoil_vector_by_deleting_element(s);
real_1d_array bndl = "[-1,-1]";
if( _spoil_scenario==11 )
spoil_vector_by_nan(bndl);
if( _spoil_scenario==12 )
spoil_vector_by_deleting_element(bndl);
real_1d_array bndu = "[+1,+1]";
if( _spoil_scenario==13 )
spoil_vector_by_nan(bndu);
if( _spoil_scenario==14 )
spoil_vector_by_deleting_element(bndu);
real_1d_array x;
minlpstate state;
minlpreport rep;
minlpcreate(2, state);
//
// Set cost vector, box constraints, general linear constraints.
//
// Box constraints can be set in one call to minlpsetbc() or minlpsetbcall()
// (latter sets same constraints for all variables and accepts two scalars
// instead of two vectors).
//
// General linear constraints can be specified in several ways:
// * minlpsetlc2dense() - accepts dense 2D array as input; sometimes this
// approach is more convenient, although less memory-efficient.
// * minlpsetlc2() - accepts sparse matrix as input
// * minlpaddlc2dense() - appends one row to the current set of constraints;
// row being appended is specified as dense vector
// * minlpaddlc2() - appends one row to the current set of constraints;
// row being appended is specified as sparse set of elements
// Independently from specific function being used, LP solver uses sparse
// storage format for internal representation of constraints.
//
minlpsetcost(state, c);
minlpsetbc(state, bndl, bndu);
minlpsetlc2dense(state, a, al, au, 2);
//
// Set scale of the parameters.
//
// It is strongly recommended that you set scale of your variables.
// Knowing their scales is essential for evaluation of stopping criteria
// and for preconditioning of the algorithm steps.
// You can find more information on scaling at http://www.alglib.net/optimization/scaling.php
//
minlpsetscale(state, s);
// Solve
minlpoptimize(state);
minlpresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[0,1]", 0.0005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minlp_basic");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minnlc_d_inequality
// Nonlinearly constrained optimization (inequality constraints)
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<9; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of
//
// f(x0,x1) = -x0+x1
//
// subject to box constraints
//
// x0>=0, x1>=0
//
// and nonlinear inequality constraint
//
// x0^2 + x1^2 - 1 <= 0
//
real_1d_array x0 = "[0,0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x0);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x0);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x0);
real_1d_array s = "[1,1]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(s);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(s);
double epsx = 0.000001;
if( _spoil_scenario==6 )
epsx = fp_nan;
if( _spoil_scenario==7 )
epsx = fp_posinf;
if( _spoil_scenario==8 )
epsx = fp_neginf;
ae_int_t maxits = 0;
real_1d_array bndl = "[0,0]";
real_1d_array bndu = "[+inf,+inf]";
minnlcstate state;
//
// Create optimizer object and tune its settings:
// * epsx=0.000001 stopping condition for inner iterations
// * s=[1,1] all variables have unit scale; it is important to
// tell optimizer about scales of your variables - it
// greatly accelerates convergence and helps to perform
// some important integrity checks.
//
minnlccreate(2, x0, state);
minnlcsetcond(state, epsx, maxits);
minnlcsetscale(state, s);
//
// Choose one of the nonlinear programming solvers supported by minnlc
// optimizer:
// * SQP - sequential quadratic programming NLP solver
// * AUL - augmented Lagrangian NLP solver
// * SLP - successive linear programming NLP solver
//
// Different solvers have different properties:
// * SQP needs less function evaluations than any other solver, but it
// has much higher iteration cost than other solvers (a QP subproblem
// has to be solved during each step)
// * AUL solver has cheaper iterations, but needs more target function
// evaluations
// * SLP is the most robust solver provided by ALGLIB, but it performs
// order of magnitude more iterations than SQP.
//
// In the code below we set solver to be AUL but then override it with SLP,
// and then with SQP, so the effective choice is to use SLP. We recommend
// you to use SQP at least for early prototyping stages, and then switch
// to AUL if possible.
//
double rho = 1000.0;
ae_int_t outerits = 5;
minnlcsetalgoaul(state, rho, outerits);
minnlcsetalgoslp(state);
minnlcsetalgosqp(state);
//
// Set constraints:
//
// 1. boundary constraints are passed with minnlcsetbc() call
//
// 2. nonlinear constraints are more tricky - you can not "pack" general
// nonlinear function into double precision array. That's why
// minnlcsetnlc() does not accept constraints itself - only constraint
// counts are passed: first parameter is number of equality constraints,
// second one is number of inequality constraints.
//
// As for constraining functions - these functions are passed as part
// of problem Jacobian (see below).
//
// NOTE: MinNLC optimizer supports arbitrary combination of boundary, general
// linear and general nonlinear constraints. This example does not
// show how to work with general linear constraints, but you can
// easily find it in documentation on minnlcsetlc() function.
//
minnlcsetbc(state, bndl, bndu);
minnlcsetnlc(state, 0, 1);
//
// Activate OptGuard integrity checking.
//
// OptGuard monitor helps to catch common coding and problem statement
// issues, like:
// * discontinuity of the target/constraints (C0 continuity violation)
// * nonsmoothness of the target/constraints (C1 continuity violation)
// * erroneous analytic Jacobian, i.e. one inconsistent with actual
// change in the target/constraints
//
// OptGuard is essential for early prototyping stages because such
// problems often result in premature termination of the optimizer
// which is really hard to distinguish from the correct termination.
//
// IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL
// DIFFERENTIATION, THUS DO NOT USE IT IN PRODUCTION CODE!
//
// Other OptGuard checks add moderate overhead, but anyway
// it is better to turn them off when they are not needed.
//
minnlcoptguardsmoothness(state);
minnlcoptguardgradient(state, 0.001);
//
// Optimize and test results.
//
// Optimizer object accepts vector function and its Jacobian, with first
// component (Jacobian row) being target function, and next components
// (Jacobian rows) being nonlinear equality and inequality constraints.
//
// So, our vector function has form
//
// {f0,f1} = { -x0+x1 , x0^2+x1^2-1 }
//
// with Jacobian
//
// [ -1 +1 ]
// J = [ ]
// [ 2*x0 2*x1 ]
//
// with f0 being target function, f1 being constraining function. Number
// of equality/inequality constraints is specified by minnlcsetnlc(),
// with equality ones always being first, inequality ones being last.
//
minnlcreport rep;
real_1d_array x1;
alglib::minnlcoptimize(state, nlcfunc1_jac);
minnlcresults(state, x1, rep);
_TestResult = _TestResult && doc_test_real_vector(x1, "[1.0000,0.0000]", 0.005);
//
// Check that OptGuard did not report errors
//
// NOTE: want to test OptGuard? Try breaking the Jacobian - say, add
// 1.0 to some of its components.
//
optguardreport ogrep;
minnlcoptguardresults(state, ogrep);
_TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minnlc_d_inequality");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minnlc_d_equality
// Nonlinearly constrained optimization (equality constraints)
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<9; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of
//
// f(x0,x1) = -x0+x1
//
// subject to nonlinear equality constraint
//
// x0^2 + x1^2 - 1 = 0
//
real_1d_array x0 = "[0,0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x0);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x0);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x0);
real_1d_array s = "[1,1]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(s);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(s);
double epsx = 0.000001;
if( _spoil_scenario==6 )
epsx = fp_nan;
if( _spoil_scenario==7 )
epsx = fp_posinf;
if( _spoil_scenario==8 )
epsx = fp_neginf;
ae_int_t maxits = 0;
minnlcstate state;
//
// Create optimizer object and tune its settings:
// * epsx=0.000001 stopping condition for inner iterations
// * s=[1,1] all variables have unit scale
//
minnlccreate(2, x0, state);
minnlcsetcond(state, epsx, maxits);
minnlcsetscale(state, s);
//
// Choose one of the nonlinear programming solvers supported by minnlc
// optimizer:
// * SLP - successive linear programming NLP solver
// * AUL - augmented Lagrangian NLP solver
//
// Different solvers have different properties:
// * SLP is the most robust solver provided by ALGLIB: it can solve both
// convex and nonconvex optimization problems, it respects box and
// linear constraints (after you find feasible point it won't move away
// from the feasible area) and tries to respect nonlinear constraints
// as much as possible. It also usually needs less function evaluations
// to converge than AUL.
// However, it solves LP subproblems at each iterations which adds
// significant overhead to its running time. Sometimes it can be as much
// as 7x times slower than AUL.
// * AUL solver is less robust than SLP - it can violate box and linear
// constraints at any moment, and it is intended for convex optimization
// problems (although in many cases it can deal with nonconvex ones too).
// Also, unlike SLP it needs some tuning (penalty factor and number of
// outer iterations).
// However, it is often much faster than the current version of SLP.
//
// In the code below we set solver to be AUL but then override it with SLP,
// so the effective choice is to use SLP. We recommend you to use SLP at
// least for early prototyping stages.
//
// You can comment out line with SLP if you want to solve your problem with
// AUL solver.
//
double rho = 1000.0;
ae_int_t outerits = 5;
minnlcsetalgoaul(state, rho, outerits);
minnlcsetalgoslp(state);
//
// Set constraints:
//
// Nonlinear constraints are tricky - you can not "pack" general
// nonlinear function into double precision array. That's why
// minnlcsetnlc() does not accept constraints itself - only constraint
// counts are passed: first parameter is number of equality constraints,
// second one is number of inequality constraints.
//
// As for constraining functions - these functions are passed as part
// of problem Jacobian (see below).
//
// NOTE: MinNLC optimizer supports arbitrary combination of boundary, general
// linear and general nonlinear constraints. This example does not
// show how to work with general linear constraints, but you can
// easily find it in documentation on minnlcsetbc() and
// minnlcsetlc() functions.
//
minnlcsetnlc(state, 1, 0);
//
// Activate OptGuard integrity checking.
//
// OptGuard monitor helps to catch common coding and problem statement
// issues, like:
// * discontinuity of the target/constraints (C0 continuity violation)
// * nonsmoothness of the target/constraints (C1 continuity violation)
// * erroneous analytic Jacobian, i.e. one inconsistent with actual
// change in the target/constraints
//
// OptGuard is essential for early prototyping stages because such
// problems often result in premature termination of the optimizer
// which is really hard to distinguish from the correct termination.
//
// IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL
// DIFFERENTIATION, THUS DO NOT USE IT IN PRODUCTION CODE!
//
// Other OptGuard checks add moderate overhead, but anyway
// it is better to turn them off when they are not needed.
//
minnlcoptguardsmoothness(state);
minnlcoptguardgradient(state, 0.001);
//
// Optimize and test results.
//
// Optimizer object accepts vector function and its Jacobian, with first
// component (Jacobian row) being target function, and next components
// (Jacobian rows) being nonlinear equality and inequality constraints.
//
// So, our vector function has form
//
// {f0,f1} = { -x0+x1 , x0^2+x1^2-1 }
//
// with Jacobian
//
// [ -1 +1 ]
// J = [ ]
// [ 2*x0 2*x1 ]
//
// with f0 being target function, f1 being constraining function. Number
// of equality/inequality constraints is specified by minnlcsetnlc(),
// with equality ones always being first, inequality ones being last.
//
minnlcreport rep;
real_1d_array x1;
alglib::minnlcoptimize(state, nlcfunc1_jac);
minnlcresults(state, x1, rep);
_TestResult = _TestResult && doc_test_real_vector(x1, "[0.70710,-0.70710]", 0.005);
//
// Check that OptGuard did not report errors
//
// NOTE: want to test OptGuard? Try breaking the Jacobian - say, add
// 1.0 to some of its components.
//
optguardreport ogrep;
minnlcoptguardresults(state, ogrep);
_TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minnlc_d_equality");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minnlc_d_mixed
// Nonlinearly constrained optimization with mixed equality/inequality constraints
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<9; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of
//
// f(x0,x1) = x0+x1
//
// subject to nonlinear inequality constraint
//
// x0^2 + x1^2 - 1 <= 0
//
// and nonlinear equality constraint
//
// x2-exp(x0) = 0
//
real_1d_array x0 = "[0,0,0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x0);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x0);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x0);
real_1d_array s = "[1,1,1]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(s);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(s);
double epsx = 0.000001;
if( _spoil_scenario==6 )
epsx = fp_nan;
if( _spoil_scenario==7 )
epsx = fp_posinf;
if( _spoil_scenario==8 )
epsx = fp_neginf;
ae_int_t maxits = 0;
minnlcstate state;
minnlcreport rep;
real_1d_array x1;
//
// Create optimizer object and tune its settings:
// * epsx=0.000001 stopping condition for inner iterations
// * s=[1,1] all variables have unit scale
// * upper limit on step length is specified (to avoid probing locations where exp() is large)
//
minnlccreate(3, x0, state);
minnlcsetcond(state, epsx, maxits);
minnlcsetscale(state, s);
minnlcsetstpmax(state, 10.0);
//
// Choose one of the nonlinear programming solvers supported by minnlc
// optimizer:
// * SLP - successive linear programming NLP solver
// * AUL - augmented Lagrangian NLP solver
//
// Different solvers have different properties:
// * SLP is the most robust solver provided by ALGLIB: it can solve both
// convex and nonconvex optimization problems, it respects box and
// linear constraints (after you find feasible point it won't move away
// from the feasible area) and tries to respect nonlinear constraints
// as much as possible. It also usually needs less function evaluations
// to converge than AUL.
// However, it solves LP subproblems at each iterations which adds
// significant overhead to its running time. Sometimes it can be as much
// as 7x times slower than AUL.
// * AUL solver is less robust than SLP - it can violate box and linear
// constraints at any moment, and it is intended for convex optimization
// problems (although in many cases it can deal with nonconvex ones too).
// Also, unlike SLP it needs some tuning (penalty factor and number of
// outer iterations).
// However, it is often much faster than the current version of SLP.
//
// In the code below we set solver to be AUL but then override it with SLP,
// so the effective choice is to use SLP. We recommend you to use SLP at
// least for early prototyping stages.
//
// You can comment out line with SLP if you want to solve your problem with
// AUL solver.
//
double rho = 1000.0;
ae_int_t outerits = 5;
minnlcsetalgoaul(state, rho, outerits);
minnlcsetalgoslp(state);
//
// Set constraints:
//
// Nonlinear constraints are tricky - you can not "pack" general
// nonlinear function into double precision array. That's why
// minnlcsetnlc() does not accept constraints itself - only constraint
// counts are passed: first parameter is number of equality constraints,
// second one is number of inequality constraints.
//
// As for constraining functions - these functions are passed as part
// of problem Jacobian (see below).
//
// NOTE: MinNLC optimizer supports arbitrary combination of boundary, general
// linear and general nonlinear constraints. This example does not
// show how to work with boundary or general linear constraints, but you
// can easily find it in documentation on minnlcsetbc() and
// minnlcsetlc() functions.
//
minnlcsetnlc(state, 1, 1);
//
// Activate OptGuard integrity checking.
//
// OptGuard monitor helps to catch common coding and problem statement
// issues, like:
// * discontinuity of the target/constraints (C0 continuity violation)
// * nonsmoothness of the target/constraints (C1 continuity violation)
// * erroneous analytic Jacobian, i.e. one inconsistent with actual
// change in the target/constraints
//
// OptGuard is essential for early prototyping stages because such
// problems often result in premature termination of the optimizer
// which is really hard to distinguish from the correct termination.
//
// IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL
// DIFFERENTIATION, THUS DO NOT USE IT IN PRODUCTION CODE!
//
// Other OptGuard checks add moderate overhead, but anyway
// it is better to turn them off when they are not needed.
//
minnlcoptguardsmoothness(state);
minnlcoptguardgradient(state, 0.001);
//
// Optimize and test results.
//
// Optimizer object accepts vector function and its Jacobian, with first
// component (Jacobian row) being target function, and next components
// (Jacobian rows) being nonlinear equality and inequality constraints.
//
// So, our vector function has form
//
// {f0,f1,f2} = { x0+x1 , x2-exp(x0) , x0^2+x1^2-1 }
//
// with Jacobian
//
// [ +1 +1 0 ]
// J = [-exp(x0) 0 1 ]
// [ 2*x0 2*x1 0 ]
//
// with f0 being target function, f1 being equality constraint "f1=0",
// f2 being inequality constraint "f2<=0". Number of equality/inequality
// constraints is specified by minnlcsetnlc(), with equality ones always
// being first, inequality ones being last.
//
alglib::minnlcoptimize(state, nlcfunc2_jac);
minnlcresults(state, x1, rep);
_TestResult = _TestResult && doc_test_real_vector(x1, "[-0.70710,-0.70710,0.49306]", 0.005);
//
// Check that OptGuard did not report errors
//
// NOTE: want to test OptGuard? Try breaking the Jacobian - say, add
// 1.0 to some of its components.
//
optguardreport ogrep;
minnlcoptguardresults(state, ogrep);
_TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minnlc_d_mixed");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minbc_d_1
// Nonlinear optimization with box constraints
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<20; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of
//
// f(x,y) = 100*(x+3)^4+(y-3)^4
//
// subject to box constraints
//
// -1<=x<=+1, -1<=y<=+1
//
// using MinBC optimizer with:
// * initial point x=[0,0]
// * unit scale being set for all variables (see minbcsetscale for more info)
// * stopping criteria set to "terminate after short enough step"
// * OptGuard integrity check being used to check problem statement
// for some common errors like nonsmoothness or bad analytic gradient
//
// First, we create optimizer object and tune its properties:
// * set box constraints
// * set variable scales
// * set stopping criteria
//
real_1d_array x = "[0,0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
real_1d_array s = "[1,1]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(s);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(s);
if( _spoil_scenario==6 )
spoil_vector_by_deleting_element(s);
real_1d_array bndl = "[-1,-1]";
if( _spoil_scenario==7 )
spoil_vector_by_nan(bndl);
if( _spoil_scenario==8 )
spoil_vector_by_deleting_element(bndl);
real_1d_array bndu = "[+1,+1]";
if( _spoil_scenario==9 )
spoil_vector_by_nan(bndu);
if( _spoil_scenario==10 )
spoil_vector_by_deleting_element(bndu);
minbcstate state;
double epsg = 0;
if( _spoil_scenario==11 )
epsg = fp_nan;
if( _spoil_scenario==12 )
epsg = fp_posinf;
if( _spoil_scenario==13 )
epsg = fp_neginf;
double epsf = 0;
if( _spoil_scenario==14 )
epsf = fp_nan;
if( _spoil_scenario==15 )
epsf = fp_posinf;
if( _spoil_scenario==16 )
epsf = fp_neginf;
double epsx = 0.000001;
if( _spoil_scenario==17 )
epsx = fp_nan;
if( _spoil_scenario==18 )
epsx = fp_posinf;
if( _spoil_scenario==19 )
epsx = fp_neginf;
ae_int_t maxits = 0;
minbccreate(x, state);
minbcsetbc(state, bndl, bndu);
minbcsetscale(state, s);
minbcsetcond(state, epsg, epsf, epsx, maxits);
//
// Then we activate OptGuard integrity checking.
//
// OptGuard monitor helps to catch common coding and problem statement
// issues, like:
// * discontinuity of the target function (C0 continuity violation)
// * nonsmoothness of the target function (C1 continuity violation)
// * erroneous analytic gradient, i.e. one inconsistent with actual
// change in the target/constraints
//
// OptGuard is essential for early prototyping stages because such
// problems often result in premature termination of the optimizer
// which is really hard to distinguish from the correct termination.
//
// IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL
// DIFFERENTIATION. DO NOT USE IT IN PRODUCTION CODE!!!!!!!
//
// Other OptGuard checks add moderate overhead, but anyway
// it is better to turn them off when they are not needed.
//
minbcoptguardsmoothness(state);
minbcoptguardgradient(state, 0.001);
//
// Optimize and evaluate results
//
minbcreport rep;
alglib::minbcoptimize(state, function1_grad);
minbcresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[-1,1]", 0.005);
//
// Check that OptGuard did not report errors
//
// NOTE: want to test OptGuard? Try breaking the gradient - say, add
// 1.0 to some of its components.
//
optguardreport ogrep;
minbcoptguardresults(state, ogrep);
_TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minbc_d_1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minbc_numdiff
// Nonlinear optimization with bound constraints and numerical differentiation
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<23; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of
//
// f(x,y) = 100*(x+3)^4+(y-3)^4
//
// subject to box constraints
//
// -1<=x<=+1, -1<=y<=+1
//
// using MinBC optimizer with:
// * numerical differentiation being used
// * initial point x=[0,0]
// * unit scale being set for all variables (see minbcsetscale for more info)
// * stopping criteria set to "terminate after short enough step"
// * OptGuard integrity check being used to check problem statement
// for some common errors like nonsmoothness or bad analytic gradient
//
real_1d_array x = "[0,0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
real_1d_array s = "[1,1]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(s);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(s);
if( _spoil_scenario==6 )
spoil_vector_by_deleting_element(s);
real_1d_array bndl = "[-1,-1]";
if( _spoil_scenario==7 )
spoil_vector_by_nan(bndl);
if( _spoil_scenario==8 )
spoil_vector_by_deleting_element(bndl);
real_1d_array bndu = "[+1,+1]";
if( _spoil_scenario==9 )
spoil_vector_by_nan(bndu);
if( _spoil_scenario==10 )
spoil_vector_by_deleting_element(bndu);
minbcstate state;
double epsg = 0;
if( _spoil_scenario==11 )
epsg = fp_nan;
if( _spoil_scenario==12 )
epsg = fp_posinf;
if( _spoil_scenario==13 )
epsg = fp_neginf;
double epsf = 0;
if( _spoil_scenario==14 )
epsf = fp_nan;
if( _spoil_scenario==15 )
epsf = fp_posinf;
if( _spoil_scenario==16 )
epsf = fp_neginf;
double epsx = 0.000001;
if( _spoil_scenario==17 )
epsx = fp_nan;
if( _spoil_scenario==18 )
epsx = fp_posinf;
if( _spoil_scenario==19 )
epsx = fp_neginf;
ae_int_t maxits = 0;
double diffstep = 1.0e-6;
if( _spoil_scenario==20 )
diffstep = fp_nan;
if( _spoil_scenario==21 )
diffstep = fp_posinf;
if( _spoil_scenario==22 )
diffstep = fp_neginf;
//
// Now we are ready to actually optimize something:
// * first we create optimizer
// * we add boundary constraints
// * we tune stopping conditions
// * and, finally, optimize and obtain results...
//
minbccreatef(x, diffstep, state);
minbcsetbc(state, bndl, bndu);
minbcsetscale(state, s);
minbcsetcond(state, epsg, epsf, epsx, maxits);
//
// Then we activate OptGuard integrity checking.
//
// Numerical differentiation always produces "correct" gradient
// (with some truncation error, but unbiased). Thus, we just have
// to check smoothness properties of the target: C0 and C1 continuity.
//
// Sometimes user accidentally tries to solve nonsmooth problems
// with smooth optimizer. OptGuard helps to detect such situations
// early, at the prototyping stage.
//
minbcoptguardsmoothness(state);
//
// Optimize and evaluate results
//
minbcreport rep;
alglib::minbcoptimize(state, function1_func);
minbcresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[-1,1]", 0.005);
//
// Check that OptGuard did not report errors
//
// Want to challenge OptGuard? Try to make your problem
// nonsmooth by replacing 100*(x+3)^4 by 100*|x+3| and
// re-run optimizer.
//
optguardreport ogrep;
minbcoptguardresults(state, ogrep);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minbc_numdiff");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minns_d_unconstrained
// Nonsmooth unconstrained optimization
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<15; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of
//
// f(x0,x1) = 2*|x0|+|x1|
//
// using nonsmooth nonlinear optimizer.
//
real_1d_array x0 = "[1,1]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x0);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x0);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x0);
real_1d_array s = "[1,1]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(s);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(s);
double epsx = 0.00001;
if( _spoil_scenario==6 )
epsx = fp_nan;
if( _spoil_scenario==7 )
epsx = fp_posinf;
if( _spoil_scenario==8 )
epsx = fp_neginf;
double radius = 0.1;
if( _spoil_scenario==9 )
radius = fp_nan;
if( _spoil_scenario==10 )
radius = fp_posinf;
if( _spoil_scenario==11 )
radius = fp_neginf;
double rho = 0.0;
if( _spoil_scenario==12 )
rho = fp_nan;
if( _spoil_scenario==13 )
rho = fp_posinf;
if( _spoil_scenario==14 )
rho = fp_neginf;
ae_int_t maxits = 0;
minnsstate state;
minnsreport rep;
real_1d_array x1;
//
// Create optimizer object, choose AGS algorithm and tune its settings:
// * radius=0.1 good initial value; will be automatically decreased later.
// * rho=0.0 penalty coefficient for nonlinear constraints; can be zero
// because we do not have such constraints
// * epsx=0.000001 stopping conditions
// * s=[1,1] all variables have unit scale
//
minnscreate(2, x0, state);
minnssetalgoags(state, radius, rho);
minnssetcond(state, epsx, maxits);
minnssetscale(state, s);
//
// Optimize and test results.
//
// Optimizer object accepts vector function and its Jacobian, with first
// component (Jacobian row) being target function, and next components
// (Jacobian rows) being nonlinear equality and inequality constraints
// (box/linear ones are passed separately by means of minnssetbc() and
// minnssetlc() calls).
//
// If you do not have nonlinear constraints (exactly our situation), then
// you will have one-component function vector and 1xN Jacobian matrix.
//
// So, our vector function has form
//
// {f0} = { 2*|x0|+|x1| }
//
// with Jacobian
//
// [ ]
// J = [ 2*sign(x0) sign(x1) ]
// [ ]
//
// NOTE: nonsmooth optimizer requires considerably more function
// evaluations than smooth solver - about 2N times more. Using
// numerical differentiation introduces additional (multiplicative)
// 2N speedup.
//
// It means that if smooth optimizer WITH user-supplied gradient
// needs 100 function evaluations to solve 50-dimensional problem,
// then AGS solver with user-supplied gradient will need about 10.000
// function evaluations, and with numerical gradient about 1.000.000
// function evaluations will be performed.
//
// NOTE: AGS solver used by us can handle nonsmooth and nonconvex
// optimization problems. It has convergence guarantees, i.e. it will
// converge to stationary point of the function after running for some
// time.
//
// However, it is important to remember that "stationary point" is not
// equal to "solution". If your problem is convex, everything is OK.
// But nonconvex optimization problems may have "flat spots" - large
// areas where gradient is exactly zero, but function value is far away
// from optimal. Such areas are stationary points too, and optimizer
// may be trapped here.
//
// "Flat spots" are nonsmooth equivalent of the saddle points, but with
// orders of magnitude worse properties - they may be quite large and
// hard to avoid. All nonsmooth optimizers are prone to this kind of the
// problem, because it is impossible to automatically distinguish "flat
// spot" from true solution.
//
// This note is here to warn you that you should be very careful when
// you solve nonsmooth optimization problems. Visual inspection of
// results is essential.
//
alglib::minnsoptimize(state, nsfunc1_jac);
minnsresults(state, x1, rep);
_TestResult = _TestResult && doc_test_real_vector(x1, "[0.0000,0.0000]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minns_d_unconstrained");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minns_d_diff
// Nonsmooth unconstrained optimization with numerical differentiation
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<18; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of
//
// f(x0,x1) = 2*|x0|+|x1|
//
// using nonsmooth nonlinear optimizer with numerical
// differentiation provided by ALGLIB.
//
// NOTE: nonsmooth optimizer requires considerably more function
// evaluations than smooth solver - about 2N times more. Using
// numerical differentiation introduces additional (multiplicative)
// 2N speedup.
//
// It means that if smooth optimizer WITH user-supplied gradient
// needs 100 function evaluations to solve 50-dimensional problem,
// then AGS solver with user-supplied gradient will need about 10.000
// function evaluations, and with numerical gradient about 1.000.000
// function evaluations will be performed.
//
real_1d_array x0 = "[1,1]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x0);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x0);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x0);
real_1d_array s = "[1,1]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(s);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(s);
double epsx = 0.00001;
if( _spoil_scenario==6 )
epsx = fp_nan;
if( _spoil_scenario==7 )
epsx = fp_posinf;
if( _spoil_scenario==8 )
epsx = fp_neginf;
double diffstep = 0.000001;
if( _spoil_scenario==9 )
diffstep = fp_nan;
if( _spoil_scenario==10 )
diffstep = fp_posinf;
if( _spoil_scenario==11 )
diffstep = fp_neginf;
double radius = 0.1;
if( _spoil_scenario==12 )
radius = fp_nan;
if( _spoil_scenario==13 )
radius = fp_posinf;
if( _spoil_scenario==14 )
radius = fp_neginf;
double rho = 0.0;
if( _spoil_scenario==15 )
rho = fp_nan;
if( _spoil_scenario==16 )
rho = fp_posinf;
if( _spoil_scenario==17 )
rho = fp_neginf;
ae_int_t maxits = 0;
minnsstate state;
minnsreport rep;
real_1d_array x1;
//
// Create optimizer object, choose AGS algorithm and tune its settings:
// * radius=0.1 good initial value; will be automatically decreased later.
// * rho=0.0 penalty coefficient for nonlinear constraints; can be zero
// because we do not have such constraints
// * epsx=0.000001 stopping conditions
// * s=[1,1] all variables have unit scale
//
minnscreatef(2, x0, diffstep, state);
minnssetalgoags(state, radius, rho);
minnssetcond(state, epsx, maxits);
minnssetscale(state, s);
//
// Optimize and test results.
//
// Optimizer object accepts vector function, with first component
// being target function, and next components being nonlinear equality
// and inequality constraints (box/linear ones are passed separately
// by means of minnssetbc() and minnssetlc() calls).
//
// If you do not have nonlinear constraints (exactly our situation), then
// you will have one-component function vector.
//
// So, our vector function has form
//
// {f0} = { 2*|x0|+|x1| }
//
alglib::minnsoptimize(state, nsfunc1_fvec);
minnsresults(state, x1, rep);
_TestResult = _TestResult && doc_test_real_vector(x1, "[0.0000,0.0000]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minns_d_diff");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minns_d_bc
// Nonsmooth box constrained optimization
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<17; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of
//
// f(x0,x1) = 2*|x0|+|x1|
//
// subject to box constraints
//
// 1 <= x0 < +INF
// -INF <= x1 < +INF
//
// using nonsmooth nonlinear optimizer.
//
real_1d_array x0 = "[1,1]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x0);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x0);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x0);
real_1d_array s = "[1,1]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(s);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(s);
real_1d_array bndl = "[1,-inf]";
if( _spoil_scenario==6 )
spoil_vector_by_nan(bndl);
real_1d_array bndu = "[+inf,+inf]";
if( _spoil_scenario==7 )
spoil_vector_by_nan(bndu);
double epsx = 0.00001;
if( _spoil_scenario==8 )
epsx = fp_nan;
if( _spoil_scenario==9 )
epsx = fp_posinf;
if( _spoil_scenario==10 )
epsx = fp_neginf;
double radius = 0.1;
if( _spoil_scenario==11 )
radius = fp_nan;
if( _spoil_scenario==12 )
radius = fp_posinf;
if( _spoil_scenario==13 )
radius = fp_neginf;
double rho = 0.0;
if( _spoil_scenario==14 )
rho = fp_nan;
if( _spoil_scenario==15 )
rho = fp_posinf;
if( _spoil_scenario==16 )
rho = fp_neginf;
ae_int_t maxits = 0;
minnsstate state;
minnsreport rep;
real_1d_array x1;
//
// Create optimizer object, choose AGS algorithm and tune its settings:
// * radius=0.1 good initial value; will be automatically decreased later.
// * rho=0.0 penalty coefficient for nonlinear constraints; can be zero
// because we do not have such constraints
// * epsx=0.000001 stopping conditions
// * s=[1,1] all variables have unit scale
//
minnscreate(2, x0, state);
minnssetalgoags(state, radius, rho);
minnssetcond(state, epsx, maxits);
minnssetscale(state, s);
//
// Set box constraints.
//
// General linear constraints are set in similar way (see comments on
// minnssetlc() function for more information).
//
// You may combine box, linear and nonlinear constraints in one optimization
// problem.
//
minnssetbc(state, bndl, bndu);
//
// Optimize and test results.
//
// Optimizer object accepts vector function and its Jacobian, with first
// component (Jacobian row) being target function, and next components
// (Jacobian rows) being nonlinear equality and inequality constraints
// (box/linear ones are passed separately by means of minnssetbc() and
// minnssetlc() calls).
//
// If you do not have nonlinear constraints (exactly our situation), then
// you will have one-component function vector and 1xN Jacobian matrix.
//
// So, our vector function has form
//
// {f0} = { 2*|x0|+|x1| }
//
// with Jacobian
//
// [ ]
// J = [ 2*sign(x0) sign(x1) ]
// [ ]
//
// NOTE: nonsmooth optimizer requires considerably more function
// evaluations than smooth solver - about 2N times more. Using
// numerical differentiation introduces additional (multiplicative)
// 2N speedup.
//
// It means that if smooth optimizer WITH user-supplied gradient
// needs 100 function evaluations to solve 50-dimensional problem,
// then AGS solver with user-supplied gradient will need about 10.000
// function evaluations, and with numerical gradient about 1.000.000
// function evaluations will be performed.
//
// NOTE: AGS solver used by us can handle nonsmooth and nonconvex
// optimization problems. It has convergence guarantees, i.e. it will
// converge to stationary point of the function after running for some
// time.
//
// However, it is important to remember that "stationary point" is not
// equal to "solution". If your problem is convex, everything is OK.
// But nonconvex optimization problems may have "flat spots" - large
// areas where gradient is exactly zero, but function value is far away
// from optimal. Such areas are stationary points too, and optimizer
// may be trapped here.
//
// "Flat spots" are nonsmooth equivalent of the saddle points, but with
// orders of magnitude worse properties - they may be quite large and
// hard to avoid. All nonsmooth optimizers are prone to this kind of the
// problem, because it is impossible to automatically distinguish "flat
// spot" from true solution.
//
// This note is here to warn you that you should be very careful when
// you solve nonsmooth optimization problems. Visual inspection of
// results is essential.
//
//
alglib::minnsoptimize(state, nsfunc1_jac);
minnsresults(state, x1, rep);
_TestResult = _TestResult && doc_test_real_vector(x1, "[1.0000,0.0000]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minns_d_bc");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minns_d_nlc
// Nonsmooth nonlinearly constrained optimization
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<15; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of
//
// f(x0,x1) = 2*|x0|+|x1|
//
// subject to combination of equality and inequality constraints
//
// x0 = 1
// x1 >= -1
//
// using nonsmooth nonlinear optimizer. Although these constraints
// are linear, we treat them as general nonlinear ones in order to
// demonstrate nonlinearly constrained optimization setup.
//
real_1d_array x0 = "[1,1]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x0);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x0);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x0);
real_1d_array s = "[1,1]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(s);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(s);
double epsx = 0.00001;
if( _spoil_scenario==6 )
epsx = fp_nan;
if( _spoil_scenario==7 )
epsx = fp_posinf;
if( _spoil_scenario==8 )
epsx = fp_neginf;
double radius = 0.1;
if( _spoil_scenario==9 )
radius = fp_nan;
if( _spoil_scenario==10 )
radius = fp_posinf;
if( _spoil_scenario==11 )
radius = fp_neginf;
double rho = 50.0;
if( _spoil_scenario==12 )
rho = fp_nan;
if( _spoil_scenario==13 )
rho = fp_posinf;
if( _spoil_scenario==14 )
rho = fp_neginf;
ae_int_t maxits = 0;
minnsstate state;
minnsreport rep;
real_1d_array x1;
//
// Create optimizer object, choose AGS algorithm and tune its settings:
// * radius=0.1 good initial value; will be automatically decreased later.
// * rho=50.0 penalty coefficient for nonlinear constraints. It is your
// responsibility to choose good one - large enough that it
// enforces constraints, but small enough in order to avoid
// extreme slowdown due to ill-conditioning.
// * epsx=0.000001 stopping conditions
// * s=[1,1] all variables have unit scale
//
minnscreate(2, x0, state);
minnssetalgoags(state, radius, rho);
minnssetcond(state, epsx, maxits);
minnssetscale(state, s);
//
// Set general nonlinear constraints.
//
// This part is more tricky than working with box/linear constraints - you
// can not "pack" general nonlinear function into double precision array.
// That's why minnssetnlc() does not accept constraints itself - only
// constraint COUNTS are passed: first parameter is number of equality
// constraints, second one is number of inequality constraints.
//
// As for constraining functions - these functions are passed as part
// of problem Jacobian (see below).
//
// NOTE: MinNS optimizer supports arbitrary combination of boundary, general
// linear and general nonlinear constraints. This example does not
// show how to work with general linear constraints, but you can
// easily find it in documentation on minnlcsetlc() function.
//
minnssetnlc(state, 1, 1);
//
// Optimize and test results.
//
// Optimizer object accepts vector function and its Jacobian, with first
// component (Jacobian row) being target function, and next components
// (Jacobian rows) being nonlinear equality and inequality constraints
// (box/linear ones are passed separately by means of minnssetbc() and
// minnssetlc() calls).
//
// Nonlinear equality constraints have form Gi(x)=0, inequality ones
// have form Hi(x)<=0, so we may have to "normalize" constraints prior
// to passing them to optimizer (right side is zero, constraints are
// sorted, multiplied by -1 when needed).
//
// So, our vector function has form
//
// {f0,f1,f2} = { 2*|x0|+|x1|, x0-1, -x1-1 }
//
// with Jacobian
//
// [ 2*sign(x0) sign(x1) ]
// J = [ 1 0 ]
// [ 0 -1 ]
//
// which means that we have optimization problem
//
// min{f0} subject to f1=0, f2<=0
//
// which is essentially same as
//
// min { 2*|x0|+|x1| } subject to x0=1, x1>=-1
//
// NOTE: AGS solver used by us can handle nonsmooth and nonconvex
// optimization problems. It has convergence guarantees, i.e. it will
// converge to stationary point of the function after running for some
// time.
//
// However, it is important to remember that "stationary point" is not
// equal to "solution". If your problem is convex, everything is OK.
// But nonconvex optimization problems may have "flat spots" - large
// areas where gradient is exactly zero, but function value is far away
// from optimal. Such areas are stationary points too, and optimizer
// may be trapped here.
//
// "Flat spots" are nonsmooth equivalent of the saddle points, but with
// orders of magnitude worse properties - they may be quite large and
// hard to avoid. All nonsmooth optimizers are prone to this kind of the
// problem, because it is impossible to automatically distinguish "flat
// spot" from true solution.
//
// This note is here to warn you that you should be very careful when
// you solve nonsmooth optimization problems. Visual inspection of
// results is essential.
//
alglib::minnsoptimize(state, nsfunc2_jac);
minnsresults(state, x1, rep);
_TestResult = _TestResult && doc_test_real_vector(x1, "[1.0000,0.0000]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minns_d_nlc");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST mincg_d_1
// Nonlinear optimization by CG
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<15; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of
//
// f(x,y) = 100*(x+3)^4+(y-3)^4
//
// using nonlinear conjugate gradient method with:
// * initial point x=[0,0]
// * unit scale being set for all variables (see mincgsetscale for more info)
// * stopping criteria set to "terminate after short enough step"
// * OptGuard integrity check being used to check problem statement
// for some common errors like nonsmoothness or bad analytic gradient
//
// First, we create optimizer object and tune its properties
//
real_1d_array x = "[0,0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
real_1d_array s = "[1,1]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(s);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(s);
double epsg = 0;
if( _spoil_scenario==6 )
epsg = fp_nan;
if( _spoil_scenario==7 )
epsg = fp_posinf;
if( _spoil_scenario==8 )
epsg = fp_neginf;
double epsf = 0;
if( _spoil_scenario==9 )
epsf = fp_nan;
if( _spoil_scenario==10 )
epsf = fp_posinf;
if( _spoil_scenario==11 )
epsf = fp_neginf;
double epsx = 0.0000000001;
if( _spoil_scenario==12 )
epsx = fp_nan;
if( _spoil_scenario==13 )
epsx = fp_posinf;
if( _spoil_scenario==14 )
epsx = fp_neginf;
ae_int_t maxits = 0;
mincgstate state;
mincgcreate(x, state);
mincgsetcond(state, epsg, epsf, epsx, maxits);
mincgsetscale(state, s);
//
// Activate OptGuard integrity checking.
//
// OptGuard monitor helps to catch common coding and problem statement
// issues, like:
// * discontinuity of the target function (C0 continuity violation)
// * nonsmoothness of the target function (C1 continuity violation)
// * erroneous analytic gradient, i.e. one inconsistent with actual
// change in the target/constraints
//
// OptGuard is essential for early prototyping stages because such
// problems often result in premature termination of the optimizer
// which is really hard to distinguish from the correct termination.
//
// IMPORTANT: GRADIENT VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL
// DIFFERENTIATION. DO NOT USE IT IN PRODUCTION CODE!!!!!!!
//
// Other OptGuard checks add moderate overhead, but anyway
// it is better to turn them off when they are not needed.
//
mincgoptguardsmoothness(state);
mincgoptguardgradient(state, 0.001);
//
// Optimize and evaluate results
//
mincgreport rep;
alglib::mincgoptimize(state, function1_grad);
mincgresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[-3,3]", 0.005);
//
// Check that OptGuard did not report errors
//
// NOTE: want to test OptGuard? Try breaking the gradient - say, add
// 1.0 to some of its components.
//
optguardreport ogrep;
mincgoptguardresults(state, ogrep);
_TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "mincg_d_1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST mincg_d_2
// Nonlinear optimization with additional settings and restarts
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<21; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of f(x,y) = 100*(x+3)^4+(y-3)^4
// with nonlinear conjugate gradient method.
//
// Several advanced techniques are demonstrated:
// * upper limit on step size
// * restart from new point
//
real_1d_array x = "[0,0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
real_1d_array s = "[1,1]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(s);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(s);
double epsg = 0;
if( _spoil_scenario==6 )
epsg = fp_nan;
if( _spoil_scenario==7 )
epsg = fp_posinf;
if( _spoil_scenario==8 )
epsg = fp_neginf;
double epsf = 0;
if( _spoil_scenario==9 )
epsf = fp_nan;
if( _spoil_scenario==10 )
epsf = fp_posinf;
if( _spoil_scenario==11 )
epsf = fp_neginf;
double epsx = 0.0000000001;
if( _spoil_scenario==12 )
epsx = fp_nan;
if( _spoil_scenario==13 )
epsx = fp_posinf;
if( _spoil_scenario==14 )
epsx = fp_neginf;
double stpmax = 0.1;
if( _spoil_scenario==15 )
stpmax = fp_nan;
if( _spoil_scenario==16 )
stpmax = fp_posinf;
if( _spoil_scenario==17 )
stpmax = fp_neginf;
ae_int_t maxits = 0;
mincgstate state;
mincgreport rep;
// create and tune optimizer
mincgcreate(x, state);
mincgsetscale(state, s);
mincgsetcond(state, epsg, epsf, epsx, maxits);
mincgsetstpmax(state, stpmax);
// Set up OptGuard integrity checker which catches errors
// like nonsmooth targets or errors in the analytic gradient.
//
// OptGuard is essential at the early prototyping stages.
//
// NOTE: gradient verification needs 3*N additional function
// evaluations; DO NOT USE IT IN THE PRODUCTION CODE
// because it leads to unnecessary slowdown of your app.
mincgoptguardsmoothness(state);
mincgoptguardgradient(state, 0.001);
// first run
alglib::mincgoptimize(state, function1_grad);
mincgresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[-3,3]", 0.005);
// second run - algorithm is restarted with mincgrestartfrom()
x = "[10,10]";
if( _spoil_scenario==18 )
spoil_vector_by_nan(x);
if( _spoil_scenario==19 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==20 )
spoil_vector_by_neginf(x);
mincgrestartfrom(state, x);
alglib::mincgoptimize(state, function1_grad);
mincgresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[-3,3]", 0.005);
// check OptGuard integrity report. Why do we need it at all?
// Well, try breaking the gradient by adding 1.0 to some
// of its components - OptGuard should report it as error.
// And it may also catch unintended errors too :)
optguardreport ogrep;
mincgoptguardresults(state, ogrep);
_TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "mincg_d_2");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST mincg_numdiff
// Nonlinear optimization by CG with numerical differentiation
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<18; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of
//
// f(x,y) = 100*(x+3)^4+(y-3)^4
//
// using numerical differentiation to calculate gradient.
//
// We also show how to use OptGuard integrity checker to catch common
// problem statement errors like accidentally specifying nonsmooth target
// function.
//
// First, we set up optimizer...
//
real_1d_array x = "[0,0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
real_1d_array s = "[1,1]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(s);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(s);
double epsg = 0;
if( _spoil_scenario==6 )
epsg = fp_nan;
if( _spoil_scenario==7 )
epsg = fp_posinf;
if( _spoil_scenario==8 )
epsg = fp_neginf;
double epsf = 0;
if( _spoil_scenario==9 )
epsf = fp_nan;
if( _spoil_scenario==10 )
epsf = fp_posinf;
if( _spoil_scenario==11 )
epsf = fp_neginf;
double epsx = 0.0000000001;
if( _spoil_scenario==12 )
epsx = fp_nan;
if( _spoil_scenario==13 )
epsx = fp_posinf;
if( _spoil_scenario==14 )
epsx = fp_neginf;
double diffstep = 1.0e-6;
if( _spoil_scenario==15 )
diffstep = fp_nan;
if( _spoil_scenario==16 )
diffstep = fp_posinf;
if( _spoil_scenario==17 )
diffstep = fp_neginf;
ae_int_t maxits = 0;
mincgstate state;
mincgcreatef(x, diffstep, state);
mincgsetcond(state, epsg, epsf, epsx, maxits);
mincgsetscale(state, s);
//
// Then, we activate OptGuard integrity checking.
//
// Numerical differentiation always produces "correct" gradient
// (with some truncation error, but unbiased). Thus, we just have
// to check smoothness properties of the target: C0 and C1 continuity.
//
// Sometimes user accidentally tried to solve nonsmooth problems
// with smooth optimizer. OptGuard helps to detect such situations
// early, at the prototyping stage.
//
mincgoptguardsmoothness(state);
//
// Now we are ready to run the optimization
//
mincgreport rep;
alglib::mincgoptimize(state, function1_func);
mincgresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[-3,3]", 0.005);
//
// ...and to check OptGuard integrity report.
//
// Want to challenge OptGuard? Try to make your problem
// nonsmooth by replacing 100*(x+3)^4 by 100*|x+3| and
// re-run optimizer.
//
optguardreport ogrep;
mincgoptguardresults(state, ogrep);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc0suspected, false);
_TestResult = _TestResult && doc_test_bool(ogrep.nonc1suspected, false);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "mincg_numdiff");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minlm_d_v
// Nonlinear least squares optimization using function vector only
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<9; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of F(x0,x1) = f0^2+f1^2, where
//
// f0(x0,x1) = 10*(x0+3)^2
// f1(x0,x1) = (x1-3)^2
//
// using "V" mode of the Levenberg-Marquardt optimizer.
//
// Optimization algorithm uses:
// * function vector f[] = {f1,f2}
//
// No other information (Jacobian, gradient, etc.) is needed.
//
real_1d_array x = "[0,0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
real_1d_array s = "[1,1]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(s);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(s);
double epsx = 0.0000000001;
if( _spoil_scenario==6 )
epsx = fp_nan;
if( _spoil_scenario==7 )
epsx = fp_posinf;
if( _spoil_scenario==8 )
epsx = fp_neginf;
ae_int_t maxits = 0;
minlmstate state;
minlmreport rep;
//
// Create optimizer, tell it to:
// * use numerical differentiation with step equal to 0.0001
// * use unit scale for all variables (s is a unit vector)
// * stop after short enough step (less than epsx)
//
minlmcreatev(2, x, 0.0001, state);
minlmsetcond(state, epsx, maxits);
minlmsetscale(state, s);
//
// Optimize
//
alglib::minlmoptimize(state, function1_fvec);
//
// Test optimization results
//
// NOTE: because we use numerical differentiation, we do not
// verify Jacobian correctness - it is always "correct".
// However, if you switch to analytic gradient, consider
// checking it with OptGuard (see other examples).
//
minlmresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[-3,+3]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minlm_d_v");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minlm_d_vj
// Nonlinear least squares optimization using function vector and Jacobian
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<9; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of F(x0,x1) = f0^2+f1^2, where
//
// f0(x0,x1) = 10*(x0+3)^2
// f1(x0,x1) = (x1-3)^2
//
// using "VJ" mode of the Levenberg-Marquardt optimizer.
//
// Optimization algorithm uses:
// * function vector f[] = {f1,f2}
// * Jacobian matrix J = {dfi/dxj}.
//
real_1d_array x = "[0,0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
real_1d_array s = "[1,1]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(s);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(s);
double epsx = 0.0000000001;
if( _spoil_scenario==6 )
epsx = fp_nan;
if( _spoil_scenario==7 )
epsx = fp_posinf;
if( _spoil_scenario==8 )
epsx = fp_neginf;
ae_int_t maxits = 0;
minlmstate state;
//
// Create optimizer, tell it to:
// * use analytic gradient provided by user
// * use unit scale for all variables (s is a unit vector)
// * stop after short enough step (less than epsx)
//
minlmcreatevj(2, x, state);
minlmsetcond(state, epsx, maxits);
minlmsetscale(state, s);
//
// Activate OptGuard integrity checking.
//
// OptGuard monitor helps to detect erroneous analytic Jacobian,
// i.e. one inconsistent with actual change in the target function.
//
// OptGuard is essential for early prototyping stages because such
// problems often result in premature termination of the optimizer
// which is really hard to distinguish from the correct termination.
//
// IMPORTANT: JACOBIAN VERIFICATION IS PERFORMED BY MEANS OF NUMERICAL
// DIFFERENTIATION, THUS DO NOT USE IT IN PRODUCTION CODE!
//
minlmoptguardgradient(state, 0.001);
//
// Optimize
//
alglib::minlmoptimize(state, function1_fvec, function1_jac);
//
// Test optimization results
//
minlmreport rep;
minlmresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[-3,+3]", 0.005);
//
// Check that OptGuard did not report errors
//
// NOTE: want to test OptGuard? Try breaking the Jacobian - say, add
// 1.0 to some of its components.
//
// NOTE: unfortunately, specifics of LM optimization do not allow us
// to detect errors like nonsmoothness (like we do with other
// optimizers). So, only Jacobian correctness is verified.
//
optguardreport ogrep;
minlmoptguardresults(state, ogrep);
_TestResult = _TestResult && doc_test_bool(ogrep.badgradsuspected, false);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minlm_d_vj");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minlm_d_fgh
// Nonlinear Hessian-based optimization for general functions
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<6; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of F(x0,x1) = 100*(x0+3)^4+(x1-3)^4
// using "FGH" mode of the Levenberg-Marquardt optimizer.
//
// F is treated like a monolitic function without internal structure,
// i.e. we do NOT represent it as a sum of squares.
//
// Optimization algorithm uses:
// * function value F(x0,x1)
// * gradient G={dF/dxi}
// * Hessian H={d2F/(dxi*dxj)}
//
real_1d_array x = "[0,0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
double epsx = 0.0000000001;
if( _spoil_scenario==3 )
epsx = fp_nan;
if( _spoil_scenario==4 )
epsx = fp_posinf;
if( _spoil_scenario==5 )
epsx = fp_neginf;
ae_int_t maxits = 0;
minlmstate state;
minlmreport rep;
minlmcreatefgh(x, state);
minlmsetcond(state, epsx, maxits);
alglib::minlmoptimize(state, function1_func, function1_grad, function1_hess);
minlmresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[-3,+3]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minlm_d_fgh");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minlm_d_vb
// Bound constrained nonlinear least squares optimization
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<13; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of F(x0,x1) = f0^2+f1^2, where
//
// f0(x0,x1) = 10*(x0+3)^2
// f1(x0,x1) = (x1-3)^2
//
// with boundary constraints
//
// -1 <= x0 <= +1
// -1 <= x1 <= +1
//
// using "V" mode of the Levenberg-Marquardt optimizer.
//
// Optimization algorithm uses:
// * function vector f[] = {f1,f2}
//
// No other information (Jacobian, gradient, etc.) is needed.
//
real_1d_array x = "[0,0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
real_1d_array s = "[1,1]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(s);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(s);
real_1d_array bndl = "[-1,-1]";
if( _spoil_scenario==6 )
spoil_vector_by_nan(bndl);
if( _spoil_scenario==7 )
spoil_vector_by_deleting_element(bndl);
real_1d_array bndu = "[+1,+1]";
if( _spoil_scenario==8 )
spoil_vector_by_nan(bndu);
if( _spoil_scenario==9 )
spoil_vector_by_deleting_element(bndu);
double epsx = 0.0000000001;
if( _spoil_scenario==10 )
epsx = fp_nan;
if( _spoil_scenario==11 )
epsx = fp_posinf;
if( _spoil_scenario==12 )
epsx = fp_neginf;
ae_int_t maxits = 0;
minlmstate state;
//
// Create optimizer, tell it to:
// * use numerical differentiation with step equal to 1.0
// * use unit scale for all variables (s is a unit vector)
// * stop after short enough step (less than epsx)
// * set box constraints
//
minlmcreatev(2, x, 0.0001, state);
minlmsetbc(state, bndl, bndu);
minlmsetcond(state, epsx, maxits);
minlmsetscale(state, s);
//
// Optimize
//
alglib::minlmoptimize(state, function1_fvec);
//
// Test optimization results
//
// NOTE: because we use numerical differentiation, we do not
// verify Jacobian correctness - it is always "correct".
// However, if you switch to analytic gradient, consider
// checking it with OptGuard (see other examples).
//
minlmreport rep;
minlmresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[-1,+1]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minlm_d_vb");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minlm_d_restarts
// Efficient restarts of LM optimizer
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<9; _spoil_scenario++)
{
try
{
//
// This example demonstrates minimization of F(x0,x1) = f0^2+f1^2, where
//
// f0(x0,x1) = 10*(x0+3)^2
// f1(x0,x1) = (x1-3)^2
//
// using several starting points and efficient restarts.
//
real_1d_array x;
double epsx = 0.0000000001;
if( _spoil_scenario==0 )
epsx = fp_nan;
if( _spoil_scenario==1 )
epsx = fp_posinf;
if( _spoil_scenario==2 )
epsx = fp_neginf;
ae_int_t maxits = 0;
minlmstate state;
minlmreport rep;
//
// create optimizer using minlmcreatev()
//
x = "[10,10]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(x);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(x);
minlmcreatev(2, x, 0.0001, state);
minlmsetcond(state, epsx, maxits);
alglib::minlmoptimize(state, function1_fvec);
minlmresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[-3,+3]", 0.005);
//
// restart optimizer using minlmrestartfrom()
//
// we can use different starting point, different function,
// different stopping conditions, but problem size
// must remain unchanged.
//
x = "[4,4]";
if( _spoil_scenario==6 )
spoil_vector_by_nan(x);
if( _spoil_scenario==7 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==8 )
spoil_vector_by_neginf(x);
minlmrestartfrom(state, x);
alglib::minlmoptimize(state, function2_fvec);
minlmresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[0,1]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minlm_d_restarts");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minlm_t_1
// Nonlinear least squares optimization, FJ scheme (obsolete, but supported)
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<6; _spoil_scenario++)
{
try
{
real_1d_array x = "[0,0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
double epsx = 0.0000000001;
if( _spoil_scenario==3 )
epsx = fp_nan;
if( _spoil_scenario==4 )
epsx = fp_posinf;
if( _spoil_scenario==5 )
epsx = fp_neginf;
ae_int_t maxits = 0;
minlmstate state;
minlmreport rep;
minlmcreatefj(2, x, state);
minlmsetcond(state, epsx, maxits);
alglib::minlmoptimize(state, function1_func, function1_jac);
minlmresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[-3,+3]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minlm_t_1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST minlm_t_2
// Nonlinear least squares optimization, FGJ scheme (obsolete, but supported)
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<6; _spoil_scenario++)
{
try
{
real_1d_array x = "[0,0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
double epsx = 0.0000000001;
if( _spoil_scenario==3 )
epsx = fp_nan;
if( _spoil_scenario==4 )
epsx = fp_posinf;
if( _spoil_scenario==5 )
epsx = fp_neginf;
ae_int_t maxits = 0;
minlmstate state;
minlmreport rep;
minlmcreatefgj(2, x, state);
minlmsetcond(state, epsx, maxits);
alglib::minlmoptimize(state, function1_func, function1_grad, function1_jac);
minlmresults(state, x, rep);
_TestResult = _TestResult && doc_test_real_vector(x, "[-3,+3]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "minlm_t_2");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST basestat_d_base
// Basic functionality (moments, adev, median, percentile)
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<6; _spoil_scenario++)
{
try
{
real_1d_array x = "[0,1,4,9,16,25,36,49,64,81]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
double mean;
double variance;
double skewness;
double kurtosis;
double adev;
double p;
double v;
//
// Here we demonstrate calculation of sample moments
// (mean, variance, skewness, kurtosis)
//
samplemoments(x, mean, variance, skewness, kurtosis);
_TestResult = _TestResult && doc_test_real(mean, 28.5, 0.01);
_TestResult = _TestResult && doc_test_real(variance, 801.1667, 0.01);
_TestResult = _TestResult && doc_test_real(skewness, 0.5751, 0.01);
_TestResult = _TestResult && doc_test_real(kurtosis, -1.2666, 0.01);
//
// Average deviation
//
sampleadev(x, adev);
_TestResult = _TestResult && doc_test_real(adev, 23.2, 0.01);
//
// Median and percentile
//
samplemedian(x, v);
_TestResult = _TestResult && doc_test_real(v, 20.5, 0.01);
p = 0.5;
if( _spoil_scenario==3 )
p = fp_nan;
if( _spoil_scenario==4 )
p = fp_posinf;
if( _spoil_scenario==5 )
p = fp_neginf;
samplepercentile(x, p, v);
_TestResult = _TestResult && doc_test_real(v, 20.5, 0.01);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "basestat_d_base");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST basestat_d_c2
// Correlation (covariance) between two random variables
//
printf("50/151\n");
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<10; _spoil_scenario++)
{
try
{
//
// We have two samples - x and y, and want to measure dependency between them
//
real_1d_array x = "[0,1,4,9,16,25,36,49,64,81]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_adding_element(x);
if( _spoil_scenario==4 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[0,1,2,3,4,5,6,7,8,9]";
if( _spoil_scenario==5 )
spoil_vector_by_nan(y);
if( _spoil_scenario==6 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==7 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==8 )
spoil_vector_by_adding_element(y);
if( _spoil_scenario==9 )
spoil_vector_by_deleting_element(y);
double v;
//
// Three dependency measures are calculated:
// * covariation
// * Pearson correlation
// * Spearman rank correlation
//
v = cov2(x, y);
_TestResult = _TestResult && doc_test_real(v, 82.5, 0.001);
v = pearsoncorr2(x, y);
_TestResult = _TestResult && doc_test_real(v, 0.9627, 0.001);
v = spearmancorr2(x, y);
_TestResult = _TestResult && doc_test_real(v, 1.000, 0.001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "basestat_d_c2");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST basestat_d_cm
// Correlation (covariance) between components of random vector
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// X is a sample matrix:
// * I-th row corresponds to I-th observation
// * J-th column corresponds to J-th variable
//
real_2d_array x = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(x);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(x);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(x);
real_2d_array c;
//
// Three dependency measures are calculated:
// * covariation
// * Pearson correlation
// * Spearman rank correlation
//
// Result is stored into C, with C[i,j] equal to correlation
// (covariance) between I-th and J-th variables of X.
//
covm(x, c);
_TestResult = _TestResult && doc_test_real_matrix(c, "[[1.80,0.60,-1.40],[0.60,0.70,-0.80],[-1.40,-0.80,14.70]]", 0.01);
pearsoncorrm(x, c);
_TestResult = _TestResult && doc_test_real_matrix(c, "[[1.000,0.535,-0.272],[0.535,1.000,-0.249],[-0.272,-0.249,1.000]]", 0.01);
spearmancorrm(x, c);
_TestResult = _TestResult && doc_test_real_matrix(c, "[[1.000,0.556,-0.306],[0.556,1.000,-0.750],[-0.306,-0.750,1.000]]", 0.01);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "basestat_d_cm");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST basestat_d_cm2
// Correlation (covariance) between two random vectors
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<6; _spoil_scenario++)
{
try
{
//
// X and Y are sample matrices:
// * I-th row corresponds to I-th observation
// * J-th column corresponds to J-th variable
//
real_2d_array x = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(x);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(x);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(x);
real_2d_array y = "[[2,3],[2,1],[-1,6],[-9,9],[7,1]]";
if( _spoil_scenario==3 )
spoil_matrix_by_nan(y);
if( _spoil_scenario==4 )
spoil_matrix_by_posinf(y);
if( _spoil_scenario==5 )
spoil_matrix_by_neginf(y);
real_2d_array c;
//
// Three dependency measures are calculated:
// * covariation
// * Pearson correlation
// * Spearman rank correlation
//
// Result is stored into C, with C[i,j] equal to correlation
// (covariance) between I-th variable of X and J-th variable of Y.
//
covm2(x, y, c);
_TestResult = _TestResult && doc_test_real_matrix(c, "[[4.100,-3.250],[2.450,-1.500],[13.450,-5.750]]", 0.01);
pearsoncorrm2(x, y, c);
_TestResult = _TestResult && doc_test_real_matrix(c, "[[0.519,-0.699],[0.497,-0.518],[0.596,-0.433]]", 0.01);
spearmancorrm2(x, y, c);
_TestResult = _TestResult && doc_test_real_matrix(c, "[[0.541,-0.649],[0.216,-0.433],[0.433,-0.135]]", 0.01);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "basestat_d_cm2");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST basestat_t_base
// Tests ability to detect errors in inputs
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<34; _spoil_scenario++)
{
try
{
double mean;
double variance;
double skewness;
double kurtosis;
double adev;
double p;
double v;
//
// first, we test short form of functions
//
real_1d_array x1 = "[0,1,4,9,16,25,36,49,64,81]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x1);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x1);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x1);
samplemoments(x1, mean, variance, skewness, kurtosis);
real_1d_array x2 = "[0,1,4,9,16,25,36,49,64,81]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(x2);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(x2);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(x2);
sampleadev(x2, adev);
real_1d_array x3 = "[0,1,4,9,16,25,36,49,64,81]";
if( _spoil_scenario==6 )
spoil_vector_by_nan(x3);
if( _spoil_scenario==7 )
spoil_vector_by_posinf(x3);
if( _spoil_scenario==8 )
spoil_vector_by_neginf(x3);
samplemedian(x3, v);
real_1d_array x4 = "[0,1,4,9,16,25,36,49,64,81]";
if( _spoil_scenario==9 )
spoil_vector_by_nan(x4);
if( _spoil_scenario==10 )
spoil_vector_by_posinf(x4);
if( _spoil_scenario==11 )
spoil_vector_by_neginf(x4);
p = 0.5;
if( _spoil_scenario==12 )
p = fp_nan;
if( _spoil_scenario==13 )
p = fp_posinf;
if( _spoil_scenario==14 )
p = fp_neginf;
samplepercentile(x4, p, v);
//
// and then we test full form
//
real_1d_array x5 = "[0,1,4,9,16,25,36,49,64,81]";
if( _spoil_scenario==15 )
spoil_vector_by_nan(x5);
if( _spoil_scenario==16 )
spoil_vector_by_posinf(x5);
if( _spoil_scenario==17 )
spoil_vector_by_neginf(x5);
if( _spoil_scenario==18 )
spoil_vector_by_deleting_element(x5);
samplemoments(x5, 10, mean, variance, skewness, kurtosis);
real_1d_array x6 = "[0,1,4,9,16,25,36,49,64,81]";
if( _spoil_scenario==19 )
spoil_vector_by_nan(x6);
if( _spoil_scenario==20 )
spoil_vector_by_posinf(x6);
if( _spoil_scenario==21 )
spoil_vector_by_neginf(x6);
if( _spoil_scenario==22 )
spoil_vector_by_deleting_element(x6);
sampleadev(x6, 10, adev);
real_1d_array x7 = "[0,1,4,9,16,25,36,49,64,81]";
if( _spoil_scenario==23 )
spoil_vector_by_nan(x7);
if( _spoil_scenario==24 )
spoil_vector_by_posinf(x7);
if( _spoil_scenario==25 )
spoil_vector_by_neginf(x7);
if( _spoil_scenario==26 )
spoil_vector_by_deleting_element(x7);
samplemedian(x7, 10, v);
real_1d_array x8 = "[0,1,4,9,16,25,36,49,64,81]";
if( _spoil_scenario==27 )
spoil_vector_by_nan(x8);
if( _spoil_scenario==28 )
spoil_vector_by_posinf(x8);
if( _spoil_scenario==29 )
spoil_vector_by_neginf(x8);
if( _spoil_scenario==30 )
spoil_vector_by_deleting_element(x8);
p = 0.5;
if( _spoil_scenario==31 )
p = fp_nan;
if( _spoil_scenario==32 )
p = fp_posinf;
if( _spoil_scenario==33 )
p = fp_neginf;
samplepercentile(x8, 10, p, v);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "basestat_t_base");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST basestat_t_covcorr
// Tests ability to detect errors in inputs
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<126; _spoil_scenario++)
{
try
{
double v;
real_2d_array c;
//
// 2-sample short-form cov/corr are tested
//
real_1d_array x1 = "[0,1,4,9,16,25,36,49,64,81]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x1);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x1);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x1);
if( _spoil_scenario==3 )
spoil_vector_by_adding_element(x1);
if( _spoil_scenario==4 )
spoil_vector_by_deleting_element(x1);
real_1d_array y1 = "[0,1,2,3,4,5,6,7,8,9]";
if( _spoil_scenario==5 )
spoil_vector_by_nan(y1);
if( _spoil_scenario==6 )
spoil_vector_by_posinf(y1);
if( _spoil_scenario==7 )
spoil_vector_by_neginf(y1);
if( _spoil_scenario==8 )
spoil_vector_by_adding_element(y1);
if( _spoil_scenario==9 )
spoil_vector_by_deleting_element(y1);
v = cov2(x1, y1);
real_1d_array x2 = "[0,1,4,9,16,25,36,49,64,81]";
if( _spoil_scenario==10 )
spoil_vector_by_nan(x2);
if( _spoil_scenario==11 )
spoil_vector_by_posinf(x2);
if( _spoil_scenario==12 )
spoil_vector_by_neginf(x2);
if( _spoil_scenario==13 )
spoil_vector_by_adding_element(x2);
if( _spoil_scenario==14 )
spoil_vector_by_deleting_element(x2);
real_1d_array y2 = "[0,1,2,3,4,5,6,7,8,9]";
if( _spoil_scenario==15 )
spoil_vector_by_nan(y2);
if( _spoil_scenario==16 )
spoil_vector_by_posinf(y2);
if( _spoil_scenario==17 )
spoil_vector_by_neginf(y2);
if( _spoil_scenario==18 )
spoil_vector_by_adding_element(y2);
if( _spoil_scenario==19 )
spoil_vector_by_deleting_element(y2);
v = pearsoncorr2(x2, y2);
real_1d_array x3 = "[0,1,4,9,16,25,36,49,64,81]";
if( _spoil_scenario==20 )
spoil_vector_by_nan(x3);
if( _spoil_scenario==21 )
spoil_vector_by_posinf(x3);
if( _spoil_scenario==22 )
spoil_vector_by_neginf(x3);
if( _spoil_scenario==23 )
spoil_vector_by_adding_element(x3);
if( _spoil_scenario==24 )
spoil_vector_by_deleting_element(x3);
real_1d_array y3 = "[0,1,2,3,4,5,6,7,8,9]";
if( _spoil_scenario==25 )
spoil_vector_by_nan(y3);
if( _spoil_scenario==26 )
spoil_vector_by_posinf(y3);
if( _spoil_scenario==27 )
spoil_vector_by_neginf(y3);
if( _spoil_scenario==28 )
spoil_vector_by_adding_element(y3);
if( _spoil_scenario==29 )
spoil_vector_by_deleting_element(y3);
v = spearmancorr2(x3, y3);
//
// 2-sample full-form cov/corr are tested
//
real_1d_array x1a = "[0,1,4,9,16,25,36,49,64,81]";
if( _spoil_scenario==30 )
spoil_vector_by_nan(x1a);
if( _spoil_scenario==31 )
spoil_vector_by_posinf(x1a);
if( _spoil_scenario==32 )
spoil_vector_by_neginf(x1a);
if( _spoil_scenario==33 )
spoil_vector_by_deleting_element(x1a);
real_1d_array y1a = "[0,1,2,3,4,5,6,7,8,9]";
if( _spoil_scenario==34 )
spoil_vector_by_nan(y1a);
if( _spoil_scenario==35 )
spoil_vector_by_posinf(y1a);
if( _spoil_scenario==36 )
spoil_vector_by_neginf(y1a);
if( _spoil_scenario==37 )
spoil_vector_by_deleting_element(y1a);
v = cov2(x1a, y1a, 10);
real_1d_array x2a = "[0,1,4,9,16,25,36,49,64,81]";
if( _spoil_scenario==38 )
spoil_vector_by_nan(x2a);
if( _spoil_scenario==39 )
spoil_vector_by_posinf(x2a);
if( _spoil_scenario==40 )
spoil_vector_by_neginf(x2a);
if( _spoil_scenario==41 )
spoil_vector_by_deleting_element(x2a);
real_1d_array y2a = "[0,1,2,3,4,5,6,7,8,9]";
if( _spoil_scenario==42 )
spoil_vector_by_nan(y2a);
if( _spoil_scenario==43 )
spoil_vector_by_posinf(y2a);
if( _spoil_scenario==44 )
spoil_vector_by_neginf(y2a);
if( _spoil_scenario==45 )
spoil_vector_by_deleting_element(y2a);
v = pearsoncorr2(x2a, y2a, 10);
real_1d_array x3a = "[0,1,4,9,16,25,36,49,64,81]";
if( _spoil_scenario==46 )
spoil_vector_by_nan(x3a);
if( _spoil_scenario==47 )
spoil_vector_by_posinf(x3a);
if( _spoil_scenario==48 )
spoil_vector_by_neginf(x3a);
if( _spoil_scenario==49 )
spoil_vector_by_deleting_element(x3a);
real_1d_array y3a = "[0,1,2,3,4,5,6,7,8,9]";
if( _spoil_scenario==50 )
spoil_vector_by_nan(y3a);
if( _spoil_scenario==51 )
spoil_vector_by_posinf(y3a);
if( _spoil_scenario==52 )
spoil_vector_by_neginf(y3a);
if( _spoil_scenario==53 )
spoil_vector_by_deleting_element(y3a);
v = spearmancorr2(x3a, y3a, 10);
//
// vector short-form cov/corr are tested.
//
real_2d_array x4 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]";
if( _spoil_scenario==54 )
spoil_matrix_by_nan(x4);
if( _spoil_scenario==55 )
spoil_matrix_by_posinf(x4);
if( _spoil_scenario==56 )
spoil_matrix_by_neginf(x4);
covm(x4, c);
real_2d_array x5 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]";
if( _spoil_scenario==57 )
spoil_matrix_by_nan(x5);
if( _spoil_scenario==58 )
spoil_matrix_by_posinf(x5);
if( _spoil_scenario==59 )
spoil_matrix_by_neginf(x5);
pearsoncorrm(x5, c);
real_2d_array x6 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]";
if( _spoil_scenario==60 )
spoil_matrix_by_nan(x6);
if( _spoil_scenario==61 )
spoil_matrix_by_posinf(x6);
if( _spoil_scenario==62 )
spoil_matrix_by_neginf(x6);
spearmancorrm(x6, c);
//
// vector full-form cov/corr are tested.
//
real_2d_array x7 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]";
if( _spoil_scenario==63 )
spoil_matrix_by_nan(x7);
if( _spoil_scenario==64 )
spoil_matrix_by_posinf(x7);
if( _spoil_scenario==65 )
spoil_matrix_by_neginf(x7);
if( _spoil_scenario==66 )
spoil_matrix_by_deleting_row(x7);
if( _spoil_scenario==67 )
spoil_matrix_by_deleting_col(x7);
covm(x7, 5, 3, c);
real_2d_array x8 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]";
if( _spoil_scenario==68 )
spoil_matrix_by_nan(x8);
if( _spoil_scenario==69 )
spoil_matrix_by_posinf(x8);
if( _spoil_scenario==70 )
spoil_matrix_by_neginf(x8);
if( _spoil_scenario==71 )
spoil_matrix_by_deleting_row(x8);
if( _spoil_scenario==72 )
spoil_matrix_by_deleting_col(x8);
pearsoncorrm(x8, 5, 3, c);
real_2d_array x9 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]";
if( _spoil_scenario==73 )
spoil_matrix_by_nan(x9);
if( _spoil_scenario==74 )
spoil_matrix_by_posinf(x9);
if( _spoil_scenario==75 )
spoil_matrix_by_neginf(x9);
if( _spoil_scenario==76 )
spoil_matrix_by_deleting_row(x9);
if( _spoil_scenario==77 )
spoil_matrix_by_deleting_col(x9);
spearmancorrm(x9, 5, 3, c);
//
// cross-vector short-form cov/corr are tested.
//
real_2d_array x10 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]";
if( _spoil_scenario==78 )
spoil_matrix_by_nan(x10);
if( _spoil_scenario==79 )
spoil_matrix_by_posinf(x10);
if( _spoil_scenario==80 )
spoil_matrix_by_neginf(x10);
real_2d_array y10 = "[[2,3],[2,1],[-1,6],[-9,9],[7,1]]";
if( _spoil_scenario==81 )
spoil_matrix_by_nan(y10);
if( _spoil_scenario==82 )
spoil_matrix_by_posinf(y10);
if( _spoil_scenario==83 )
spoil_matrix_by_neginf(y10);
covm2(x10, y10, c);
real_2d_array x11 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]";
if( _spoil_scenario==84 )
spoil_matrix_by_nan(x11);
if( _spoil_scenario==85 )
spoil_matrix_by_posinf(x11);
if( _spoil_scenario==86 )
spoil_matrix_by_neginf(x11);
real_2d_array y11 = "[[2,3],[2,1],[-1,6],[-9,9],[7,1]]";
if( _spoil_scenario==87 )
spoil_matrix_by_nan(y11);
if( _spoil_scenario==88 )
spoil_matrix_by_posinf(y11);
if( _spoil_scenario==89 )
spoil_matrix_by_neginf(y11);
pearsoncorrm2(x11, y11, c);
real_2d_array x12 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]";
if( _spoil_scenario==90 )
spoil_matrix_by_nan(x12);
if( _spoil_scenario==91 )
spoil_matrix_by_posinf(x12);
if( _spoil_scenario==92 )
spoil_matrix_by_neginf(x12);
real_2d_array y12 = "[[2,3],[2,1],[-1,6],[-9,9],[7,1]]";
if( _spoil_scenario==93 )
spoil_matrix_by_nan(y12);
if( _spoil_scenario==94 )
spoil_matrix_by_posinf(y12);
if( _spoil_scenario==95 )
spoil_matrix_by_neginf(y12);
spearmancorrm2(x12, y12, c);
//
// cross-vector full-form cov/corr are tested.
//
real_2d_array x13 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]";
if( _spoil_scenario==96 )
spoil_matrix_by_nan(x13);
if( _spoil_scenario==97 )
spoil_matrix_by_posinf(x13);
if( _spoil_scenario==98 )
spoil_matrix_by_neginf(x13);
if( _spoil_scenario==99 )
spoil_matrix_by_deleting_row(x13);
if( _spoil_scenario==100 )
spoil_matrix_by_deleting_col(x13);
real_2d_array y13 = "[[2,3],[2,1],[-1,6],[-9,9],[7,1]]";
if( _spoil_scenario==101 )
spoil_matrix_by_nan(y13);
if( _spoil_scenario==102 )
spoil_matrix_by_posinf(y13);
if( _spoil_scenario==103 )
spoil_matrix_by_neginf(y13);
if( _spoil_scenario==104 )
spoil_matrix_by_deleting_row(y13);
if( _spoil_scenario==105 )
spoil_matrix_by_deleting_col(y13);
covm2(x13, y13, 5, 3, 2, c);
real_2d_array x14 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]";
if( _spoil_scenario==106 )
spoil_matrix_by_nan(x14);
if( _spoil_scenario==107 )
spoil_matrix_by_posinf(x14);
if( _spoil_scenario==108 )
spoil_matrix_by_neginf(x14);
if( _spoil_scenario==109 )
spoil_matrix_by_deleting_row(x14);
if( _spoil_scenario==110 )
spoil_matrix_by_deleting_col(x14);
real_2d_array y14 = "[[2,3],[2,1],[-1,6],[-9,9],[7,1]]";
if( _spoil_scenario==111 )
spoil_matrix_by_nan(y14);
if( _spoil_scenario==112 )
spoil_matrix_by_posinf(y14);
if( _spoil_scenario==113 )
spoil_matrix_by_neginf(y14);
if( _spoil_scenario==114 )
spoil_matrix_by_deleting_row(y14);
if( _spoil_scenario==115 )
spoil_matrix_by_deleting_col(y14);
pearsoncorrm2(x14, y14, 5, 3, 2, c);
real_2d_array x15 = "[[1,0,1],[1,1,0],[-1,1,0],[-2,-1,1],[-1,0,9]]";
if( _spoil_scenario==116 )
spoil_matrix_by_nan(x15);
if( _spoil_scenario==117 )
spoil_matrix_by_posinf(x15);
if( _spoil_scenario==118 )
spoil_matrix_by_neginf(x15);
if( _spoil_scenario==119 )
spoil_matrix_by_deleting_row(x15);
if( _spoil_scenario==120 )
spoil_matrix_by_deleting_col(x15);
real_2d_array y15 = "[[2,3],[2,1],[-1,6],[-9,9],[7,1]]";
if( _spoil_scenario==121 )
spoil_matrix_by_nan(y15);
if( _spoil_scenario==122 )
spoil_matrix_by_posinf(y15);
if( _spoil_scenario==123 )
spoil_matrix_by_neginf(y15);
if( _spoil_scenario==124 )
spoil_matrix_by_deleting_row(y15);
if( _spoil_scenario==125 )
spoil_matrix_by_deleting_col(y15);
spearmancorrm2(x15, y15, 5, 3, 2, c);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "basestat_t_covcorr");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST ssa_d_basic
// Simple SSA analysis demo
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// Here we demonstrate SSA trend/noise separation for some toy problem:
// small monotonically growing series X are analyzed with 3-tick window
// and "top-K" version of SSA, which selects K largest singular vectors
// for analysis, with K=1.
//
ssamodel s;
real_1d_array x = "[0,0.5,1,1,1.5,2]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
//
// First, we create SSA model, set its properties and add dataset.
//
// We use window with width=3 and configure model to use direct SSA
// algorithm - one which runs exact O(N*W^2) analysis - to extract
// one top singular vector. Well, it is toy problem :)
//
// NOTE: SSA model may store and analyze more than one sequence
// (say, different sequences may correspond to data collected
// from different devices)
//
ssacreate(s);
ssasetwindow(s, 3);
ssaaddsequence(s, x);
ssasetalgotopkdirect(s, 1);
//
// Now we begin analysis. Internally SSA model stores everything it needs:
// data, settings, solvers and so on. Right after first call to analysis-
// related function it will analyze dataset, build basis and perform analysis.
//
// Subsequent calls to analysis functions will reuse previously computed
// basis, unless you invalidate it by changing model settings (or dataset).
//
real_1d_array trend;
real_1d_array noise;
ssaanalyzesequence(s, x, trend, noise);
_TestResult = _TestResult && doc_test_real_vector(trend, "[0.3815,0.5582,0.7810,1.0794,1.5041,2.0105]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "ssa_d_basic");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST ssa_d_forecast
// Simple SSA forecasting demo
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// Here we demonstrate SSA forecasting on some toy problem with clearly
// visible linear trend and small amount of noise.
//
ssamodel s;
real_1d_array x = "[0.05,0.96,2.04,3.11,3.97,5.03,5.98,7.02,8.02]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
//
// First, we create SSA model, set its properties and add dataset.
//
// We use window with width=3 and configure model to use direct SSA
// algorithm - one which runs exact O(N*W^2) analysis - to extract
// two top singular vectors. Well, it is toy problem :)
//
// NOTE: SSA model may store and analyze more than one sequence
// (say, different sequences may correspond to data collected
// from different devices)
//
ssacreate(s);
ssasetwindow(s, 3);
ssaaddsequence(s, x);
ssasetalgotopkdirect(s, 2);
//
// Now we begin analysis. Internally SSA model stores everything it needs:
// data, settings, solvers and so on. Right after first call to analysis-
// related function it will analyze dataset, build basis and perform analysis.
//
// Subsequent calls to analysis functions will reuse previously computed
// basis, unless you invalidate it by changing model settings (or dataset).
//
// In this example we show how to use ssaforecastlast() function, which
// predicts changed in the last sequence of the dataset. If you want to
// perform prediction for some other sequence, use ssaforecastsequence().
//
real_1d_array trend;
ssaforecastlast(s, 3, trend);
//
// Well, we expected it to be [9,10,11]. There exists some difference,
// which can be explained by the artificial noise in the dataset.
//
_TestResult = _TestResult && doc_test_real_vector(trend, "[9.0005,9.9322,10.8051]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "ssa_d_forecast");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST ssa_d_realtime
// Real-time SSA algorithm with fast incremental updates
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<9; _spoil_scenario++)
{
try
{
//
// Suppose that you have a constant stream of incoming data, and you want
// to regularly perform singular spectral analysis of this stream.
//
// One full run of direct algorithm costs O(N*Width^2) operations, so
// the more points you have, the more it costs to rebuild basis from
// scratch.
//
// Luckily we have incremental SSA algorithm which can perform quick
// updates of already computed basis in O(K*Width^2) ops, where K
// is a number of singular vectors extracted. Usually it is orders of
// magnitude faster than full update of the basis.
//
// In this example we start from some initial dataset x0. Then we
// start appending elements one by one to the end of the last sequence.
//
// NOTE: direct algorithm also supports incremental updates, but
// with O(Width^3) cost. Typically K<1)
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// The very simple example on neural network: network is trained to reproduce
// small 2x2 multiplication table.
//
// NOTE: we use network with excessive amount of neurons, which guarantees
// almost exact reproduction of the training set. Generalization ability
// of such network is rather low, but we are not concerned with such
// questions in this basic demo.
//
mlptrainer trn;
multilayerperceptron network;
mlpreport rep;
//
// Training set:
// * one row corresponds to one record A*B=C in the multiplication table
// * first two columns store A and B, last column stores C
//
// [1 * 1 = 1]
// [1 * 2 = 2]
// [2 * 1 = 2]
// [2 * 2 = 4]
//
real_2d_array xy = "[[1,1,1],[1,2,2],[2,1,2],[2,2,4]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
//
// Network is created.
// Trainer object is created.
// Dataset is attached to trainer object.
//
mlpcreatetrainer(2, 1, trn);
mlpcreate1(2, 5, 1, network);
mlpsetdataset(trn, xy, 4);
//
// Network is trained with 5 restarts from random positions
//
mlptrainnetwork(trn, network, 5, rep);
//
// 2*2=?
//
real_1d_array x = "[2,2]";
real_1d_array y = "[0]";
mlpprocess(network, x, y);
_TestResult = _TestResult && doc_test_real_vector(y, "[4.000]", 0.05);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "nn_regr");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST nn_regr_n
// Regression problem with multiple outputs (2=>2)
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// Network with 2 inputs and 2 outputs is trained to reproduce vector function:
// (x0,x1) => (x0+x1, x0*x1)
//
// Informally speaking, we want neural network to simultaneously calculate
// both sum of two numbers and their product.
//
// NOTE: we use network with excessive amount of neurons, which guarantees
// almost exact reproduction of the training set. Generalization ability
// of such network is rather low, but we are not concerned with such
// questions in this basic demo.
//
mlptrainer trn;
multilayerperceptron network;
mlpreport rep;
//
// Training set. One row corresponds to one record [A,B,A+B,A*B].
//
// [ 1 1 1+1 1*1 ]
// [ 1 2 1+2 1*2 ]
// [ 2 1 2+1 2*1 ]
// [ 2 2 2+2 2*2 ]
//
real_2d_array xy = "[[1,1,2,1],[1,2,3,2],[2,1,3,2],[2,2,4,4]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
//
// Network is created.
// Trainer object is created.
// Dataset is attached to trainer object.
//
mlpcreatetrainer(2, 2, trn);
mlpcreate1(2, 5, 2, network);
mlpsetdataset(trn, xy, 4);
//
// Network is trained with 5 restarts from random positions
//
mlptrainnetwork(trn, network, 5, rep);
//
// 2+1=?
// 2*1=?
//
real_1d_array x = "[2,1]";
real_1d_array y = "[0,0]";
mlpprocess(network, x, y);
_TestResult = _TestResult && doc_test_real_vector(y, "[3.000,2.000]", 0.05);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "nn_regr_n");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST nn_cls2
// Binary classification problem
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// Suppose that we want to classify numbers as positive (class 0) and negative
// (class 1). We have training set which includes several strictly positive
// or negative numbers - and zero.
//
// The problem is that we are not sure how to classify zero, so from time to
// time we mark it as positive or negative (with equal probability). Other
// numbers are marked in pure deterministic setting. How will neural network
// cope with such classification task?
//
// NOTE: we use network with excessive amount of neurons, which guarantees
// almost exact reproduction of the training set. Generalization ability
// of such network is rather low, but we are not concerned with such
// questions in this basic demo.
//
mlptrainer trn;
multilayerperceptron network;
mlpreport rep;
real_1d_array x = "[0]";
real_1d_array y = "[0,0]";
//
// Training set. One row corresponds to one record [A => class(A)].
//
// Classes are denoted by numbers from 0 to 1, where 0 corresponds to positive
// numbers and 1 to negative numbers.
//
// [ +1 0]
// [ +2 0]
// [ -1 1]
// [ -2 1]
// [ 0 0] !! sometimes we classify 0 as positive, sometimes as negative
// [ 0 1] !!
//
real_2d_array xy = "[[+1,0],[+2,0],[-1,1],[-2,1],[0,0],[0,1]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
//
//
// When we solve classification problems, everything is slightly different from
// the regression ones:
//
// 1. Network is created. Because we solve classification problem, we use
// mlpcreatec1() function instead of mlpcreate1(). This function creates
// classifier network with SOFTMAX-normalized outputs. This network returns
// vector of class membership probabilities which are normalized to be
// non-negative and sum to 1.0
//
// 2. We use mlpcreatetrainercls() function instead of mlpcreatetrainer() to
// create trainer object. Trainer object process dataset and neural network
// slightly differently to account for specifics of the classification
// problems.
//
// 3. Dataset is attached to trainer object. Note that dataset format is slightly
// different from one used for regression.
//
mlpcreatetrainercls(1, 2, trn);
mlpcreatec1(1, 5, 2, network);
mlpsetdataset(trn, xy, 6);
//
// Network is trained with 5 restarts from random positions
//
mlptrainnetwork(trn, network, 5, rep);
//
// Test our neural network on strictly positive and strictly negative numbers.
//
// IMPORTANT! Classifier network returns class membership probabilities instead
// of class indexes. Network returns two values (probabilities) instead of one
// (class index).
//
// Thus, for +1 we expect to get [P0,P1] = [1,0], where P0 is probability that
// number is positive (belongs to class 0), and P1 is probability that number
// is negative (belongs to class 1).
//
// For -1 we expect to get [P0,P1] = [0,1]
//
// Following properties are guaranteed by network architecture:
// * P0>=0, P1>=0 non-negativity
// * P0+P1=1 normalization
//
x = "[1]";
mlpprocess(network, x, y);
_TestResult = _TestResult && doc_test_real_vector(y, "[1.000,0.000]", 0.05);
x = "[-1]";
mlpprocess(network, x, y);
_TestResult = _TestResult && doc_test_real_vector(y, "[0.000,1.000]", 0.05);
//
// But what our network will return for 0, which is between classes 0 and 1?
//
// In our dataset it has two different marks assigned (class 0 AND class 1).
// So network will return something average between class 0 and class 1:
// 0 => [0.5, 0.5]
//
x = "[0]";
mlpprocess(network, x, y);
_TestResult = _TestResult && doc_test_real_vector(y, "[0.500,0.500]", 0.05);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "nn_cls2");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST nn_cls3
// Multiclass classification problem
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// Suppose that we want to classify numbers as positive (class 0) and negative
// (class 1). We also have one more class for zero (class 2).
//
// NOTE: we use network with excessive amount of neurons, which guarantees
// almost exact reproduction of the training set. Generalization ability
// of such network is rather low, but we are not concerned with such
// questions in this basic demo.
//
mlptrainer trn;
multilayerperceptron network;
mlpreport rep;
real_1d_array x = "[0]";
real_1d_array y = "[0,0,0]";
//
// Training set. One row corresponds to one record [A => class(A)].
//
// Classes are denoted by numbers from 0 to 2, where 0 corresponds to positive
// numbers, 1 to negative numbers, 2 to zero
//
// [ +1 0]
// [ +2 0]
// [ -1 1]
// [ -2 1]
// [ 0 2]
//
real_2d_array xy = "[[+1,0],[+2,0],[-1,1],[-2,1],[0,2]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
//
//
// When we solve classification problems, everything is slightly different from
// the regression ones:
//
// 1. Network is created. Because we solve classification problem, we use
// mlpcreatec1() function instead of mlpcreate1(). This function creates
// classifier network with SOFTMAX-normalized outputs. This network returns
// vector of class membership probabilities which are normalized to be
// non-negative and sum to 1.0
//
// 2. We use mlpcreatetrainercls() function instead of mlpcreatetrainer() to
// create trainer object. Trainer object process dataset and neural network
// slightly differently to account for specifics of the classification
// problems.
//
// 3. Dataset is attached to trainer object. Note that dataset format is slightly
// different from one used for regression.
//
mlpcreatetrainercls(1, 3, trn);
mlpcreatec1(1, 5, 3, network);
mlpsetdataset(trn, xy, 5);
//
// Network is trained with 5 restarts from random positions
//
mlptrainnetwork(trn, network, 5, rep);
//
// Test our neural network on strictly positive and strictly negative numbers.
//
// IMPORTANT! Classifier network returns class membership probabilities instead
// of class indexes. Network returns three values (probabilities) instead of one
// (class index).
//
// Thus, for +1 we expect to get [P0,P1,P2] = [1,0,0],
// for -1 we expect to get [P0,P1,P2] = [0,1,0],
// and for 0 we will get [P0,P1,P2] = [0,0,1].
//
// Following properties are guaranteed by network architecture:
// * P0>=0, P1>=0, P2>=0 non-negativity
// * P0+P1+P2=1 normalization
//
x = "[1]";
mlpprocess(network, x, y);
_TestResult = _TestResult && doc_test_real_vector(y, "[1.000,0.000,0.000]", 0.05);
x = "[-1]";
mlpprocess(network, x, y);
_TestResult = _TestResult && doc_test_real_vector(y, "[0.000,1.000,0.000]", 0.05);
x = "[0]";
mlpprocess(network, x, y);
_TestResult = _TestResult && doc_test_real_vector(y, "[0.000,0.000,1.000]", 0.05);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "nn_cls3");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST nn_trainerobject
// Advanced example on trainer object
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<6; _spoil_scenario++)
{
try
{
//
// Trainer object is used to train network. It stores dataset, training settings,
// and other information which is NOT part of neural network. You should use
// trainer object as follows:
// (1) you create trainer object and specify task type (classification/regression)
// and number of inputs/outputs
// (2) you add dataset to the trainer object
// (3) you may change training settings (stopping criteria or weight decay)
// (4) finally, you may train one or more networks
//
// You may interleave stages 2...4 and repeat them many times. Trainer object
// remembers its internal state and can be used several times after its creation
// and initialization.
//
mlptrainer trn;
//
// Stage 1: object creation.
//
// We have to specify number of inputs and outputs. Trainer object can be used
// only for problems with same number of inputs/outputs as was specified during
// its creation.
//
// In case you want to train SOFTMAX-normalized network which solves classification
// problems, you must use another function to create trainer object:
// mlpcreatetrainercls().
//
// Below we create trainer object which can be used to train regression networks
// with 2 inputs and 1 output.
//
mlpcreatetrainer(2, 1, trn);
//
// Stage 2: specification of the training set
//
// By default trainer object stores empty dataset. So to solve your non-empty problem
// you have to set dataset by passing to trainer dense or sparse matrix.
//
// One row of the matrix corresponds to one record A*B=C in the multiplication table.
// First two columns store A and B, last column stores C
//
// [1 * 1 = 1] [ 1 1 1 ]
// [1 * 2 = 2] [ 1 2 2 ]
// [2 * 1 = 2] = [ 2 1 2 ]
// [2 * 2 = 4] [ 2 2 4 ]
//
real_2d_array xy = "[[1,1,1],[1,2,2],[2,1,2],[2,2,4]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
mlpsetdataset(trn, xy, 4);
//
// Stage 3: modification of the training parameters.
//
// You may modify parameters like weights decay or stopping criteria:
// * we set moderate weight decay
// * we choose iterations limit as stopping condition (another condition - step size -
// is zero, which means than this condition is not active)
//
double wstep = 0.000;
if( _spoil_scenario==3 )
wstep = fp_nan;
if( _spoil_scenario==4 )
wstep = fp_posinf;
if( _spoil_scenario==5 )
wstep = fp_neginf;
ae_int_t maxits = 100;
mlpsetdecay(trn, 0.01);
mlpsetcond(trn, wstep, maxits);
//
// Stage 4: training.
//
// We will train several networks with different architecture using same trainer object.
// We may change training parameters or even dataset, so different networks are trained
// differently. But in this simple example we will train all networks with same settings.
//
// We create and train three networks:
// * network 1 has 2x1 architecture (2 inputs, no hidden neurons, 1 output)
// * network 2 has 2x5x1 architecture (2 inputs, 5 hidden neurons, 1 output)
// * network 3 has 2x5x5x1 architecture (2 inputs, two hidden layers, 1 output)
//
// NOTE: these networks solve regression problems. For classification problems you
// should use mlpcreatec0/c1/c2 to create neural networks which have SOFTMAX-
// normalized outputs.
//
multilayerperceptron net1;
multilayerperceptron net2;
multilayerperceptron net3;
mlpreport rep;
mlpcreate0(2, 1, net1);
mlpcreate1(2, 5, 1, net2);
mlpcreate2(2, 5, 5, 1, net3);
mlptrainnetwork(trn, net1, 5, rep);
mlptrainnetwork(trn, net2, 5, rep);
mlptrainnetwork(trn, net3, 5, rep);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "nn_trainerobject");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST nn_crossvalidation
// Cross-validation
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// This example shows how to perform cross-validation with ALGLIB
//
mlptrainer trn;
multilayerperceptron network;
mlpreport rep;
//
// Training set: f(x)=1/(x^2+1)
// One row corresponds to one record [x,f(x)]
//
real_2d_array xy = "[[-2.0,0.2],[-1.6,0.3],[-1.3,0.4],[-1,0.5],[-0.6,0.7],[-0.3,0.9],[0,1],[2.0,0.2],[1.6,0.3],[1.3,0.4],[1,0.5],[0.6,0.7],[0.3,0.9]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
//
// Trainer object is created.
// Dataset is attached to trainer object.
//
// NOTE: it is not good idea to perform cross-validation on sample
// as small as ours (13 examples). It is done for demonstration
// purposes only. Generalization error estimates won't be
// precise enough for practical purposes.
//
mlpcreatetrainer(1, 1, trn);
mlpsetdataset(trn, xy, 13);
//
// The key property of the cross-validation is that it estimates
// generalization properties of neural ARCHITECTURE. It does NOT
// estimates generalization error of some specific network which
// is passed to the k-fold CV routine.
//
// In our example we create 1x4x1 neural network and pass it to
// CV routine without training it. Original state of the network
// is not used for cross-validation - each round is restarted from
// random initial state. Only geometry of network matters.
//
// We perform 5 restarts from different random positions for each
// of the 10 cross-validation rounds.
//
mlpcreate1(1, 4, 1, network);
mlpkfoldcv(trn, network, 5, 10, rep);
//
// Cross-validation routine stores estimates of the generalization
// error to MLP report structure. You may examine its fields and
// see estimates of different errors (RMS, CE, Avg).
//
// Because cross-validation is non-deterministic, in our manual we
// can not say what values will be stored to rep after call to
// mlpkfoldcv(). Every CV round will return slightly different
// estimates.
//
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "nn_crossvalidation");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST nn_ensembles_es
// Early stopping ensembles
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// This example shows how to train early stopping ensebles.
//
mlptrainer trn;
mlpensemble ensemble;
mlpreport rep;
//
// Training set: f(x)=1/(x^2+1)
// One row corresponds to one record [x,f(x)]
//
real_2d_array xy = "[[-2.0,0.2],[-1.6,0.3],[-1.3,0.4],[-1,0.5],[-0.6,0.7],[-0.3,0.9],[0,1],[2.0,0.2],[1.6,0.3],[1.3,0.4],[1,0.5],[0.6,0.7],[0.3,0.9]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
//
// Trainer object is created.
// Dataset is attached to trainer object.
//
// NOTE: it is not good idea to use early stopping ensemble on sample
// as small as ours (13 examples). It is done for demonstration
// purposes only. Ensemble training algorithm won't find good
// solution on such small sample.
//
mlpcreatetrainer(1, 1, trn);
mlpsetdataset(trn, xy, 13);
//
// Ensemble is created and trained. Each of 50 network is trained
// with 5 restarts.
//
mlpecreate1(1, 4, 1, 50, ensemble);
mlptrainensemblees(trn, ensemble, 5, rep);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "nn_ensembles_es");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST nn_parallel
// Parallel training
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// This example shows how to use parallel functionality of ALGLIB.
// We generate simple 1-dimensional regression problem and show how
// to use parallel training, parallel cross-validation, parallel
// training of neural ensembles.
//
// We assume that you already know how to use ALGLIB in serial mode
// and concentrate on its parallel capabilities.
//
// NOTE: it is not good idea to use parallel features on sample as small
// as ours (13 examples). It is done only for demonstration purposes.
//
mlptrainer trn;
multilayerperceptron network;
mlpensemble ensemble;
mlpreport rep;
real_2d_array xy = "[[-2.0,0.2],[-1.6,0.3],[-1.3,0.4],[-1,0.5],[-0.6,0.7],[-0.3,0.9],[0,1],[2.0,0.2],[1.6,0.3],[1.3,0.4],[1,0.5],[0.6,0.7],[0.3,0.9]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
mlpcreatetrainer(1, 1, trn);
mlpsetdataset(trn, xy, 13);
mlpcreate1(1, 4, 1, network);
mlpecreate1(1, 4, 1, 50, ensemble);
//
// Below we demonstrate how to perform:
// * parallel training of individual networks
// * parallel cross-validation
// * parallel training of neural ensembles
//
// In order to use multithreading, you have to:
// 1) Install SMP edition of ALGLIB.
// 2) This step is specific for C++ users: you should activate OS-specific
// capabilities of ALGLIB by defining AE_OS=AE_POSIX (for *nix systems)
// or AE_OS=AE_WINDOWS (for Windows systems).
// C# users do not have to perform this step because C# programs are
// portable across different systems without OS-specific tuning.
// 3) Tell ALGLIB that you want it to use multithreading by means of
// setnworkers() call:
// * alglib::setnworkers(0) = use all cores
// * alglib::setnworkers(-1) = leave one core unused
// * alglib::setnworkers(-2) = leave two cores unused
// * alglib::setnworkers(+2) = use 2 cores (even if you have more)
// During runtime ALGLIB will automatically determine whether it is
// feasible to start worker threads and split your task between cores.
//
alglib::setnworkers(+2);
//
// First, we perform parallel training of individual network with 5
// restarts from random positions. These 5 rounds of training are
// executed in parallel manner, with best network chosen after
// training.
//
// ALGLIB can use additional way to speed up computations - divide
// dataset into smaller subsets and process these subsets
// simultaneously. It allows us to efficiently parallelize even
// single training round. This operation is performed automatically
// for large datasets, but our toy dataset is too small.
//
mlptrainnetwork(trn, network, 5, rep);
//
// Then, we perform parallel 10-fold cross-validation, with 5 random
// restarts per each CV round. I.e., 5*10=50 networks are trained
// in total. All these operations can be parallelized.
//
// NOTE: again, ALGLIB can parallelize calculation of gradient
// over entire dataset - but our dataset is too small.
//
mlpkfoldcv(trn, network, 5, 10, rep);
//
// Finally, we train early stopping ensemble of 50 neural networks,
// each of them is trained with 5 random restarts. I.e., 5*50=250
// networks aretrained in total.
//
mlptrainensemblees(trn, ensemble, 5, rep);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "nn_parallel");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST clst_ahc
// Simple hierarchical clusterization with Euclidean distance function
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// The very simple clusterization example
//
// We have a set of points in 2D space:
// (P0,P1,P2,P3,P4) = ((1,1),(1,2),(4,1),(2,3),(4,1.5))
//
// |
// | P3
// |
// | P1
// | P4
// | P0 P2
// |-------------------------
//
// We want to perform Agglomerative Hierarchic Clusterization (AHC),
// using complete linkage (default algorithm) and Euclidean distance
// (default metric).
//
// In order to do that, we:
// * create clusterizer with clusterizercreate()
// * set points XY and metric (2=Euclidean) with clusterizersetpoints()
// * run AHC algorithm with clusterizerrunahc
//
// You may see that clusterization itself is a minor part of the example,
// most of which is dominated by comments :)
//
clusterizerstate s;
ahcreport rep;
real_2d_array xy = "[[1,1],[1,2],[4,1],[2,3],[4,1.5]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
clusterizercreate(s);
clusterizersetpoints(s, xy, 2);
clusterizerrunahc(s, rep);
//
// Now we've built our clusterization tree. Rep.z contains information which
// is required to build dendrogram. I-th row of rep.z represents one merge
// operation, with first cluster to merge having index rep.z[I,0] and second
// one having index rep.z[I,1]. Merge result has index NPoints+I.
//
// Clusters with indexes less than NPoints are single-point initial clusters,
// while ones with indexes from NPoints to 2*NPoints-2 are multi-point
// clusters created during merges.
//
// In our example, Z=[[2,4], [0,1], [3,6], [5,7]]
//
// It means that:
// * first, we merge C2=(P2) and C4=(P4), and create C5=(P2,P4)
// * then, we merge C2=(P0) and C1=(P1), and create C6=(P0,P1)
// * then, we merge C3=(P3) and C6=(P0,P1), and create C7=(P0,P1,P3)
// * finally, we merge C5 and C7 and create C8=(P0,P1,P2,P3,P4)
//
// Thus, we have following dendrogram:
//
// ------8-----
// | |
// | ----7----
// | | |
// ---5--- | ---6---
// | | | | |
// P2 P4 P3 P0 P1
//
_TestResult = _TestResult && doc_test_int_matrix(rep.z, "[[2,4],[0,1],[3,6],[5,7]]");
//
// We've built dendrogram above by reordering our dataset.
//
// Without such reordering it would be impossible to build dendrogram without
// intersections. Luckily, ahcreport structure contains two additional fields
// which help to build dendrogram from your data:
// * rep.p, which contains permutation applied to dataset
// * rep.pm, which contains another representation of merges
//
// In our example we have:
// * P=[3,4,0,2,1]
// * PZ=[[0,0,1,1,0,0],[3,3,4,4,0,0],[2,2,3,4,0,1],[0,1,2,4,1,2]]
//
// Permutation array P tells us that P0 should be moved to position 3,
// P1 moved to position 4, P2 moved to position 0 and so on:
//
// (P0 P1 P2 P3 P4) => (P2 P4 P3 P0 P1)
//
// Merges array PZ tells us how to perform merges on the sorted dataset.
// One row of PZ corresponds to one merge operations, with first pair of
// elements denoting first of the clusters to merge (start index, end
// index) and next pair of elements denoting second of the clusters to
// merge. Clusters being merged are always adjacent, with first one on
// the left and second one on the right.
//
// For example, first row of PZ tells us that clusters [0,0] and [1,1] are
// merged (single-point clusters, with first one containing P2 and second
// one containing P4). Third row of PZ tells us that we merge one single-
// point cluster [2,2] with one two-point cluster [3,4].
//
// There are two more elements in each row of PZ. These are the helper
// elements, which denote HEIGHT (not size) of left and right subdendrograms.
// For example, according to PZ, first two merges are performed on clusterization
// trees of height 0, while next two merges are performed on 0-1 and 1-2
// pairs of trees correspondingly.
//
_TestResult = _TestResult && doc_test_int_vector(rep.p, "[3,4,0,2,1]");
_TestResult = _TestResult && doc_test_int_matrix(rep.pm, "[[0,0,1,1,0,0],[3,3,4,4,0,0],[2,2,3,4,0,1],[0,1,2,4,1,2]]");
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "clst_ahc");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST clst_kmeans
// Simple k-means clusterization
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// The very simple clusterization example
//
// We have a set of points in 2D space:
// (P0,P1,P2,P3,P4) = ((1,1),(1,2),(4,1),(2,3),(4,1.5))
//
// |
// | P3
// |
// | P1
// | P4
// | P0 P2
// |-------------------------
//
// We want to perform k-means++ clustering with K=2.
//
// In order to do that, we:
// * create clusterizer with clusterizercreate()
// * set points XY and metric (must be Euclidean, distype=2) with clusterizersetpoints()
// * (optional) set number of restarts from random positions to 5
// * run k-means algorithm with clusterizerrunkmeans()
//
// You may see that clusterization itself is a minor part of the example,
// most of which is dominated by comments :)
//
clusterizerstate s;
kmeansreport rep;
real_2d_array xy = "[[1,1],[1,2],[4,1],[2,3],[4,1.5]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
clusterizercreate(s);
clusterizersetpoints(s, xy, 2);
clusterizersetkmeanslimits(s, 5, 0);
clusterizerrunkmeans(s, 2, rep);
//
// We've performed clusterization, and it succeeded (completion code is +1).
//
// Now first center is stored in the first row of rep.c, second one is stored
// in the second row. rep.cidx can be used to determine which center is
// closest to some specific point of the dataset.
//
_TestResult = _TestResult && doc_test_int(rep.terminationtype, 1);
// We called clusterizersetpoints() with disttype=2 because k-means++
// algorithm does NOT support metrics other than Euclidean. But what if we
// try to use some other metric?
//
// We change metric type by calling clusterizersetpoints() one more time,
// and try to run k-means algo again. It fails.
//
clusterizersetpoints(s, xy, 0);
clusterizerrunkmeans(s, 2, rep);
_TestResult = _TestResult && doc_test_int(rep.terminationtype, -5);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "clst_kmeans");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST clst_linkage
// Clusterization with different linkage types
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// We have a set of points in 1D space:
// (P0,P1,P2,P3,P4) = (1, 3, 10, 16, 20)
//
// We want to perform Agglomerative Hierarchic Clusterization (AHC),
// using either complete or single linkage and Euclidean distance
// (default metric).
//
// First two steps merge P0/P1 and P3/P4 independently of the linkage type.
// However, third step depends on linkage type being used:
// * in case of complete linkage P2=10 is merged with [P0,P1]
// * in case of single linkage P2=10 is merged with [P3,P4]
//
clusterizerstate s;
ahcreport rep;
real_2d_array xy = "[[1],[3],[10],[16],[20]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
integer_1d_array cidx;
integer_1d_array cz;
clusterizercreate(s);
clusterizersetpoints(s, xy, 2);
// use complete linkage, reduce set down to 2 clusters.
// print clusterization with clusterizergetkclusters(2).
// P2 must belong to [P0,P1]
clusterizersetahcalgo(s, 0);
clusterizerrunahc(s, rep);
clusterizergetkclusters(rep, 2, cidx, cz);
_TestResult = _TestResult && doc_test_int_vector(cidx, "[1,1,1,0,0]");
// use single linkage, reduce set down to 2 clusters.
// print clusterization with clusterizergetkclusters(2).
// P2 must belong to [P2,P3]
clusterizersetahcalgo(s, 1);
clusterizerrunahc(s, rep);
clusterizergetkclusters(rep, 2, cidx, cz);
_TestResult = _TestResult && doc_test_int_vector(cidx, "[0,0,1,1,1]");
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "clst_linkage");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST clst_distance
// Clusterization with different metric types
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// We have three points in 4D space:
// (P0,P1,P2) = ((1, 2, 1, 2), (6, 7, 6, 7), (7, 6, 7, 6))
//
// We want to try clustering them with different distance functions.
// Distance function is chosen when we add dataset to the clusterizer.
// We can choose several distance types - Euclidean, city block, Chebyshev,
// several correlation measures or user-supplied distance matrix.
//
// Here we'll try three distances: Euclidean, Pearson correlation,
// user-supplied distance matrix. Different distance functions lead
// to different choices being made by algorithm during clustering.
//
clusterizerstate s;
ahcreport rep;
ae_int_t disttype;
real_2d_array xy = "[[1, 2, 1, 2], [6, 7, 6, 7], [7, 6, 7, 6]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
clusterizercreate(s);
// With Euclidean distance function (disttype=2) two closest points
// are P1 and P2, thus:
// * first, we merge P1 and P2 to form C3=[P1,P2]
// * second, we merge P0 and C3 to form C4=[P0,P1,P2]
disttype = 2;
clusterizersetpoints(s, xy, disttype);
clusterizerrunahc(s, rep);
_TestResult = _TestResult && doc_test_int_matrix(rep.z, "[[1,2],[0,3]]");
// With Pearson correlation distance function (disttype=10) situation
// is different - distance between P0 and P1 is zero, thus:
// * first, we merge P0 and P1 to form C3=[P0,P1]
// * second, we merge P2 and C3 to form C4=[P0,P1,P2]
disttype = 10;
clusterizersetpoints(s, xy, disttype);
clusterizerrunahc(s, rep);
_TestResult = _TestResult && doc_test_int_matrix(rep.z, "[[0,1],[2,3]]");
// Finally, we try clustering with user-supplied distance matrix:
// [ 0 3 1 ]
// P = [ 3 0 3 ], where P[i,j] = dist(Pi,Pj)
// [ 1 3 0 ]
//
// * first, we merge P0 and P2 to form C3=[P0,P2]
// * second, we merge P1 and C3 to form C4=[P0,P1,P2]
real_2d_array d = "[[0,3,1],[3,0,3],[1,3,0]]";
clusterizersetdistances(s, d, true);
clusterizerrunahc(s, rep);
_TestResult = _TestResult && doc_test_int_matrix(rep.z, "[[0,2],[1,3]]");
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "clst_distance");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST clst_kclusters
// Obtaining K top clusters from clusterization tree
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// We have a set of points in 2D space:
// (P0,P1,P2,P3,P4) = ((1,1),(1,2),(4,1),(2,3),(4,1.5))
//
// |
// | P3
// |
// | P1
// | P4
// | P0 P2
// |-------------------------
//
// We perform Agglomerative Hierarchic Clusterization (AHC) and we want
// to get top K clusters from clusterization tree for different K.
//
clusterizerstate s;
ahcreport rep;
real_2d_array xy = "[[1,1],[1,2],[4,1],[2,3],[4,1.5]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
integer_1d_array cidx;
integer_1d_array cz;
clusterizercreate(s);
clusterizersetpoints(s, xy, 2);
clusterizerrunahc(s, rep);
// with K=5, every points is assigned to its own cluster:
// C0=P0, C1=P1 and so on...
clusterizergetkclusters(rep, 5, cidx, cz);
_TestResult = _TestResult && doc_test_int_vector(cidx, "[0,1,2,3,4]");
// with K=1 we have one large cluster C0=[P0,P1,P2,P3,P4,P5]
clusterizergetkclusters(rep, 1, cidx, cz);
_TestResult = _TestResult && doc_test_int_vector(cidx, "[0,0,0,0,0]");
// with K=3 we have three clusters C0=[P3], C1=[P2,P4], C2=[P0,P1]
clusterizergetkclusters(rep, 3, cidx, cz);
_TestResult = _TestResult && doc_test_int_vector(cidx, "[2,2,1,0,1]");
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "clst_kclusters");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST randomforest_cls
// Simple classification with random forests
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// The very simple classification example: classify points (x,y) in 2D space
// as ones with x>=0 and ones with x<0 (y is ignored, but our classifier
// has to find out it).
//
// First, we have to create decision forest builder object, load dataset and
// specify training settings. Our dataset is specified as matrix, which has
// following format:
//
// x0 y0 class0
// x1 y1 class1
// x2 y2 class2
// ....
//
// Here xi and yi can be any values (and in fact you can have any number of
// independent variables), and classi MUST be integer number in [0,NClasses)
// range. In our example we denote points with x>=0 as class #0, and
// ones with negative xi as class #1.
//
// NOTE: if you want to solve regression problem, specify NClasses=1. In
// this case last column of xy can be any numeric value.
//
// For the sake of simplicity, our example includes only 4-point dataset.
// However, random forests are able to cope with extremely large datasets
// having millions of examples.
//
decisionforestbuilder builder;
ae_int_t nvars = 2;
ae_int_t nclasses = 2;
ae_int_t npoints = 4;
real_2d_array xy = "[[1,1,0],[1,-1,0],[-1,1,1],[-1,-1,1]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
dfbuildercreate(builder);
dfbuildersetdataset(builder, xy, npoints, nvars, nclasses);
// in our example we train decision forest using full sample - it allows us
// to get zero classification error. However, in practical applications smaller
// values are used: 50%, 25%, 5% or even less.
dfbuildersetsubsampleratio(builder, 1.0);
// we train random forest with just one tree; again, in real life situations
// you typically need from 50 to 500 trees.
ae_int_t ntrees = 1;
decisionforest forest;
dfreport rep;
dfbuilderbuildrandomforest(builder, ntrees, forest, rep);
// with such settings (100% of the training set is used) you can expect
// zero classification error. Beautiful results, but remember - in real life
// you do not need zero TRAINING SET error, you need good generalization.
_TestResult = _TestResult && doc_test_real(rep.relclserror, 0.0000, 0.00005);
// now, let's perform some simple processing with dfprocess()
real_1d_array x = "[+1,0]";
real_1d_array y = "[]";
dfprocess(forest, x, y);
_TestResult = _TestResult && doc_test_real_vector(y, "[+1,0]", 0.0005);
// another option is to use dfprocess0() which returns just first component
// of the output vector y. ideal for regression problems and binary classifiers.
double y0;
y0 = dfprocess0(forest, x);
_TestResult = _TestResult && doc_test_real(y0, 1.000, 0.0005);
// finally, you can use dfclassify() which returns most probable class index (i.e. argmax y[i]).
ae_int_t i;
i = dfclassify(forest, x);
_TestResult = _TestResult && doc_test_int(i, 0);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "randomforest_cls");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST randomforest_reg
// Simple classification with decision forest
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// The very simple regression example: model f(x,y)=x+y
//
// First, we have to create DF builder object, load dataset and specify
// training settings. Our dataset is specified as matrix, which has following
// format:
//
// x0 y0 f0
// x1 y1 f1
// x2 y2 f2
// ....
//
// Here xi and yi can be any values, and fi is a dependent function value.
//
// NOTE: you can also solve classification problems with DF models, see
// another example for this unit.
//
decisionforestbuilder builder;
ae_int_t nvars = 2;
ae_int_t nclasses = 1;
ae_int_t npoints = 4;
real_2d_array xy = "[[1,1,+2],[1,-1,0],[-1,1,0],[-1,-1,-2]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
dfbuildercreate(builder);
dfbuildersetdataset(builder, xy, npoints, nvars, nclasses);
// in our example we train decision forest using full sample - it allows us
// to get zero classification error. However, in practical applications smaller
// values are used: 50%, 25%, 5% or even less.
dfbuildersetsubsampleratio(builder, 1.0);
// we train random forest with just one tree; again, in real life situations
// you typically need from 50 to 500 trees.
ae_int_t ntrees = 1;
decisionforest model;
dfreport rep;
dfbuilderbuildrandomforest(builder, ntrees, model, rep);
// with such settings (full sample is used) you can expect zero RMS error on the
// training set. Beautiful results, but remember - in real life you do not
// need zero TRAINING SET error, you need good generalization.
_TestResult = _TestResult && doc_test_real(rep.rmserror, 0.0000, 0.00005);
// now, let's perform some simple processing with dfprocess()
real_1d_array x = "[+1,+1]";
real_1d_array y = "[]";
dfprocess(model, x, y);
_TestResult = _TestResult && doc_test_real_vector(y, "[+2]", 0.0005);
// another option is to use dfprocess0() which returns just first component
// of the output vector y. ideal for regression problems and binary classifiers.
double y0;
y0 = dfprocess0(model, x);
_TestResult = _TestResult && doc_test_real(y0, 2.000, 0.0005);
// there also exist another convenience function, dfclassify(),
// but it does not work for regression problems - it always returns -1.
ae_int_t i;
i = dfclassify(model, x);
_TestResult = _TestResult && doc_test_int(i, -1);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "randomforest_reg");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST knn_cls
// Simple classification with KNN model
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// The very simple classification example: classify points (x,y) in 2D space
// as ones with x>=0 and ones with x<0 (y is ignored, but our classifier
// has to find out it).
//
// First, we have to create KNN builder object, load dataset and specify
// training settings. Our dataset is specified as matrix, which has following
// format:
//
// x0 y0 class0
// x1 y1 class1
// x2 y2 class2
// ....
//
// Here xi and yi can be any values (and in fact you can have any number of
// independent variables), and classi MUST be integer number in [0,NClasses)
// range. In our example we denote points with x>=0 as class #0, and
// ones with negative xi as class #1.
//
// NOTE: if you want to solve regression problem, specify dataset in similar
// format, but with dependent variable(s) instead of class labels. You
// can have dataset with multiple dependent variables, by the way!
//
// For the sake of simplicity, our example includes only 4-point dataset and
// really simple K=1 nearest neighbor search. Industrial problems typically
// need larger values of K.
//
knnbuilder builder;
ae_int_t nvars = 2;
ae_int_t nclasses = 2;
ae_int_t npoints = 4;
real_2d_array xy = "[[1,1,0],[1,-1,0],[-1,1,1],[-1,-1,1]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
knnbuildercreate(builder);
knnbuildersetdatasetcls(builder, xy, npoints, nvars, nclasses);
// we build KNN model with k=1 and eps=0 (exact k-nn search is performed)
ae_int_t k = 1;
double eps = 0;
knnmodel model;
knnreport rep;
knnbuilderbuildknnmodel(builder, k, eps, model, rep);
// with such settings (k=1 is used) you can expect zero classification
// error on training set. Beautiful results, but remember - in real life
// you do not need zero TRAINING SET error, you need good generalization.
_TestResult = _TestResult && doc_test_real(rep.relclserror, 0.0000, 0.00005);
// now, let's perform some simple processing with knnprocess()
real_1d_array x = "[+1,0]";
real_1d_array y = "[]";
knnprocess(model, x, y);
_TestResult = _TestResult && doc_test_real_vector(y, "[+1,0]", 0.0005);
// another option is to use knnprocess0() which returns just first component
// of the output vector y. ideal for regression problems and binary classifiers.
double y0;
y0 = knnprocess0(model, x);
_TestResult = _TestResult && doc_test_real(y0, 1.000, 0.0005);
// finally, you can use knnclassify() which returns most probable class index (i.e. argmax y[i]).
ae_int_t i;
i = knnclassify(model, x);
_TestResult = _TestResult && doc_test_int(i, 0);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "knn_cls");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST knn_reg
// Simple classification with KNN model
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// The very simple regression example: model f(x,y)=x+y
//
// First, we have to create KNN builder object, load dataset and specify
// training settings. Our dataset is specified as matrix, which has following
// format:
//
// x0 y0 f0
// x1 y1 f1
// x2 y2 f2
// ....
//
// Here xi and yi can be any values, and fi is a dependent function value.
// By the way, with KNN algorithm you can even model functions with multiple
// dependent variables!
//
// NOTE: you can also solve classification problems with KNN models, see
// another example for this unit.
//
// For the sake of simplicity, our example includes only 4-point dataset and
// really simple K=1 nearest neighbor search. Industrial problems typically
// need larger values of K.
//
knnbuilder builder;
ae_int_t nvars = 2;
ae_int_t nout = 1;
ae_int_t npoints = 4;
real_2d_array xy = "[[1,1,+2],[1,-1,0],[-1,1,0],[-1,-1,-2]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
knnbuildercreate(builder);
knnbuildersetdatasetreg(builder, xy, npoints, nvars, nout);
// we build KNN model with k=1 and eps=0 (exact k-nn search is performed)
ae_int_t k = 1;
double eps = 0;
knnmodel model;
knnreport rep;
knnbuilderbuildknnmodel(builder, k, eps, model, rep);
// with such settings (k=1 is used) you can expect zero RMS error on the
// training set. Beautiful results, but remember - in real life you do not
// need zero TRAINING SET error, you need good generalization.
_TestResult = _TestResult && doc_test_real(rep.rmserror, 0.0000, 0.00005);
// now, let's perform some simple processing with knnprocess()
real_1d_array x = "[+1,+1]";
real_1d_array y = "[]";
knnprocess(model, x, y);
_TestResult = _TestResult && doc_test_real_vector(y, "[+2]", 0.0005);
// another option is to use knnprocess0() which returns just first component
// of the output vector y. ideal for regression problems and binary classifiers.
double y0;
y0 = knnprocess0(model, x);
_TestResult = _TestResult && doc_test_real(y0, 2.000, 0.0005);
// there also exist another convenience function, knnclassify(),
// but it does not work for regression problems - it always returns -1.
ae_int_t i;
i = knnclassify(model, x);
_TestResult = _TestResult && doc_test_int(i, -1);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "knn_reg");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST autogk_d1
// Integrating f=exp(x) by adaptive integrator
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<6; _spoil_scenario++)
{
try
{
//
// This example demonstrates integration of f=exp(x) on [0,1]:
// * first, autogkstate is initialized
// * then we call integration function
// * and finally we obtain results with autogkresults() call
//
double a = 0;
if( _spoil_scenario==0 )
a = fp_nan;
if( _spoil_scenario==1 )
a = fp_posinf;
if( _spoil_scenario==2 )
a = fp_neginf;
double b = 1;
if( _spoil_scenario==3 )
b = fp_nan;
if( _spoil_scenario==4 )
b = fp_posinf;
if( _spoil_scenario==5 )
b = fp_neginf;
autogkstate s;
double v;
autogkreport rep;
autogksmooth(a, b, s);
alglib::autogkintegrate(s, int_function_1_func);
autogkresults(s, v, rep);
_TestResult = _TestResult && doc_test_real(v, 1.7182, 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "autogk_d1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST fft_complex_d1
// Complex FFT: simple example
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// first we demonstrate forward FFT:
// [1i,1i,1i,1i] is converted to [4i, 0, 0, 0]
//
complex_1d_array z = "[1i,1i,1i,1i]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(z);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(z);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(z);
fftc1d(z);
_TestResult = _TestResult && doc_test_complex_vector(z, "[4i,0,0,0]", 0.0001);
//
// now we convert [4i, 0, 0, 0] back to [1i,1i,1i,1i]
// with backward FFT
//
fftc1dinv(z);
_TestResult = _TestResult && doc_test_complex_vector(z, "[1i,1i,1i,1i]", 0.0001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "fft_complex_d1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST fft_complex_d2
// Complex FFT: advanced example
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// first we demonstrate forward FFT:
// [0,1,0,1i] is converted to [1+1i, -1-1i, -1-1i, 1+1i]
//
complex_1d_array z = "[0,1,0,1i]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(z);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(z);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(z);
fftc1d(z);
_TestResult = _TestResult && doc_test_complex_vector(z, "[1+1i, -1-1i, -1-1i, 1+1i]", 0.0001);
//
// now we convert result back with backward FFT
//
fftc1dinv(z);
_TestResult = _TestResult && doc_test_complex_vector(z, "[0,1,0,1i]", 0.0001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "fft_complex_d2");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST fft_real_d1
// Real FFT: simple example
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// first we demonstrate forward FFT:
// [1,1,1,1] is converted to [4, 0, 0, 0]
//
real_1d_array x = "[1,1,1,1]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
complex_1d_array f;
real_1d_array x2;
fftr1d(x, f);
_TestResult = _TestResult && doc_test_complex_vector(f, "[4,0,0,0]", 0.0001);
//
// now we convert [4, 0, 0, 0] back to [1,1,1,1]
// with backward FFT
//
fftr1dinv(f, x2);
_TestResult = _TestResult && doc_test_real_vector(x2, "[1,1,1,1]", 0.0001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "fft_real_d1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST fft_real_d2
// Real FFT: advanced example
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// first we demonstrate forward FFT:
// [1,2,3,4] is converted to [10, -2+2i, -2, -2-2i]
//
// note that output array is self-adjoint:
// * f[0] = conj(f[0])
// * f[1] = conj(f[3])
// * f[2] = conj(f[2])
//
real_1d_array x = "[1,2,3,4]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
complex_1d_array f;
real_1d_array x2;
fftr1d(x, f);
_TestResult = _TestResult && doc_test_complex_vector(f, "[10, -2+2i, -2, -2-2i]", 0.0001);
//
// now we convert [10, -2+2i, -2, -2-2i] back to [1,2,3,4]
//
fftr1dinv(f, x2);
_TestResult = _TestResult && doc_test_real_vector(x2, "[1,2,3,4]", 0.0001);
//
// remember that F is self-adjoint? It means that we can pass just half
// (slightly larger than half) of F to inverse real FFT and still get our result.
//
// I.e. instead [10, -2+2i, -2, -2-2i] we pass just [10, -2+2i, -2] and everything works!
//
// NOTE: in this case we should explicitly pass array length (which is 4) to ALGLIB;
// if not, it will automatically use array length to determine FFT size and
// will erroneously make half-length FFT.
//
f = "[10, -2+2i, -2]";
fftr1dinv(f, 4, x2);
_TestResult = _TestResult && doc_test_real_vector(x2, "[1,2,3,4]", 0.0001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "fft_real_d2");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST fft_complex_e1
// error detection in backward FFT
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
complex_1d_array z = "[0,2,0,-2]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(z);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(z);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(z);
fftc1dinv(z);
_TestResult = _TestResult && doc_test_complex_vector(z, "[0,1i,0,-1i]", 0.0001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "fft_complex_e1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST idw_d_mstab
// Simple model built with IDW-MSTAB algorithm
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// This example illustrates basic concepts of the IDW models:
// creation and evaluation.
//
// Suppose that we have set of 2-dimensional points with associated
// scalar function values, and we want to build an IDW model using
// our data.
//
// NOTE: we can work with N-dimensional models and vector-valued functions too :)
//
// Typical sequence of steps is given below:
// 1. we create IDW builder object
// 2. we attach our dataset to the IDW builder and tune algorithm settings
// 3. we generate IDW model
// 4. we use IDW model instance (evaluate, serialize, etc.)
//
double v;
//
// Step 1: IDW builder creation.
//
// We have to specify dimensionality of the space (2 or 3) and
// dimensionality of the function (scalar or vector).
//
// New builder object is empty - it has not dataset and uses
// default model construction settings
//
idwbuilder builder;
idwbuildercreate(2, 1, builder);
//
// Step 2: dataset addition
//
// XY contains two points - x0=(-1,0) and x1=(+1,0) -
// and two function values f(x0)=2, f(x1)=3.
//
real_2d_array xy = "[[-1,0,2],[+1,0,3]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
idwbuildersetpoints(builder, xy);
//
// Step 3: choose IDW algorithm and generate model
//
// We use modified stabilized IDW algorithm with following parameters:
// * SRad - set to 5.0 (search radius must be large enough)
//
// IDW-MSTAB algorithm is a state-of-the-art implementation of IDW which
// is competitive with RBFs and bicubic splines. See comments on the
// idwbuildersetalgomstab() function for more information.
//
idwmodel model;
idwreport rep;
idwbuildersetalgomstab(builder, 5.0);
idwfit(builder, model, rep);
//
// Step 4: model was built, evaluate its value
//
v = idwcalc2(model, 1.0, 0.0);
_TestResult = _TestResult && doc_test_real(v, 3.000, 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "idw_d_mstab");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST idw_d_serialize
// IDW model serialization/unserialization
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// This example shows how to serialize and unserialize IDW model.
//
// Suppose that we have set of 2-dimensional points with associated
// scalar function values, and we have built an IDW model using
// our data.
//
// This model can be serialized to string or stream. ALGLIB supports
// flexible (un)serialization, i.e. you can move serialized model
// representation between different machines (32-bit or 64-bit),
// different CPU architectures (x86/64, ARM) or even different
// programming languages supported by ALGLIB (C#, C++, ...).
//
// Our first step is to build model, evaluate it at point (1,0),
// and serialize it to string.
//
std::string s;
double v;
real_2d_array xy = "[[-1,0,2],[+1,0,3]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
idwbuilder builder;
idwmodel model;
idwmodel model2;
idwreport rep;
idwbuildercreate(2, 1, builder);
idwbuildersetpoints(builder, xy);
idwbuildersetalgomstab(builder, 5.0);
idwfit(builder, model, rep);
v = idwcalc2(model, 1.0, 0.0);
_TestResult = _TestResult && doc_test_real(v, 3.000, 0.005);
//
// Serialization + unserialization to a different instance
// of the model class.
//
alglib::idwserialize(model, s);
alglib::idwunserialize(s, model2);
//
// Evaluate unserialized model at the same point
//
v = idwcalc2(model2, 1.0, 0.0);
_TestResult = _TestResult && doc_test_real(v, 3.000, 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "idw_d_serialize");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST spline1d_d_linear
// Piecewise linear spline interpolation
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<12; _spoil_scenario++)
{
try
{
//
// We use piecewise linear spline to interpolate f(x)=x^2 sampled
// at 5 equidistant nodes on [-1,+1].
//
real_1d_array x = "[-1.0,-0.5,0.0,+0.5,+1.0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_adding_element(x);
if( _spoil_scenario==4 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[+1.0,0.25,0.0,0.25,+1.0]";
if( _spoil_scenario==5 )
spoil_vector_by_nan(y);
if( _spoil_scenario==6 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==7 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==8 )
spoil_vector_by_adding_element(y);
if( _spoil_scenario==9 )
spoil_vector_by_deleting_element(y);
double t = 0.25;
if( _spoil_scenario==10 )
t = fp_posinf;
if( _spoil_scenario==11 )
t = fp_neginf;
double v;
spline1dinterpolant s;
// build spline
spline1dbuildlinear(x, y, s);
// calculate S(0.25) - it is quite different from 0.25^2=0.0625
v = spline1dcalc(s, t);
_TestResult = _TestResult && doc_test_real(v, 0.125, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "spline1d_d_linear");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST spline1d_d_cubic
// Cubic spline interpolation
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<10; _spoil_scenario++)
{
try
{
//
// We use cubic spline to interpolate f(x)=x^2 sampled
// at 5 equidistant nodes on [-1,+1].
//
// First, we use default boundary conditions ("parabolically terminated
// spline") because cubic spline built with such boundary conditions
// will exactly reproduce any quadratic f(x).
//
// Then we try to use natural boundary conditions
// d2S(-1)/dx^2 = 0.0
// d2S(+1)/dx^2 = 0.0
// and see that such spline interpolated f(x) with small error.
//
real_1d_array x = "[-1.0,-0.5,0.0,+0.5,+1.0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[+1.0,0.25,0.0,0.25,+1.0]";
if( _spoil_scenario==4 )
spoil_vector_by_nan(y);
if( _spoil_scenario==5 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==6 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==7 )
spoil_vector_by_deleting_element(y);
double t = 0.25;
if( _spoil_scenario==8 )
t = fp_posinf;
if( _spoil_scenario==9 )
t = fp_neginf;
double v;
spline1dinterpolant s;
ae_int_t natural_bound_type = 2;
//
// Test exact boundary conditions: build S(x), calculare S(0.25)
// (almost same as original function)
//
spline1dbuildcubic(x, y, s);
v = spline1dcalc(s, t);
_TestResult = _TestResult && doc_test_real(v, 0.0625, 0.00001);
//
// Test natural boundary conditions: build S(x), calculare S(0.25)
// (small interpolation error)
//
spline1dbuildcubic(x, y, 5, natural_bound_type, 0.0, natural_bound_type, 0.0, s);
v = spline1dcalc(s, t);
_TestResult = _TestResult && doc_test_real(v, 0.0580, 0.0001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "spline1d_d_cubic");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST spline1d_d_monotone
// Monotone interpolation
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<10; _spoil_scenario++)
{
try
{
//
// Spline built witn spline1dbuildcubic() can be non-monotone even when
// Y-values form monotone sequence. Say, for x=[0,1,2] and y=[0,1,1]
// cubic spline will monotonically grow until x=1.5 and then start
// decreasing.
//
// That's why ALGLIB provides special spline construction function
// which builds spline which preserves monotonicity of the original
// dataset.
//
// NOTE: in case original dataset is non-monotonic, ALGLIB splits it
// into monotone subsequences and builds piecewise monotonic spline.
//
real_1d_array x = "[0,1,2]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_adding_element(x);
if( _spoil_scenario==4 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[0,1,1]";
if( _spoil_scenario==5 )
spoil_vector_by_nan(y);
if( _spoil_scenario==6 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==7 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==8 )
spoil_vector_by_adding_element(y);
if( _spoil_scenario==9 )
spoil_vector_by_deleting_element(y);
spline1dinterpolant s;
// build spline
spline1dbuildmonotone(x, y, s);
// calculate S at x = [-0.5, 0.0, 0.5, 1.0, 1.5, 2.0]
// you may see that spline is really monotonic
double v;
v = spline1dcalc(s, -0.5);
_TestResult = _TestResult && doc_test_real(v, 0.0000, 0.00005);
v = spline1dcalc(s, 0.0);
_TestResult = _TestResult && doc_test_real(v, 0.0000, 0.00005);
v = spline1dcalc(s, +0.5);
_TestResult = _TestResult && doc_test_real(v, 0.5000, 0.00005);
v = spline1dcalc(s, 1.0);
_TestResult = _TestResult && doc_test_real(v, 1.0000, 0.00005);
v = spline1dcalc(s, 1.5);
_TestResult = _TestResult && doc_test_real(v, 1.0000, 0.00005);
v = spline1dcalc(s, 2.0);
_TestResult = _TestResult && doc_test_real(v, 1.0000, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "spline1d_d_monotone");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST spline1d_d_griddiff
// Differentiation on the grid using cubic splines
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<10; _spoil_scenario++)
{
try
{
//
// We use cubic spline to do grid differentiation, i.e. having
// values of f(x)=x^2 sampled at 5 equidistant nodes on [-1,+1]
// we calculate derivatives of cubic spline at nodes WITHOUT
// CONSTRUCTION OF SPLINE OBJECT.
//
// There are efficient functions spline1dgriddiffcubic() and
// spline1dgriddiff2cubic() for such calculations.
//
// We use default boundary conditions ("parabolically terminated
// spline") because cubic spline built with such boundary conditions
// will exactly reproduce any quadratic f(x).
//
// Actually, we could use natural conditions, but we feel that
// spline which exactly reproduces f() will show us more
// understandable results.
//
real_1d_array x = "[-1.0,-0.5,0.0,+0.5,+1.0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_adding_element(x);
if( _spoil_scenario==4 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[+1.0,0.25,0.0,0.25,+1.0]";
if( _spoil_scenario==5 )
spoil_vector_by_nan(y);
if( _spoil_scenario==6 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==7 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==8 )
spoil_vector_by_adding_element(y);
if( _spoil_scenario==9 )
spoil_vector_by_deleting_element(y);
real_1d_array d1;
real_1d_array d2;
//
// We calculate first derivatives: they must be equal to 2*x
//
spline1dgriddiffcubic(x, y, d1);
_TestResult = _TestResult && doc_test_real_vector(d1, "[-2.0, -1.0, 0.0, +1.0, +2.0]", 0.0001);
//
// Now test griddiff2, which returns first AND second derivatives.
// First derivative is 2*x, second is equal to 2.0
//
spline1dgriddiff2cubic(x, y, d1, d2);
_TestResult = _TestResult && doc_test_real_vector(d1, "[-2.0, -1.0, 0.0, +1.0, +2.0]", 0.0001);
_TestResult = _TestResult && doc_test_real_vector(d2, "[ 2.0, 2.0, 2.0, 2.0, 2.0]", 0.0001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "spline1d_d_griddiff");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST spline1d_d_convdiff
// Resampling using cubic splines
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<11; _spoil_scenario++)
{
try
{
//
// We use cubic spline to do resampling, i.e. having
// values of f(x)=x^2 sampled at 5 equidistant nodes on [-1,+1]
// we calculate values/derivatives of cubic spline on
// another grid (equidistant with 9 nodes on [-1,+1])
// WITHOUT CONSTRUCTION OF SPLINE OBJECT.
//
// There are efficient functions spline1dconvcubic(),
// spline1dconvdiffcubic() and spline1dconvdiff2cubic()
// for such calculations.
//
// We use default boundary conditions ("parabolically terminated
// spline") because cubic spline built with such boundary conditions
// will exactly reproduce any quadratic f(x).
//
// Actually, we could use natural conditions, but we feel that
// spline which exactly reproduces f() will show us more
// understandable results.
//
real_1d_array x_old = "[-1.0,-0.5,0.0,+0.5,+1.0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x_old);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x_old);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x_old);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(x_old);
real_1d_array y_old = "[+1.0,0.25,0.0,0.25,+1.0]";
if( _spoil_scenario==4 )
spoil_vector_by_nan(y_old);
if( _spoil_scenario==5 )
spoil_vector_by_posinf(y_old);
if( _spoil_scenario==6 )
spoil_vector_by_neginf(y_old);
if( _spoil_scenario==7 )
spoil_vector_by_deleting_element(y_old);
real_1d_array x_new = "[-1.00,-0.75,-0.50,-0.25,0.00,+0.25,+0.50,+0.75,+1.00]";
if( _spoil_scenario==8 )
spoil_vector_by_nan(x_new);
if( _spoil_scenario==9 )
spoil_vector_by_posinf(x_new);
if( _spoil_scenario==10 )
spoil_vector_by_neginf(x_new);
real_1d_array y_new;
real_1d_array d1_new;
real_1d_array d2_new;
//
// First, conversion without differentiation.
//
//
spline1dconvcubic(x_old, y_old, x_new, y_new);
_TestResult = _TestResult && doc_test_real_vector(y_new, "[1.0000, 0.5625, 0.2500, 0.0625, 0.0000, 0.0625, 0.2500, 0.5625, 1.0000]", 0.0001);
//
// Then, conversion with differentiation (first derivatives only)
//
//
spline1dconvdiffcubic(x_old, y_old, x_new, y_new, d1_new);
_TestResult = _TestResult && doc_test_real_vector(y_new, "[1.0000, 0.5625, 0.2500, 0.0625, 0.0000, 0.0625, 0.2500, 0.5625, 1.0000]", 0.0001);
_TestResult = _TestResult && doc_test_real_vector(d1_new, "[-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0]", 0.0001);
//
// Finally, conversion with first and second derivatives
//
//
spline1dconvdiff2cubic(x_old, y_old, x_new, y_new, d1_new, d2_new);
_TestResult = _TestResult && doc_test_real_vector(y_new, "[1.0000, 0.5625, 0.2500, 0.0625, 0.0000, 0.0625, 0.2500, 0.5625, 1.0000]", 0.0001);
_TestResult = _TestResult && doc_test_real_vector(d1_new, "[-2.0, -1.5, -1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0]", 0.0001);
_TestResult = _TestResult && doc_test_real_vector(d2_new, "[2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0]", 0.0001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "spline1d_d_convdiff");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST parametric_rdp
// Parametric Ramer-Douglas-Peucker approximation
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<7; _spoil_scenario++)
{
try
{
//
// We use RDP algorithm to approximate parametric 2D curve given by
// locations in t=0,1,2,3 (see below), which form piecewise linear
// trajectory through D-dimensional space (2-dimensional in our example).
//
// |
// |
// - * * X2................X3
// | .
// | .
// - * * . * * * *
// | .
// | .
// - * X1 * * * *
// | .....
// | ....
// X0----|-----|-----|-----|-----|-----|---
//
ae_int_t npoints = 4;
ae_int_t ndimensions = 2;
real_2d_array x = "[[0,0],[2,1],[3,3],[6,3]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(x);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(x);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(x);
if( _spoil_scenario==3 )
spoil_matrix_by_deleting_row(x);
if( _spoil_scenario==4 )
spoil_matrix_by_deleting_col(x);
//
// Approximation of parametric curve is performed by another parametric curve
// with lesser amount of points. It allows to work with "compressed"
// representation, which needs smaller amount of memory. Say, in our example
// (we allow points with error smaller than 0.8) approximation will have
// just two sequential sections connecting X0 with X2, and X2 with X3.
//
// |
// |
// - * * X2................X3
// | .
// | .
// - * . * * * *
// | .
// | .
// - . X1 * * * *
// | .
// | .
// X0----|-----|-----|-----|-----|-----|---
//
//
real_2d_array y;
integer_1d_array idxy;
ae_int_t nsections;
ae_int_t limitcnt = 0;
double limiteps = 0.8;
if( _spoil_scenario==5 )
limiteps = fp_posinf;
if( _spoil_scenario==6 )
limiteps = fp_neginf;
parametricrdpfixed(x, npoints, ndimensions, limitcnt, limiteps, y, idxy, nsections);
_TestResult = _TestResult && doc_test_int(nsections, 2);
_TestResult = _TestResult && doc_test_int_vector(idxy, "[0,2,3]");
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "parametric_rdp");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST spline3d_trilinear
// Trilinear spline interpolation
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<22; _spoil_scenario++)
{
try
{
//
// We use trilinear spline to interpolate f(x,y,z)=x+xy+z sampled
// at (x,y,z) from [0.0, 1.0] X [0.0, 1.0] X [0.0, 1.0].
//
// We store x, y and z-values at local arrays with same names.
// Function values are stored in the array F as follows:
// f[0] (x,y,z) = (0,0,0)
// f[1] (x,y,z) = (1,0,0)
// f[2] (x,y,z) = (0,1,0)
// f[3] (x,y,z) = (1,1,0)
// f[4] (x,y,z) = (0,0,1)
// f[5] (x,y,z) = (1,0,1)
// f[6] (x,y,z) = (0,1,1)
// f[7] (x,y,z) = (1,1,1)
//
real_1d_array x = "[0.0, 1.0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[0.0, 1.0]";
if( _spoil_scenario==4 )
spoil_vector_by_nan(y);
if( _spoil_scenario==5 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==6 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==7 )
spoil_vector_by_deleting_element(y);
real_1d_array z = "[0.0, 1.0]";
if( _spoil_scenario==8 )
spoil_vector_by_nan(z);
if( _spoil_scenario==9 )
spoil_vector_by_posinf(z);
if( _spoil_scenario==10 )
spoil_vector_by_neginf(z);
if( _spoil_scenario==11 )
spoil_vector_by_deleting_element(z);
real_1d_array f = "[0,1,0,2,1,2,1,3]";
if( _spoil_scenario==12 )
spoil_vector_by_nan(f);
if( _spoil_scenario==13 )
spoil_vector_by_posinf(f);
if( _spoil_scenario==14 )
spoil_vector_by_neginf(f);
if( _spoil_scenario==15 )
spoil_vector_by_deleting_element(f);
double vx = 0.50;
if( _spoil_scenario==16 )
vx = fp_posinf;
if( _spoil_scenario==17 )
vx = fp_neginf;
double vy = 0.50;
if( _spoil_scenario==18 )
vy = fp_posinf;
if( _spoil_scenario==19 )
vy = fp_neginf;
double vz = 0.50;
if( _spoil_scenario==20 )
vz = fp_posinf;
if( _spoil_scenario==21 )
vz = fp_neginf;
double v;
spline3dinterpolant s;
// build spline
spline3dbuildtrilinearv(x, 2, y, 2, z, 2, f, 1, s);
// calculate S(0.5,0.5,0.5)
v = spline3dcalc(s, vx, vy, vz);
_TestResult = _TestResult && doc_test_real(v, 1.2500, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "spline3d_trilinear");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST spline3d_vector
// Vector-valued trilinear spline interpolation
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<22; _spoil_scenario++)
{
try
{
//
// We use trilinear vector-valued spline to interpolate {f0,f1}={x+xy+z,x+xy+yz+z}
// sampled at (x,y,z) from [0.0, 1.0] X [0.0, 1.0] X [0.0, 1.0].
//
// We store x, y and z-values at local arrays with same names.
// Function values are stored in the array F as follows:
// f[0] f0, (x,y,z) = (0,0,0)
// f[1] f1, (x,y,z) = (0,0,0)
// f[2] f0, (x,y,z) = (1,0,0)
// f[3] f1, (x,y,z) = (1,0,0)
// f[4] f0, (x,y,z) = (0,1,0)
// f[5] f1, (x,y,z) = (0,1,0)
// f[6] f0, (x,y,z) = (1,1,0)
// f[7] f1, (x,y,z) = (1,1,0)
// f[8] f0, (x,y,z) = (0,0,1)
// f[9] f1, (x,y,z) = (0,0,1)
// f[10] f0, (x,y,z) = (1,0,1)
// f[11] f1, (x,y,z) = (1,0,1)
// f[12] f0, (x,y,z) = (0,1,1)
// f[13] f1, (x,y,z) = (0,1,1)
// f[14] f0, (x,y,z) = (1,1,1)
// f[15] f1, (x,y,z) = (1,1,1)
//
real_1d_array x = "[0.0, 1.0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[0.0, 1.0]";
if( _spoil_scenario==4 )
spoil_vector_by_nan(y);
if( _spoil_scenario==5 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==6 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==7 )
spoil_vector_by_deleting_element(y);
real_1d_array z = "[0.0, 1.0]";
if( _spoil_scenario==8 )
spoil_vector_by_nan(z);
if( _spoil_scenario==9 )
spoil_vector_by_posinf(z);
if( _spoil_scenario==10 )
spoil_vector_by_neginf(z);
if( _spoil_scenario==11 )
spoil_vector_by_deleting_element(z);
real_1d_array f = "[0,0, 1,1, 0,0, 2,2, 1,1, 2,2, 1,2, 3,4]";
if( _spoil_scenario==12 )
spoil_vector_by_nan(f);
if( _spoil_scenario==13 )
spoil_vector_by_posinf(f);
if( _spoil_scenario==14 )
spoil_vector_by_neginf(f);
if( _spoil_scenario==15 )
spoil_vector_by_deleting_element(f);
double vx = 0.50;
if( _spoil_scenario==16 )
vx = fp_posinf;
if( _spoil_scenario==17 )
vx = fp_neginf;
double vy = 0.50;
if( _spoil_scenario==18 )
vy = fp_posinf;
if( _spoil_scenario==19 )
vy = fp_neginf;
double vz = 0.50;
if( _spoil_scenario==20 )
vz = fp_posinf;
if( _spoil_scenario==21 )
vz = fp_neginf;
spline3dinterpolant s;
// build spline
spline3dbuildtrilinearv(x, 2, y, 2, z, 2, f, 2, s);
// calculate S(0.5,0.5,0.5) - we have vector of values instead of single value
real_1d_array v;
spline3dcalcv(s, vx, vy, vz, v);
_TestResult = _TestResult && doc_test_real_vector(v, "[1.2500,1.5000]", 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "spline3d_vector");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST polint_d_calcdiff
// Interpolation and differentiation using barycentric representation
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<12; _spoil_scenario++)
{
try
{
//
// Here we demonstrate polynomial interpolation and differentiation
// of y=x^2-x sampled at [0,1,2]. Barycentric representation of polynomial is used.
//
real_1d_array x = "[0,1,2]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_adding_element(x);
if( _spoil_scenario==4 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[0,0,2]";
if( _spoil_scenario==5 )
spoil_vector_by_nan(y);
if( _spoil_scenario==6 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==7 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==8 )
spoil_vector_by_adding_element(y);
if( _spoil_scenario==9 )
spoil_vector_by_deleting_element(y);
double t = -1;
if( _spoil_scenario==10 )
t = fp_posinf;
if( _spoil_scenario==11 )
t = fp_neginf;
double v;
double dv;
double d2v;
barycentricinterpolant p;
// barycentric model is created
polynomialbuild(x, y, p);
// barycentric interpolation is demonstrated
v = barycentriccalc(p, t);
_TestResult = _TestResult && doc_test_real(v, 2.0, 0.00005);
// barycentric differentation is demonstrated
barycentricdiff1(p, t, v, dv);
_TestResult = _TestResult && doc_test_real(v, 2.0, 0.00005);
_TestResult = _TestResult && doc_test_real(dv, -3.0, 0.00005);
// second derivatives with barycentric representation
barycentricdiff1(p, t, v, dv);
_TestResult = _TestResult && doc_test_real(v, 2.0, 0.00005);
_TestResult = _TestResult && doc_test_real(dv, -3.0, 0.00005);
barycentricdiff2(p, t, v, dv, d2v);
_TestResult = _TestResult && doc_test_real(v, 2.0, 0.00005);
_TestResult = _TestResult && doc_test_real(dv, -3.0, 0.00005);
_TestResult = _TestResult && doc_test_real(d2v, 2.0, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "polint_d_calcdiff");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST polint_d_conv
// Conversion between power basis and barycentric representation
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<5; _spoil_scenario++)
{
try
{
//
// Here we demonstrate conversion of y=x^2-x
// between power basis and barycentric representation.
//
real_1d_array a = "[0,-1,+1]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(a);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(a);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(a);
double t = 2;
if( _spoil_scenario==3 )
t = fp_posinf;
if( _spoil_scenario==4 )
t = fp_neginf;
real_1d_array a2;
double v;
barycentricinterpolant p;
//
// a=[0,-1,+1] is decomposition of y=x^2-x in the power basis:
//
// y = 0 - 1*x + 1*x^2
//
// We convert it to the barycentric form.
//
polynomialpow2bar(a, p);
// now we have barycentric interpolation; we can use it for interpolation
v = barycentriccalc(p, t);
_TestResult = _TestResult && doc_test_real(v, 2.0, 0.005);
// we can also convert back from barycentric representation to power basis
polynomialbar2pow(p, a2);
_TestResult = _TestResult && doc_test_real_vector(a2, "[0,-1,+1]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "polint_d_conv");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST polint_d_spec
// Polynomial interpolation on special grids (equidistant, Chebyshev I/II)
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<11; _spoil_scenario++)
{
try
{
//
// Temporaries:
// * values of y=x^2-x sampled at three special grids:
// * equdistant grid spanning [0,2], x[i] = 2*i/(N-1), i=0..N-1
// * Chebyshev-I grid spanning [-1,+1], x[i] = 1 + Cos(PI*(2*i+1)/(2*n)), i=0..N-1
// * Chebyshev-II grid spanning [-1,+1], x[i] = 1 + Cos(PI*i/(n-1)), i=0..N-1
// * barycentric interpolants for these three grids
// * vectors to store coefficients of quadratic representation
//
real_1d_array y_eqdist = "[0,0,2]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(y_eqdist);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(y_eqdist);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(y_eqdist);
real_1d_array y_cheb1 = "[-0.116025,0.000000,1.616025]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(y_cheb1);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(y_cheb1);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(y_cheb1);
real_1d_array y_cheb2 = "[0,0,2]";
if( _spoil_scenario==6 )
spoil_vector_by_nan(y_cheb2);
if( _spoil_scenario==7 )
spoil_vector_by_posinf(y_cheb2);
if( _spoil_scenario==8 )
spoil_vector_by_neginf(y_cheb2);
barycentricinterpolant p_eqdist;
barycentricinterpolant p_cheb1;
barycentricinterpolant p_cheb2;
real_1d_array a_eqdist;
real_1d_array a_cheb1;
real_1d_array a_cheb2;
//
// First, we demonstrate construction of barycentric interpolants on
// special grids. We unpack power representation to ensure that
// interpolant was built correctly.
//
// In all three cases we should get same quadratic function.
//
polynomialbuildeqdist(0.0, 2.0, y_eqdist, p_eqdist);
polynomialbar2pow(p_eqdist, a_eqdist);
_TestResult = _TestResult && doc_test_real_vector(a_eqdist, "[0,-1,+1]", 0.00005);
polynomialbuildcheb1(-1, +1, y_cheb1, p_cheb1);
polynomialbar2pow(p_cheb1, a_cheb1);
_TestResult = _TestResult && doc_test_real_vector(a_cheb1, "[0,-1,+1]", 0.00005);
polynomialbuildcheb2(-1, +1, y_cheb2, p_cheb2);
polynomialbar2pow(p_cheb2, a_cheb2);
_TestResult = _TestResult && doc_test_real_vector(a_cheb2, "[0,-1,+1]", 0.00005);
//
// Now we demonstrate polynomial interpolation without construction
// of the barycentricinterpolant structure.
//
// We calculate interpolant value at x=-2.
// In all three cases we should get same f=6
//
double t = -2;
if( _spoil_scenario==9 )
t = fp_posinf;
if( _spoil_scenario==10 )
t = fp_neginf;
double v;
v = polynomialcalceqdist(0.0, 2.0, y_eqdist, t);
_TestResult = _TestResult && doc_test_real(v, 6.0, 0.00005);
v = polynomialcalccheb1(-1, +1, y_cheb1, t);
_TestResult = _TestResult && doc_test_real(v, 6.0, 0.00005);
v = polynomialcalccheb2(-1, +1, y_cheb2, t);
_TestResult = _TestResult && doc_test_real(v, 6.0, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "polint_d_spec");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST polint_t_1
// Polynomial interpolation, full list of parameters.
//
printf("100/151\n");
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<10; _spoil_scenario++)
{
try
{
real_1d_array x = "[0,1,2]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[0,0,2]";
if( _spoil_scenario==4 )
spoil_vector_by_nan(y);
if( _spoil_scenario==5 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==6 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==7 )
spoil_vector_by_deleting_element(y);
double t = -1;
if( _spoil_scenario==8 )
t = fp_posinf;
if( _spoil_scenario==9 )
t = fp_neginf;
barycentricinterpolant p;
double v;
polynomialbuild(x, y, 3, p);
v = barycentriccalc(p, t);
_TestResult = _TestResult && doc_test_real(v, 2.0, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "polint_t_1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST polint_t_2
// Polynomial interpolation, full list of parameters.
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<6; _spoil_scenario++)
{
try
{
real_1d_array y = "[0,0,2]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(y);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(y);
double t = -1;
if( _spoil_scenario==4 )
t = fp_posinf;
if( _spoil_scenario==5 )
t = fp_neginf;
barycentricinterpolant p;
double v;
polynomialbuildeqdist(0.0, 2.0, y, 3, p);
v = barycentriccalc(p, t);
_TestResult = _TestResult && doc_test_real(v, 2.0, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "polint_t_2");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST polint_t_3
// Polynomial interpolation, full list of parameters.
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<6; _spoil_scenario++)
{
try
{
real_1d_array y = "[-0.116025,0.000000,1.616025]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(y);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(y);
double t = -1;
if( _spoil_scenario==4 )
t = fp_posinf;
if( _spoil_scenario==5 )
t = fp_neginf;
barycentricinterpolant p;
double v;
polynomialbuildcheb1(-1.0, +1.0, y, 3, p);
v = barycentriccalc(p, t);
_TestResult = _TestResult && doc_test_real(v, 2.0, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "polint_t_3");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST polint_t_4
// Polynomial interpolation, full list of parameters.
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<12; _spoil_scenario++)
{
try
{
real_1d_array y = "[0,0,2]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(y);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(y);
double t = -2;
if( _spoil_scenario==4 )
t = fp_posinf;
if( _spoil_scenario==5 )
t = fp_neginf;
double a = -1;
if( _spoil_scenario==6 )
a = fp_nan;
if( _spoil_scenario==7 )
a = fp_posinf;
if( _spoil_scenario==8 )
a = fp_neginf;
double b = +1;
if( _spoil_scenario==9 )
b = fp_nan;
if( _spoil_scenario==10 )
b = fp_posinf;
if( _spoil_scenario==11 )
b = fp_neginf;
barycentricinterpolant p;
double v;
polynomialbuildcheb2(a, b, y, 3, p);
v = barycentriccalc(p, t);
_TestResult = _TestResult && doc_test_real(v, 6.0, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "polint_t_4");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST polint_t_5
// Polynomial interpolation, full list of parameters.
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<6; _spoil_scenario++)
{
try
{
real_1d_array y = "[0,0,2]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(y);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(y);
double t = -1;
if( _spoil_scenario==4 )
t = fp_posinf;
if( _spoil_scenario==5 )
t = fp_neginf;
double v;
v = polynomialcalceqdist(0.0, 2.0, y, 3, t);
_TestResult = _TestResult && doc_test_real(v, 2.0, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "polint_t_5");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST polint_t_6
// Polynomial interpolation, full list of parameters.
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<12; _spoil_scenario++)
{
try
{
real_1d_array y = "[-0.116025,0.000000,1.616025]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(y);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(y);
double t = -1;
if( _spoil_scenario==4 )
t = fp_posinf;
if( _spoil_scenario==5 )
t = fp_neginf;
double a = -1;
if( _spoil_scenario==6 )
a = fp_nan;
if( _spoil_scenario==7 )
a = fp_posinf;
if( _spoil_scenario==8 )
a = fp_neginf;
double b = +1;
if( _spoil_scenario==9 )
b = fp_nan;
if( _spoil_scenario==10 )
b = fp_posinf;
if( _spoil_scenario==11 )
b = fp_neginf;
double v;
v = polynomialcalccheb1(a, b, y, 3, t);
_TestResult = _TestResult && doc_test_real(v, 2.0, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "polint_t_6");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST polint_t_7
// Polynomial interpolation, full list of parameters.
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<12; _spoil_scenario++)
{
try
{
real_1d_array y = "[0,0,2]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(y);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(y);
double t = -2;
if( _spoil_scenario==4 )
t = fp_posinf;
if( _spoil_scenario==5 )
t = fp_neginf;
double a = -1;
if( _spoil_scenario==6 )
a = fp_nan;
if( _spoil_scenario==7 )
a = fp_posinf;
if( _spoil_scenario==8 )
a = fp_neginf;
double b = +1;
if( _spoil_scenario==9 )
b = fp_nan;
if( _spoil_scenario==10 )
b = fp_posinf;
if( _spoil_scenario==11 )
b = fp_neginf;
double v;
v = polynomialcalccheb2(a, b, y, 3, t);
_TestResult = _TestResult && doc_test_real(v, 6.0, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "polint_t_7");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST polint_t_8
// Polynomial interpolation: y=x^2-x, equidistant grid, barycentric form
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<5; _spoil_scenario++)
{
try
{
real_1d_array y = "[0,0,2]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(y);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(y);
double t = -1;
if( _spoil_scenario==3 )
t = fp_posinf;
if( _spoil_scenario==4 )
t = fp_neginf;
barycentricinterpolant p;
double v;
polynomialbuildeqdist(0.0, 2.0, y, p);
v = barycentriccalc(p, t);
_TestResult = _TestResult && doc_test_real(v, 2.0, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "polint_t_8");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST polint_t_9
// Polynomial interpolation: y=x^2-x, Chebyshev grid (first kind), barycentric form
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<11; _spoil_scenario++)
{
try
{
real_1d_array y = "[-0.116025,0.000000,1.616025]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(y);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(y);
double t = -1;
if( _spoil_scenario==3 )
t = fp_posinf;
if( _spoil_scenario==4 )
t = fp_neginf;
double a = -1;
if( _spoil_scenario==5 )
a = fp_nan;
if( _spoil_scenario==6 )
a = fp_posinf;
if( _spoil_scenario==7 )
a = fp_neginf;
double b = +1;
if( _spoil_scenario==8 )
b = fp_nan;
if( _spoil_scenario==9 )
b = fp_posinf;
if( _spoil_scenario==10 )
b = fp_neginf;
barycentricinterpolant p;
double v;
polynomialbuildcheb1(a, b, y, p);
v = barycentriccalc(p, t);
_TestResult = _TestResult && doc_test_real(v, 2.0, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "polint_t_9");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST polint_t_10
// Polynomial interpolation: y=x^2-x, Chebyshev grid (second kind), barycentric form
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<11; _spoil_scenario++)
{
try
{
real_1d_array y = "[0,0,2]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(y);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(y);
double t = -2;
if( _spoil_scenario==3 )
t = fp_posinf;
if( _spoil_scenario==4 )
t = fp_neginf;
double a = -1;
if( _spoil_scenario==5 )
a = fp_nan;
if( _spoil_scenario==6 )
a = fp_posinf;
if( _spoil_scenario==7 )
a = fp_neginf;
double b = +1;
if( _spoil_scenario==8 )
b = fp_nan;
if( _spoil_scenario==9 )
b = fp_posinf;
if( _spoil_scenario==10 )
b = fp_neginf;
barycentricinterpolant p;
double v;
polynomialbuildcheb2(a, b, y, p);
v = barycentriccalc(p, t);
_TestResult = _TestResult && doc_test_real(v, 6.0, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "polint_t_10");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST polint_t_11
// Polynomial interpolation: y=x^2-x, equidistant grid
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<5; _spoil_scenario++)
{
try
{
real_1d_array y = "[0,0,2]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(y);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(y);
double t = -1;
if( _spoil_scenario==3 )
t = fp_posinf;
if( _spoil_scenario==4 )
t = fp_neginf;
double v;
v = polynomialcalceqdist(0.0, 2.0, y, t);
_TestResult = _TestResult && doc_test_real(v, 2.0, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "polint_t_11");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST polint_t_12
// Polynomial interpolation: y=x^2-x, Chebyshev grid (first kind)
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<11; _spoil_scenario++)
{
try
{
real_1d_array y = "[-0.116025,0.000000,1.616025]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(y);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(y);
double t = -1;
if( _spoil_scenario==3 )
t = fp_posinf;
if( _spoil_scenario==4 )
t = fp_neginf;
double a = -1;
if( _spoil_scenario==5 )
a = fp_nan;
if( _spoil_scenario==6 )
a = fp_posinf;
if( _spoil_scenario==7 )
a = fp_neginf;
double b = +1;
if( _spoil_scenario==8 )
b = fp_nan;
if( _spoil_scenario==9 )
b = fp_posinf;
if( _spoil_scenario==10 )
b = fp_neginf;
double v;
v = polynomialcalccheb1(a, b, y, t);
_TestResult = _TestResult && doc_test_real(v, 2.0, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "polint_t_12");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST polint_t_13
// Polynomial interpolation: y=x^2-x, Chebyshev grid (second kind)
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<11; _spoil_scenario++)
{
try
{
real_1d_array y = "[0,0,2]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(y);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(y);
double t = -2;
if( _spoil_scenario==3 )
t = fp_posinf;
if( _spoil_scenario==4 )
t = fp_neginf;
double a = -1;
if( _spoil_scenario==5 )
a = fp_nan;
if( _spoil_scenario==6 )
a = fp_posinf;
if( _spoil_scenario==7 )
a = fp_neginf;
double b = +1;
if( _spoil_scenario==8 )
b = fp_nan;
if( _spoil_scenario==9 )
b = fp_posinf;
if( _spoil_scenario==10 )
b = fp_neginf;
double v;
v = polynomialcalccheb2(a, b, y, t);
_TestResult = _TestResult && doc_test_real(v, 6.0, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "polint_t_13");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST lsfit_d_nlf
// Nonlinear fitting using function value only
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<24; _spoil_scenario++)
{
try
{
//
// In this example we demonstrate exponential fitting
// by f(x) = exp(-c*x^2)
// using function value only.
//
// Gradient is estimated using combination of numerical differences
// and secant updates. diffstep variable stores differentiation step
// (we have to tell algorithm what step to use).
//
real_2d_array x = "[[-1],[-0.8],[-0.6],[-0.4],[-0.2],[0],[0.2],[0.4],[0.6],[0.8],[1.0]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(x);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(x);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(x);
if( _spoil_scenario==3 )
spoil_matrix_by_deleting_row(x);
if( _spoil_scenario==4 )
spoil_matrix_by_deleting_col(x);
real_1d_array y = "[0.223130, 0.382893, 0.582748, 0.786628, 0.941765, 1.000000, 0.941765, 0.786628, 0.582748, 0.382893, 0.223130]";
if( _spoil_scenario==5 )
spoil_vector_by_nan(y);
if( _spoil_scenario==6 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==7 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==8 )
spoil_vector_by_adding_element(y);
if( _spoil_scenario==9 )
spoil_vector_by_deleting_element(y);
real_1d_array c = "[0.3]";
if( _spoil_scenario==10 )
spoil_vector_by_nan(c);
if( _spoil_scenario==11 )
spoil_vector_by_posinf(c);
if( _spoil_scenario==12 )
spoil_vector_by_neginf(c);
double epsx = 0.000001;
if( _spoil_scenario==13 )
epsx = fp_nan;
if( _spoil_scenario==14 )
epsx = fp_posinf;
if( _spoil_scenario==15 )
epsx = fp_neginf;
ae_int_t maxits = 0;
ae_int_t info;
lsfitstate state;
lsfitreport rep;
double diffstep = 0.0001;
if( _spoil_scenario==16 )
diffstep = fp_nan;
if( _spoil_scenario==17 )
diffstep = fp_posinf;
if( _spoil_scenario==18 )
diffstep = fp_neginf;
//
// Fitting without weights
//
lsfitcreatef(x, y, c, diffstep, state);
lsfitsetcond(state, epsx, maxits);
alglib::lsfitfit(state, function_cx_1_func);
lsfitresults(state, info, c, rep);
_TestResult = _TestResult && doc_test_int(info, 2);
_TestResult = _TestResult && doc_test_real_vector(c, "[1.5]", 0.05);
//
// Fitting with weights
// (you can change weights and see how it changes result)
//
real_1d_array w = "[1,1,1,1,1,1,1,1,1,1,1]";
if( _spoil_scenario==19 )
spoil_vector_by_nan(w);
if( _spoil_scenario==20 )
spoil_vector_by_posinf(w);
if( _spoil_scenario==21 )
spoil_vector_by_neginf(w);
if( _spoil_scenario==22 )
spoil_vector_by_adding_element(w);
if( _spoil_scenario==23 )
spoil_vector_by_deleting_element(w);
lsfitcreatewf(x, y, w, c, diffstep, state);
lsfitsetcond(state, epsx, maxits);
alglib::lsfitfit(state, function_cx_1_func);
lsfitresults(state, info, c, rep);
_TestResult = _TestResult && doc_test_int(info, 2);
_TestResult = _TestResult && doc_test_real_vector(c, "[1.5]", 0.05);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "lsfit_d_nlf");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST lsfit_d_nlfg
// Nonlinear fitting using gradient
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<21; _spoil_scenario++)
{
try
{
//
// In this example we demonstrate exponential fitting
// by f(x) = exp(-c*x^2)
// using function value and gradient (with respect to c).
//
real_2d_array x = "[[-1],[-0.8],[-0.6],[-0.4],[-0.2],[0],[0.2],[0.4],[0.6],[0.8],[1.0]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(x);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(x);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(x);
if( _spoil_scenario==3 )
spoil_matrix_by_deleting_row(x);
if( _spoil_scenario==4 )
spoil_matrix_by_deleting_col(x);
real_1d_array y = "[0.223130, 0.382893, 0.582748, 0.786628, 0.941765, 1.000000, 0.941765, 0.786628, 0.582748, 0.382893, 0.223130]";
if( _spoil_scenario==5 )
spoil_vector_by_nan(y);
if( _spoil_scenario==6 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==7 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==8 )
spoil_vector_by_adding_element(y);
if( _spoil_scenario==9 )
spoil_vector_by_deleting_element(y);
real_1d_array c = "[0.3]";
if( _spoil_scenario==10 )
spoil_vector_by_nan(c);
if( _spoil_scenario==11 )
spoil_vector_by_posinf(c);
if( _spoil_scenario==12 )
spoil_vector_by_neginf(c);
double epsx = 0.000001;
if( _spoil_scenario==13 )
epsx = fp_nan;
if( _spoil_scenario==14 )
epsx = fp_posinf;
if( _spoil_scenario==15 )
epsx = fp_neginf;
ae_int_t maxits = 0;
ae_int_t info;
lsfitstate state;
lsfitreport rep;
//
// Fitting without weights
//
lsfitcreatefg(x, y, c, true, state);
lsfitsetcond(state, epsx, maxits);
alglib::lsfitfit(state, function_cx_1_func, function_cx_1_grad);
lsfitresults(state, info, c, rep);
_TestResult = _TestResult && doc_test_int(info, 2);
_TestResult = _TestResult && doc_test_real_vector(c, "[1.5]", 0.05);
//
// Fitting with weights
// (you can change weights and see how it changes result)
//
real_1d_array w = "[1,1,1,1,1,1,1,1,1,1,1]";
if( _spoil_scenario==16 )
spoil_vector_by_nan(w);
if( _spoil_scenario==17 )
spoil_vector_by_posinf(w);
if( _spoil_scenario==18 )
spoil_vector_by_neginf(w);
if( _spoil_scenario==19 )
spoil_vector_by_adding_element(w);
if( _spoil_scenario==20 )
spoil_vector_by_deleting_element(w);
lsfitcreatewfg(x, y, w, c, true, state);
lsfitsetcond(state, epsx, maxits);
alglib::lsfitfit(state, function_cx_1_func, function_cx_1_grad);
lsfitresults(state, info, c, rep);
_TestResult = _TestResult && doc_test_int(info, 2);
_TestResult = _TestResult && doc_test_real_vector(c, "[1.5]", 0.05);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "lsfit_d_nlfg");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST lsfit_d_nlfgh
// Nonlinear fitting using gradient and Hessian
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<21; _spoil_scenario++)
{
try
{
//
// In this example we demonstrate exponential fitting
// by f(x) = exp(-c*x^2)
// using function value, gradient and Hessian (with respect to c)
//
real_2d_array x = "[[-1],[-0.8],[-0.6],[-0.4],[-0.2],[0],[0.2],[0.4],[0.6],[0.8],[1.0]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(x);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(x);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(x);
if( _spoil_scenario==3 )
spoil_matrix_by_deleting_row(x);
if( _spoil_scenario==4 )
spoil_matrix_by_deleting_col(x);
real_1d_array y = "[0.223130, 0.382893, 0.582748, 0.786628, 0.941765, 1.000000, 0.941765, 0.786628, 0.582748, 0.382893, 0.223130]";
if( _spoil_scenario==5 )
spoil_vector_by_nan(y);
if( _spoil_scenario==6 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==7 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==8 )
spoil_vector_by_adding_element(y);
if( _spoil_scenario==9 )
spoil_vector_by_deleting_element(y);
real_1d_array c = "[0.3]";
if( _spoil_scenario==10 )
spoil_vector_by_nan(c);
if( _spoil_scenario==11 )
spoil_vector_by_posinf(c);
if( _spoil_scenario==12 )
spoil_vector_by_neginf(c);
double epsx = 0.000001;
if( _spoil_scenario==13 )
epsx = fp_nan;
if( _spoil_scenario==14 )
epsx = fp_posinf;
if( _spoil_scenario==15 )
epsx = fp_neginf;
ae_int_t maxits = 0;
ae_int_t info;
lsfitstate state;
lsfitreport rep;
//
// Fitting without weights
//
lsfitcreatefgh(x, y, c, state);
lsfitsetcond(state, epsx, maxits);
alglib::lsfitfit(state, function_cx_1_func, function_cx_1_grad, function_cx_1_hess);
lsfitresults(state, info, c, rep);
_TestResult = _TestResult && doc_test_int(info, 2);
_TestResult = _TestResult && doc_test_real_vector(c, "[1.5]", 0.05);
//
// Fitting with weights
// (you can change weights and see how it changes result)
//
real_1d_array w = "[1,1,1,1,1,1,1,1,1,1,1]";
if( _spoil_scenario==16 )
spoil_vector_by_nan(w);
if( _spoil_scenario==17 )
spoil_vector_by_posinf(w);
if( _spoil_scenario==18 )
spoil_vector_by_neginf(w);
if( _spoil_scenario==19 )
spoil_vector_by_adding_element(w);
if( _spoil_scenario==20 )
spoil_vector_by_deleting_element(w);
lsfitcreatewfgh(x, y, w, c, state);
lsfitsetcond(state, epsx, maxits);
alglib::lsfitfit(state, function_cx_1_func, function_cx_1_grad, function_cx_1_hess);
lsfitresults(state, info, c, rep);
_TestResult = _TestResult && doc_test_int(info, 2);
_TestResult = _TestResult && doc_test_real_vector(c, "[1.5]", 0.05);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "lsfit_d_nlfgh");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST lsfit_d_nlfb
// Bound contstrained nonlinear fitting using function value only
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<23; _spoil_scenario++)
{
try
{
//
// In this example we demonstrate exponential fitting by
// f(x) = exp(-c*x^2)
// subject to bound constraints
// 0.0 <= c <= 1.0
// using function value only.
//
// Gradient is estimated using combination of numerical differences
// and secant updates. diffstep variable stores differentiation step
// (we have to tell algorithm what step to use).
//
// Unconstrained solution is c=1.5, but because of constraints we should
// get c=1.0 (at the boundary).
//
real_2d_array x = "[[-1],[-0.8],[-0.6],[-0.4],[-0.2],[0],[0.2],[0.4],[0.6],[0.8],[1.0]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(x);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(x);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(x);
if( _spoil_scenario==3 )
spoil_matrix_by_deleting_row(x);
if( _spoil_scenario==4 )
spoil_matrix_by_deleting_col(x);
real_1d_array y = "[0.223130, 0.382893, 0.582748, 0.786628, 0.941765, 1.000000, 0.941765, 0.786628, 0.582748, 0.382893, 0.223130]";
if( _spoil_scenario==5 )
spoil_vector_by_nan(y);
if( _spoil_scenario==6 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==7 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==8 )
spoil_vector_by_adding_element(y);
if( _spoil_scenario==9 )
spoil_vector_by_deleting_element(y);
real_1d_array c = "[0.3]";
if( _spoil_scenario==10 )
spoil_vector_by_nan(c);
if( _spoil_scenario==11 )
spoil_vector_by_posinf(c);
if( _spoil_scenario==12 )
spoil_vector_by_neginf(c);
real_1d_array bndl = "[0.0]";
if( _spoil_scenario==13 )
spoil_vector_by_nan(bndl);
if( _spoil_scenario==14 )
spoil_vector_by_deleting_element(bndl);
real_1d_array bndu = "[1.0]";
if( _spoil_scenario==15 )
spoil_vector_by_nan(bndu);
if( _spoil_scenario==16 )
spoil_vector_by_deleting_element(bndu);
double epsx = 0.000001;
if( _spoil_scenario==17 )
epsx = fp_nan;
if( _spoil_scenario==18 )
epsx = fp_posinf;
if( _spoil_scenario==19 )
epsx = fp_neginf;
ae_int_t maxits = 0;
ae_int_t info;
lsfitstate state;
lsfitreport rep;
double diffstep = 0.0001;
if( _spoil_scenario==20 )
diffstep = fp_nan;
if( _spoil_scenario==21 )
diffstep = fp_posinf;
if( _spoil_scenario==22 )
diffstep = fp_neginf;
lsfitcreatef(x, y, c, diffstep, state);
lsfitsetbc(state, bndl, bndu);
lsfitsetcond(state, epsx, maxits);
alglib::lsfitfit(state, function_cx_1_func);
lsfitresults(state, info, c, rep);
_TestResult = _TestResult && doc_test_real_vector(c, "[1.0]", 0.05);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "lsfit_d_nlfb");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST lsfit_d_nlscale
// Nonlinear fitting with custom scaling and bound constraints
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<27; _spoil_scenario++)
{
try
{
//
// In this example we demonstrate fitting by
// f(x) = c[0]*(1+c[1]*((x-1999)^c[2]-1))
// subject to bound constraints
// -INF < c[0] < +INF
// -10 <= c[1] <= +10
// 0.1 <= c[2] <= 2.0
// Data we want to fit are time series of Japan national debt
// collected from 2000 to 2008 measured in USD (dollars, not
// millions of dollars).
//
// Our variables are:
// c[0] - debt value at initial moment (2000),
// c[1] - direction coefficient (growth or decrease),
// c[2] - curvature coefficient.
// You may see that our variables are badly scaled - first one
// is order of 10^12, and next two are somewhere about 1 in
// magnitude. Such problem is difficult to solve without some
// kind of scaling.
// That is exactly where lsfitsetscale() function can be used.
// We set scale of our variables to [1.0E12, 1, 1], which allows
// us to easily solve this problem.
//
// You can try commenting out lsfitsetscale() call - and you will
// see that algorithm will fail to converge.
//
real_2d_array x = "[[2000],[2001],[2002],[2003],[2004],[2005],[2006],[2007],[2008]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(x);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(x);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(x);
if( _spoil_scenario==3 )
spoil_matrix_by_deleting_row(x);
if( _spoil_scenario==4 )
spoil_matrix_by_deleting_col(x);
real_1d_array y = "[4323239600000.0, 4560913100000.0, 5564091500000.0, 6743189300000.0, 7284064600000.0, 7050129600000.0, 7092221500000.0, 8483907600000.0, 8625804400000.0]";
if( _spoil_scenario==5 )
spoil_vector_by_nan(y);
if( _spoil_scenario==6 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==7 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==8 )
spoil_vector_by_adding_element(y);
if( _spoil_scenario==9 )
spoil_vector_by_deleting_element(y);
real_1d_array c = "[1.0e+13, 1, 1]";
if( _spoil_scenario==10 )
spoil_vector_by_nan(c);
if( _spoil_scenario==11 )
spoil_vector_by_posinf(c);
if( _spoil_scenario==12 )
spoil_vector_by_neginf(c);
double epsx = 1.0e-5;
if( _spoil_scenario==13 )
epsx = fp_nan;
if( _spoil_scenario==14 )
epsx = fp_posinf;
if( _spoil_scenario==15 )
epsx = fp_neginf;
real_1d_array bndl = "[-inf, -10, 0.1]";
if( _spoil_scenario==16 )
spoil_vector_by_nan(bndl);
if( _spoil_scenario==17 )
spoil_vector_by_deleting_element(bndl);
real_1d_array bndu = "[+inf, +10, 2.0]";
if( _spoil_scenario==18 )
spoil_vector_by_nan(bndu);
if( _spoil_scenario==19 )
spoil_vector_by_deleting_element(bndu);
real_1d_array s = "[1.0e+12, 1, 1]";
if( _spoil_scenario==20 )
spoil_vector_by_nan(s);
if( _spoil_scenario==21 )
spoil_vector_by_posinf(s);
if( _spoil_scenario==22 )
spoil_vector_by_neginf(s);
if( _spoil_scenario==23 )
spoil_vector_by_deleting_element(s);
ae_int_t maxits = 0;
ae_int_t info;
lsfitstate state;
lsfitreport rep;
double diffstep = 1.0e-5;
if( _spoil_scenario==24 )
diffstep = fp_nan;
if( _spoil_scenario==25 )
diffstep = fp_posinf;
if( _spoil_scenario==26 )
diffstep = fp_neginf;
lsfitcreatef(x, y, c, diffstep, state);
lsfitsetcond(state, epsx, maxits);
lsfitsetbc(state, bndl, bndu);
lsfitsetscale(state, s);
alglib::lsfitfit(state, function_debt_func);
lsfitresults(state, info, c, rep);
_TestResult = _TestResult && doc_test_int(info, 2);
_TestResult = _TestResult && doc_test_real_vector(c, "[4.142560e+12, 0.434240, 0.565376]", -0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "lsfit_d_nlscale");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST lsfit_d_lin
// Unconstrained (general) linear least squares fitting with and without weights
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<13; _spoil_scenario++)
{
try
{
//
// In this example we demonstrate linear fitting by f(x|a) = a*exp(0.5*x).
//
// We have:
// * y - vector of experimental data
// * fmatrix - matrix of basis functions calculated at sample points
// Actually, we have only one basis function F0 = exp(0.5*x).
//
real_2d_array fmatrix = "[[0.606531],[0.670320],[0.740818],[0.818731],[0.904837],[1.000000],[1.105171],[1.221403],[1.349859],[1.491825],[1.648721]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(fmatrix);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(fmatrix);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(fmatrix);
real_1d_array y = "[1.133719, 1.306522, 1.504604, 1.554663, 1.884638, 2.072436, 2.257285, 2.534068, 2.622017, 2.897713, 3.219371]";
if( _spoil_scenario==3 )
spoil_vector_by_nan(y);
if( _spoil_scenario==4 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==5 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==6 )
spoil_vector_by_adding_element(y);
if( _spoil_scenario==7 )
spoil_vector_by_deleting_element(y);
ae_int_t info;
real_1d_array c;
lsfitreport rep;
//
// Linear fitting without weights
//
lsfitlinear(y, fmatrix, info, c, rep);
_TestResult = _TestResult && doc_test_int(info, 1);
_TestResult = _TestResult && doc_test_real_vector(c, "[1.98650]", 0.00005);
//
// Linear fitting with individual weights.
// Slightly different result is returned.
//
real_1d_array w = "[1.414213, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]";
if( _spoil_scenario==8 )
spoil_vector_by_nan(w);
if( _spoil_scenario==9 )
spoil_vector_by_posinf(w);
if( _spoil_scenario==10 )
spoil_vector_by_neginf(w);
if( _spoil_scenario==11 )
spoil_vector_by_adding_element(w);
if( _spoil_scenario==12 )
spoil_vector_by_deleting_element(w);
lsfitlinearw(y, w, fmatrix, info, c, rep);
_TestResult = _TestResult && doc_test_int(info, 1);
_TestResult = _TestResult && doc_test_real_vector(c, "[1.983354]", 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "lsfit_d_lin");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST lsfit_d_linc
// Constrained (general) linear least squares fitting with and without weights
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<20; _spoil_scenario++)
{
try
{
//
// In this example we demonstrate linear fitting by f(x|a,b) = a*x+b
// with simple constraint f(0)=0.
//
// We have:
// * y - vector of experimental data
// * fmatrix - matrix of basis functions sampled at [0,1] with step 0.2:
// [ 1.0 0.0 ]
// [ 1.0 0.2 ]
// [ 1.0 0.4 ]
// [ 1.0 0.6 ]
// [ 1.0 0.8 ]
// [ 1.0 1.0 ]
// first column contains value of first basis function (constant term)
// second column contains second basis function (linear term)
// * cmatrix - matrix of linear constraints:
// [ 1.0 0.0 0.0 ]
// first two columns contain coefficients before basis functions,
// last column contains desired value of their sum.
// So [1,0,0] means "1*constant_term + 0*linear_term = 0"
//
real_1d_array y = "[0.072436,0.246944,0.491263,0.522300,0.714064,0.921929]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(y);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==3 )
spoil_vector_by_adding_element(y);
if( _spoil_scenario==4 )
spoil_vector_by_deleting_element(y);
real_2d_array fmatrix = "[[1,0.0],[1,0.2],[1,0.4],[1,0.6],[1,0.8],[1,1.0]]";
if( _spoil_scenario==5 )
spoil_matrix_by_nan(fmatrix);
if( _spoil_scenario==6 )
spoil_matrix_by_posinf(fmatrix);
if( _spoil_scenario==7 )
spoil_matrix_by_neginf(fmatrix);
if( _spoil_scenario==8 )
spoil_matrix_by_adding_row(fmatrix);
if( _spoil_scenario==9 )
spoil_matrix_by_adding_col(fmatrix);
if( _spoil_scenario==10 )
spoil_matrix_by_deleting_row(fmatrix);
if( _spoil_scenario==11 )
spoil_matrix_by_deleting_col(fmatrix);
real_2d_array cmatrix = "[[1,0,0]]";
if( _spoil_scenario==12 )
spoil_matrix_by_nan(cmatrix);
if( _spoil_scenario==13 )
spoil_matrix_by_posinf(cmatrix);
if( _spoil_scenario==14 )
spoil_matrix_by_neginf(cmatrix);
ae_int_t info;
real_1d_array c;
lsfitreport rep;
//
// Constrained fitting without weights
//
lsfitlinearc(y, fmatrix, cmatrix, info, c, rep);
_TestResult = _TestResult && doc_test_int(info, 1);
_TestResult = _TestResult && doc_test_real_vector(c, "[0,0.932933]", 0.0005);
//
// Constrained fitting with individual weights
//
real_1d_array w = "[1, 1.414213, 1, 1, 1, 1]";
if( _spoil_scenario==15 )
spoil_vector_by_nan(w);
if( _spoil_scenario==16 )
spoil_vector_by_posinf(w);
if( _spoil_scenario==17 )
spoil_vector_by_neginf(w);
if( _spoil_scenario==18 )
spoil_vector_by_adding_element(w);
if( _spoil_scenario==19 )
spoil_vector_by_deleting_element(w);
lsfitlinearwc(y, w, fmatrix, cmatrix, info, c, rep);
_TestResult = _TestResult && doc_test_int(info, 1);
_TestResult = _TestResult && doc_test_real_vector(c, "[0,0.938322]", 0.0005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "lsfit_d_linc");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST lsfit_d_pol
// Unconstrained polynomial fitting
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<20; _spoil_scenario++)
{
try
{
//
// This example demonstrates polynomial fitting.
//
// Fitting is done by two (M=2) functions from polynomial basis:
// f0 = 1
// f1 = x
// Basically, it just a linear fit; more complex polynomials may be used
// (e.g. parabolas with M=3, cubic with M=4), but even such simple fit allows
// us to demonstrate polynomialfit() function in action.
//
// We have:
// * x set of abscissas
// * y experimental data
//
// Additionally we demonstrate weighted fitting, where second point has
// more weight than other ones.
//
real_1d_array x = "[0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_adding_element(x);
if( _spoil_scenario==4 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[0.00,0.05,0.26,0.32,0.33,0.43,0.60,0.60,0.77,0.98,1.02]";
if( _spoil_scenario==5 )
spoil_vector_by_nan(y);
if( _spoil_scenario==6 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==7 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==8 )
spoil_vector_by_adding_element(y);
if( _spoil_scenario==9 )
spoil_vector_by_deleting_element(y);
ae_int_t m = 2;
double t = 2;
if( _spoil_scenario==10 )
t = fp_posinf;
if( _spoil_scenario==11 )
t = fp_neginf;
ae_int_t info;
barycentricinterpolant p;
polynomialfitreport rep;
double v;
//
// Fitting without individual weights
//
// NOTE: result is returned as barycentricinterpolant structure.
// if you want to get representation in the power basis,
// you can use barycentricbar2pow() function to convert
// from barycentric to power representation (see docs for
// POLINT subpackage for more info).
//
polynomialfit(x, y, m, info, p, rep);
v = barycentriccalc(p, t);
_TestResult = _TestResult && doc_test_real(v, 2.011, 0.002);
//
// Fitting with individual weights
//
// NOTE: slightly different result is returned
//
real_1d_array w = "[1,1.414213562,1,1,1,1,1,1,1,1,1]";
if( _spoil_scenario==12 )
spoil_vector_by_nan(w);
if( _spoil_scenario==13 )
spoil_vector_by_posinf(w);
if( _spoil_scenario==14 )
spoil_vector_by_neginf(w);
if( _spoil_scenario==15 )
spoil_vector_by_adding_element(w);
if( _spoil_scenario==16 )
spoil_vector_by_deleting_element(w);
real_1d_array xc = "[]";
if( _spoil_scenario==17 )
spoil_vector_by_adding_element(xc);
real_1d_array yc = "[]";
if( _spoil_scenario==18 )
spoil_vector_by_adding_element(yc);
integer_1d_array dc = "[]";
if( _spoil_scenario==19 )
spoil_vector_by_adding_element(dc);
polynomialfitwc(x, y, w, xc, yc, dc, m, info, p, rep);
v = barycentriccalc(p, t);
_TestResult = _TestResult && doc_test_real(v, 2.023, 0.002);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "lsfit_d_pol");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST lsfit_d_polc
// Constrained polynomial fitting
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<29; _spoil_scenario++)
{
try
{
//
// This example demonstrates polynomial fitting.
//
// Fitting is done by two (M=2) functions from polynomial basis:
// f0 = 1
// f1 = x
// with simple constraint on function value
// f(0) = 0
// Basically, it just a linear fit; more complex polynomials may be used
// (e.g. parabolas with M=3, cubic with M=4), but even such simple fit allows
// us to demonstrate polynomialfit() function in action.
//
// We have:
// * x set of abscissas
// * y experimental data
// * xc points where constraints are placed
// * yc constraints on derivatives
// * dc derivative indices
// (0 means function itself, 1 means first derivative)
//
real_1d_array x = "[1.0,1.0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_adding_element(x);
if( _spoil_scenario==4 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[0.9,1.1]";
if( _spoil_scenario==5 )
spoil_vector_by_nan(y);
if( _spoil_scenario==6 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==7 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==8 )
spoil_vector_by_adding_element(y);
if( _spoil_scenario==9 )
spoil_vector_by_deleting_element(y);
real_1d_array w = "[1,1]";
if( _spoil_scenario==10 )
spoil_vector_by_nan(w);
if( _spoil_scenario==11 )
spoil_vector_by_posinf(w);
if( _spoil_scenario==12 )
spoil_vector_by_neginf(w);
if( _spoil_scenario==13 )
spoil_vector_by_adding_element(w);
if( _spoil_scenario==14 )
spoil_vector_by_deleting_element(w);
real_1d_array xc = "[0]";
if( _spoil_scenario==15 )
spoil_vector_by_nan(xc);
if( _spoil_scenario==16 )
spoil_vector_by_posinf(xc);
if( _spoil_scenario==17 )
spoil_vector_by_neginf(xc);
if( _spoil_scenario==18 )
spoil_vector_by_adding_element(xc);
if( _spoil_scenario==19 )
spoil_vector_by_deleting_element(xc);
real_1d_array yc = "[0]";
if( _spoil_scenario==20 )
spoil_vector_by_nan(yc);
if( _spoil_scenario==21 )
spoil_vector_by_posinf(yc);
if( _spoil_scenario==22 )
spoil_vector_by_neginf(yc);
if( _spoil_scenario==23 )
spoil_vector_by_adding_element(yc);
if( _spoil_scenario==24 )
spoil_vector_by_deleting_element(yc);
integer_1d_array dc = "[0]";
if( _spoil_scenario==25 )
spoil_vector_by_adding_element(dc);
if( _spoil_scenario==26 )
spoil_vector_by_deleting_element(dc);
double t = 2;
if( _spoil_scenario==27 )
t = fp_posinf;
if( _spoil_scenario==28 )
t = fp_neginf;
ae_int_t m = 2;
ae_int_t info;
barycentricinterpolant p;
polynomialfitreport rep;
double v;
polynomialfitwc(x, y, w, xc, yc, dc, m, info, p, rep);
v = barycentriccalc(p, t);
_TestResult = _TestResult && doc_test_real(v, 2.000, 0.001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "lsfit_d_polc");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST lsfit_d_spline
// Unconstrained fitting by penalized regression spline
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<19; _spoil_scenario++)
{
try
{
//
// In this example we demonstrate penalized spline fitting of noisy data
//
// We have:
// * x - abscissas
// * y - vector of experimental data, straight line with small noise
//
real_1d_array x = "[0.00,0.10,0.20,0.30,0.40,0.50,0.60,0.70,0.80,0.90]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_adding_element(x);
if( _spoil_scenario==4 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[0.10,0.00,0.30,0.40,0.30,0.40,0.62,0.68,0.75,0.95]";
if( _spoil_scenario==5 )
spoil_vector_by_nan(y);
if( _spoil_scenario==6 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==7 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==8 )
spoil_vector_by_adding_element(y);
if( _spoil_scenario==9 )
spoil_vector_by_deleting_element(y);
ae_int_t info;
double v;
spline1dinterpolant s;
spline1dfitreport rep;
double rho;
//
// Fit with VERY small amount of smoothing (rho = -5.0)
// and large number of basis functions (M=50).
//
// With such small regularization penalized spline almost fully reproduces function values
//
rho = -5.0;
if( _spoil_scenario==10 )
rho = fp_nan;
if( _spoil_scenario==11 )
rho = fp_posinf;
if( _spoil_scenario==12 )
rho = fp_neginf;
spline1dfitpenalized(x, y, 50, rho, info, s, rep);
_TestResult = _TestResult && doc_test_int(info, 1);
v = spline1dcalc(s, 0.0);
_TestResult = _TestResult && doc_test_real(v, 0.10, 0.01);
//
// Fit with VERY large amount of smoothing (rho = 10.0)
// and large number of basis functions (M=50).
//
// With such regularization our spline should become close to the straight line fit.
// We will compare its value in x=1.0 with results obtained from such fit.
//
rho = +10.0;
if( _spoil_scenario==13 )
rho = fp_nan;
if( _spoil_scenario==14 )
rho = fp_posinf;
if( _spoil_scenario==15 )
rho = fp_neginf;
spline1dfitpenalized(x, y, 50, rho, info, s, rep);
_TestResult = _TestResult && doc_test_int(info, 1);
v = spline1dcalc(s, 1.0);
_TestResult = _TestResult && doc_test_real(v, 0.969, 0.001);
//
// In real life applications you may need some moderate degree of fitting,
// so we try to fit once more with rho=3.0.
//
rho = +3.0;
if( _spoil_scenario==16 )
rho = fp_nan;
if( _spoil_scenario==17 )
rho = fp_posinf;
if( _spoil_scenario==18 )
rho = fp_neginf;
spline1dfitpenalized(x, y, 50, rho, info, s, rep);
_TestResult = _TestResult && doc_test_int(info, 1);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "lsfit_d_spline");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST lsfit_t_polfit_1
// Polynomial fitting, full list of parameters.
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<10; _spoil_scenario++)
{
try
{
real_1d_array x = "[0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[0.00,0.05,0.26,0.32,0.33,0.43,0.60,0.60,0.77,0.98,1.02]";
if( _spoil_scenario==4 )
spoil_vector_by_nan(y);
if( _spoil_scenario==5 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==6 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==7 )
spoil_vector_by_deleting_element(y);
ae_int_t m = 2;
double t = 2;
if( _spoil_scenario==8 )
t = fp_posinf;
if( _spoil_scenario==9 )
t = fp_neginf;
ae_int_t info;
barycentricinterpolant p;
polynomialfitreport rep;
double v;
polynomialfit(x, y, 11, m, info, p, rep);
v = barycentriccalc(p, t);
_TestResult = _TestResult && doc_test_real(v, 2.011, 0.002);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "lsfit_t_polfit_1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST lsfit_t_polfit_2
// Polynomial fitting, full list of parameters.
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<14; _spoil_scenario++)
{
try
{
real_1d_array x = "[0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[0.00,0.05,0.26,0.32,0.33,0.43,0.60,0.60,0.77,0.98,1.02]";
if( _spoil_scenario==4 )
spoil_vector_by_nan(y);
if( _spoil_scenario==5 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==6 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==7 )
spoil_vector_by_deleting_element(y);
real_1d_array w = "[1,1.414213562,1,1,1,1,1,1,1,1,1]";
if( _spoil_scenario==8 )
spoil_vector_by_nan(w);
if( _spoil_scenario==9 )
spoil_vector_by_posinf(w);
if( _spoil_scenario==10 )
spoil_vector_by_neginf(w);
if( _spoil_scenario==11 )
spoil_vector_by_deleting_element(w);
real_1d_array xc = "[]";
real_1d_array yc = "[]";
integer_1d_array dc = "[]";
ae_int_t m = 2;
double t = 2;
if( _spoil_scenario==12 )
t = fp_posinf;
if( _spoil_scenario==13 )
t = fp_neginf;
ae_int_t info;
barycentricinterpolant p;
polynomialfitreport rep;
double v;
polynomialfitwc(x, y, w, 11, xc, yc, dc, 0, m, info, p, rep);
v = barycentriccalc(p, t);
_TestResult = _TestResult && doc_test_real(v, 2.023, 0.002);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "lsfit_t_polfit_2");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST lsfit_t_polfit_3
// Polynomial fitting, full list of parameters.
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<23; _spoil_scenario++)
{
try
{
real_1d_array x = "[1.0,1.0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[0.9,1.1]";
if( _spoil_scenario==4 )
spoil_vector_by_nan(y);
if( _spoil_scenario==5 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==6 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==7 )
spoil_vector_by_deleting_element(y);
real_1d_array w = "[1,1]";
if( _spoil_scenario==8 )
spoil_vector_by_nan(w);
if( _spoil_scenario==9 )
spoil_vector_by_posinf(w);
if( _spoil_scenario==10 )
spoil_vector_by_neginf(w);
if( _spoil_scenario==11 )
spoil_vector_by_deleting_element(w);
real_1d_array xc = "[0]";
if( _spoil_scenario==12 )
spoil_vector_by_nan(xc);
if( _spoil_scenario==13 )
spoil_vector_by_posinf(xc);
if( _spoil_scenario==14 )
spoil_vector_by_neginf(xc);
if( _spoil_scenario==15 )
spoil_vector_by_deleting_element(xc);
real_1d_array yc = "[0]";
if( _spoil_scenario==16 )
spoil_vector_by_nan(yc);
if( _spoil_scenario==17 )
spoil_vector_by_posinf(yc);
if( _spoil_scenario==18 )
spoil_vector_by_neginf(yc);
if( _spoil_scenario==19 )
spoil_vector_by_deleting_element(yc);
integer_1d_array dc = "[0]";
if( _spoil_scenario==20 )
spoil_vector_by_deleting_element(dc);
ae_int_t m = 2;
double t = 2;
if( _spoil_scenario==21 )
t = fp_posinf;
if( _spoil_scenario==22 )
t = fp_neginf;
ae_int_t info;
barycentricinterpolant p;
polynomialfitreport rep;
double v;
polynomialfitwc(x, y, w, 2, xc, yc, dc, 1, m, info, p, rep);
v = barycentriccalc(p, t);
_TestResult = _TestResult && doc_test_real(v, 2.000, 0.001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "lsfit_t_polfit_3");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST lsfit_t_4pl
// 4-parameter logistic fitting
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<8; _spoil_scenario++)
{
try
{
real_1d_array x = "[1,2,3,4,5,6,7,8]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[0.06313223,0.44552624,0.61838364,0.71385108,0.77345838,0.81383140,0.84280033,0.86449822]";
if( _spoil_scenario==4 )
spoil_vector_by_nan(y);
if( _spoil_scenario==5 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==6 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==7 )
spoil_vector_by_deleting_element(y);
ae_int_t n = 8;
double a;
double b;
double c;
double d;
lsfitreport rep;
//
// Test logisticfit4() on carefully designed data with a priori known answer.
//
logisticfit4(x, y, n, a, b, c, d, rep);
_TestResult = _TestResult && doc_test_real(a, -1.000, 0.01);
_TestResult = _TestResult && doc_test_real(b, 1.200, 0.01);
_TestResult = _TestResult && doc_test_real(c, 0.900, 0.01);
_TestResult = _TestResult && doc_test_real(d, 1.000, 0.01);
//
// Evaluate model at point x=0.5
//
double v;
v = logisticcalc4(0.5, a, b, c, d);
_TestResult = _TestResult && doc_test_real(v, -0.33874308, 0.001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "lsfit_t_4pl");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST lsfit_t_5pl
// 5-parameter logistic fitting
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<8; _spoil_scenario++)
{
try
{
real_1d_array x = "[1,2,3,4,5,6,7,8]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[0.1949776139,0.5710060208,0.726002637,0.8060434158,0.8534547965,0.8842071579,0.9054773317,0.9209088299]";
if( _spoil_scenario==4 )
spoil_vector_by_nan(y);
if( _spoil_scenario==5 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==6 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==7 )
spoil_vector_by_deleting_element(y);
ae_int_t n = 8;
double a;
double b;
double c;
double d;
double g;
lsfitreport rep;
//
// Test logisticfit5() on carefully designed data with a priori known answer.
//
logisticfit5(x, y, n, a, b, c, d, g, rep);
_TestResult = _TestResult && doc_test_real(a, -1.000, 0.01);
_TestResult = _TestResult && doc_test_real(b, 1.200, 0.01);
_TestResult = _TestResult && doc_test_real(c, 0.900, 0.01);
_TestResult = _TestResult && doc_test_real(d, 1.000, 0.01);
_TestResult = _TestResult && doc_test_real(g, 1.200, 0.01);
//
// Evaluate model at point x=0.5
//
double v;
v = logisticcalc5(0.5, a, b, c, d, g);
_TestResult = _TestResult && doc_test_real(v, -0.2354656824, 0.001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "lsfit_t_5pl");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST spline2d_bilinear
// Bilinear spline interpolation
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<16; _spoil_scenario++)
{
try
{
//
// We use bilinear spline to interpolate f(x,y)=x^2+2*y^2 sampled
// at (x,y) from [0.0, 0.5, 1.0] X [0.0, 1.0].
//
real_1d_array x = "[0.0, 0.5, 1.0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[0.0, 1.0]";
if( _spoil_scenario==4 )
spoil_vector_by_nan(y);
if( _spoil_scenario==5 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==6 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==7 )
spoil_vector_by_deleting_element(y);
real_1d_array f = "[0.00,0.25,1.00,2.00,2.25,3.00]";
if( _spoil_scenario==8 )
spoil_vector_by_nan(f);
if( _spoil_scenario==9 )
spoil_vector_by_posinf(f);
if( _spoil_scenario==10 )
spoil_vector_by_neginf(f);
if( _spoil_scenario==11 )
spoil_vector_by_deleting_element(f);
double vx = 0.25;
if( _spoil_scenario==12 )
vx = fp_posinf;
if( _spoil_scenario==13 )
vx = fp_neginf;
double vy = 0.50;
if( _spoil_scenario==14 )
vy = fp_posinf;
if( _spoil_scenario==15 )
vy = fp_neginf;
double v;
spline2dinterpolant s;
// build spline
spline2dbuildbilinearv(x, 3, y, 2, f, 1, s);
// calculate S(0.25,0.50)
v = spline2dcalc(s, vx, vy);
_TestResult = _TestResult && doc_test_real(v, 1.1250, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "spline2d_bilinear");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST spline2d_bicubic
// Bilinear spline interpolation
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<16; _spoil_scenario++)
{
try
{
//
// We use bilinear spline to interpolate f(x,y)=x^2+2*y^2 sampled
// at (x,y) from [0.0, 0.5, 1.0] X [0.0, 1.0].
//
real_1d_array x = "[0.0, 0.5, 1.0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[0.0, 1.0]";
if( _spoil_scenario==4 )
spoil_vector_by_nan(y);
if( _spoil_scenario==5 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==6 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==7 )
spoil_vector_by_deleting_element(y);
real_1d_array f = "[0.00,0.25,1.00,2.00,2.25,3.00]";
if( _spoil_scenario==8 )
spoil_vector_by_nan(f);
if( _spoil_scenario==9 )
spoil_vector_by_posinf(f);
if( _spoil_scenario==10 )
spoil_vector_by_neginf(f);
if( _spoil_scenario==11 )
spoil_vector_by_deleting_element(f);
double vx = 0.25;
if( _spoil_scenario==12 )
vx = fp_posinf;
if( _spoil_scenario==13 )
vx = fp_neginf;
double vy = 0.50;
if( _spoil_scenario==14 )
vy = fp_posinf;
if( _spoil_scenario==15 )
vy = fp_neginf;
double v;
double dx;
double dy;
double dxy;
spline2dinterpolant s;
// build spline
spline2dbuildbicubicv(x, 3, y, 2, f, 1, s);
// calculate S(0.25,0.50)
v = spline2dcalc(s, vx, vy);
_TestResult = _TestResult && doc_test_real(v, 1.0625, 0.00005);
// calculate derivatives
spline2ddiff(s, vx, vy, v, dx, dy, dxy);
_TestResult = _TestResult && doc_test_real(v, 1.0625, 0.00005);
_TestResult = _TestResult && doc_test_real(dx, 0.5000, 0.00005);
_TestResult = _TestResult && doc_test_real(dy, 2.0000, 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "spline2d_bicubic");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST spline2d_fit_blocklls
// Fitting bicubic spline to irregular data
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<5; _spoil_scenario++)
{
try
{
//
// We use bicubic spline to reproduce f(x,y)=1/(1+x^2+2*y^2) sampled
// at irregular points (x,y) from [-1,+1]*[-1,+1]
//
// We have 5 such points, located approximately at corners of the area
// and its center - but not exactly at the grid. Thus, we have to FIT
// the spline, i.e. to solve least squares problem
//
real_2d_array xy = "[[-0.987,-0.902,0.359],[0.948,-0.992,0.347],[-1.000,1.000,0.333],[1.000,0.973,0.339],[0.017,0.180,0.968]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
if( _spoil_scenario==3 )
spoil_matrix_by_deleting_row(xy);
if( _spoil_scenario==4 )
spoil_matrix_by_deleting_col(xy);
//
// First step is to create spline2dbuilder object and set its properties:
// * d=1 means that we create vector-valued spline with 1 component
// * we specify dataset xy
// * we rely on automatic selection of interpolation area
// * we tell builder that we want to use 5x5 grid for an underlying spline
// * we choose least squares solver named BlockLLS and configure it by
// telling that we want to apply zero nonlinearity penalty.
//
// NOTE: you can specify non-zero lambdav if you want to make your spline
// more "rigid", i.e. to penalize nonlinearity.
//
// NOTE: ALGLIB has two solvers which fit bicubic splines to irregular data,
// one of them is BlockLLS and another one is FastDDM. Former is
// intended for moderately sized grids (up to 512x512 nodes, although
// it may take up to few minutes); it is the most easy to use and
// control spline fitting function in the library. Latter, FastDDM,
// is intended for efficient solution of large-scale problems
// (up to 100.000.000 nodes). Both solvers can be parallelized, but
// FastDDM is much more efficient. See comments for more information.
//
spline2dbuilder builder;
ae_int_t d = 1;
double lambdav = 0.000;
spline2dbuildercreate(d, builder);
spline2dbuildersetpoints(builder, xy, 5);
spline2dbuildersetgrid(builder, 5, 5);
spline2dbuildersetalgoblocklls(builder, lambdav);
//
// Now we are ready to fit and evaluate our results
//
spline2dinterpolant s;
spline2dfitreport rep;
spline2dfit(builder, s, rep);
// evaluate results - function value at the grid is reproduced exactly
double v;
v = spline2dcalc(s, -1, 1);
_TestResult = _TestResult && doc_test_real(v, 0.333000, 0.005);
// check maximum error - it must be nearly zero
_TestResult = _TestResult && doc_test_real(rep.maxerror, 0.000, 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "spline2d_fit_blocklls");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST spline2d_unpack
// Unpacking bilinear spline
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<12; _spoil_scenario++)
{
try
{
//
// We build bilinear spline for f(x,y)=x+2*y+3*xy for (x,y) in [0,1].
// Then we demonstrate how to unpack it.
//
real_1d_array x = "[0.0, 1.0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[0.0, 1.0]";
if( _spoil_scenario==4 )
spoil_vector_by_nan(y);
if( _spoil_scenario==5 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==6 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==7 )
spoil_vector_by_deleting_element(y);
real_1d_array f = "[0.00,1.00,2.00,6.00]";
if( _spoil_scenario==8 )
spoil_vector_by_nan(f);
if( _spoil_scenario==9 )
spoil_vector_by_posinf(f);
if( _spoil_scenario==10 )
spoil_vector_by_neginf(f);
if( _spoil_scenario==11 )
spoil_vector_by_deleting_element(f);
real_2d_array c;
ae_int_t m;
ae_int_t n;
ae_int_t d;
spline2dinterpolant s;
// build spline
spline2dbuildbilinearv(x, 2, y, 2, f, 1, s);
// unpack and test
spline2dunpackv(s, m, n, d, c);
_TestResult = _TestResult && doc_test_real_matrix(c, "[[0, 1, 0, 1, 0,2,0,0, 1,3,0,0, 0,0,0,0, 0,0,0,0 ]]", 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "spline2d_unpack");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST spline2d_copytrans
// Copy and transform
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<16; _spoil_scenario++)
{
try
{
//
// We build bilinear spline for f(x,y)=x+2*y for (x,y) in [0,1].
// Then we apply several transformations to this spline.
//
real_1d_array x = "[0.0, 1.0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[0.0, 1.0]";
if( _spoil_scenario==4 )
spoil_vector_by_nan(y);
if( _spoil_scenario==5 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==6 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==7 )
spoil_vector_by_deleting_element(y);
real_1d_array f = "[0.00,1.00,2.00,3.00]";
if( _spoil_scenario==8 )
spoil_vector_by_nan(f);
if( _spoil_scenario==9 )
spoil_vector_by_posinf(f);
if( _spoil_scenario==10 )
spoil_vector_by_neginf(f);
if( _spoil_scenario==11 )
spoil_vector_by_deleting_element(f);
spline2dinterpolant s;
spline2dinterpolant snew;
double v;
spline2dbuildbilinearv(x, 2, y, 2, f, 1, s);
// copy spline, apply transformation x:=2*xnew, y:=4*ynew
// evaluate at (xnew,ynew) = (0.25,0.25) - should be same as (x,y)=(0.5,1.0)
spline2dcopy(s, snew);
spline2dlintransxy(snew, 2.0, 0.0, 4.0, 0.0);
v = spline2dcalc(snew, 0.25, 0.25);
_TestResult = _TestResult && doc_test_real(v, 2.500, 0.00005);
// copy spline, apply transformation SNew:=2*S+3
spline2dcopy(s, snew);
spline2dlintransf(snew, 2.0, 3.0);
v = spline2dcalc(snew, 0.5, 1.0);
_TestResult = _TestResult && doc_test_real(v, 8.000, 0.00005);
//
// Same example, but for vector spline (f0,f1) = {x+2*y, 2*x+y}
//
real_1d_array f2 = "[0.00,0.00, 1.00,2.00, 2.00,1.00, 3.00,3.00]";
if( _spoil_scenario==12 )
spoil_vector_by_nan(f2);
if( _spoil_scenario==13 )
spoil_vector_by_posinf(f2);
if( _spoil_scenario==14 )
spoil_vector_by_neginf(f2);
if( _spoil_scenario==15 )
spoil_vector_by_deleting_element(f2);
real_1d_array vr;
spline2dbuildbilinearv(x, 2, y, 2, f2, 2, s);
// copy spline, apply transformation x:=2*xnew, y:=4*ynew
spline2dcopy(s, snew);
spline2dlintransxy(snew, 2.0, 0.0, 4.0, 0.0);
spline2dcalcv(snew, 0.25, 0.25, vr);
_TestResult = _TestResult && doc_test_real_vector(vr, "[2.500,2.000]", 0.00005);
// copy spline, apply transformation SNew:=2*S+3
spline2dcopy(s, snew);
spline2dlintransf(snew, 2.0, 3.0);
spline2dcalcv(snew, 0.5, 1.0, vr);
_TestResult = _TestResult && doc_test_real_vector(vr, "[8.000,7.000]", 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "spline2d_copytrans");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST spline2d_vector
// Copy and transform
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<12; _spoil_scenario++)
{
try
{
//
// We build bilinear vector-valued spline (f0,f1) = {x+2*y, 2*x+y}
// Spline is built using function values at 2x2 grid: (x,y)=[0,1]*[0,1]
// Then we perform evaluation at (x,y)=(0.1,0.3)
//
real_1d_array x = "[0.0, 1.0]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(x);
real_1d_array y = "[0.0, 1.0]";
if( _spoil_scenario==4 )
spoil_vector_by_nan(y);
if( _spoil_scenario==5 )
spoil_vector_by_posinf(y);
if( _spoil_scenario==6 )
spoil_vector_by_neginf(y);
if( _spoil_scenario==7 )
spoil_vector_by_deleting_element(y);
real_1d_array f = "[0.00,0.00, 1.00,2.00, 2.00,1.00, 3.00,3.00]";
if( _spoil_scenario==8 )
spoil_vector_by_nan(f);
if( _spoil_scenario==9 )
spoil_vector_by_posinf(f);
if( _spoil_scenario==10 )
spoil_vector_by_neginf(f);
if( _spoil_scenario==11 )
spoil_vector_by_deleting_element(f);
spline2dinterpolant s;
real_1d_array vr;
spline2dbuildbilinearv(x, 2, y, 2, f, 2, s);
spline2dcalcv(s, 0.1, 0.3, vr);
_TestResult = _TestResult && doc_test_real_vector(vr, "[0.700,0.500]", 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "spline2d_vector");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST rbf_d_hrbf
// Simple model built with HRBF algorithm
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// This example illustrates basic concepts of the RBF models: creation, modification,
// evaluation.
//
// Suppose that we have set of 2-dimensional points with associated
// scalar function values, and we want to build a RBF model using
// our data.
//
// NOTE: we can work with 3D models too :)
//
// Typical sequence of steps is given below:
// 1. we create RBF model object
// 2. we attach our dataset to the RBF model and tune algorithm settings
// 3. we rebuild RBF model using QNN algorithm on new data
// 4. we use RBF model (evaluate, serialize, etc.)
//
double v;
//
// Step 1: RBF model creation.
//
// We have to specify dimensionality of the space (2 or 3) and
// dimensionality of the function (scalar or vector).
//
// New model is empty - it can be evaluated,
// but we just get zero value at any point.
//
rbfmodel model;
rbfcreate(2, 1, model);
v = rbfcalc2(model, 0.0, 0.0);
_TestResult = _TestResult && doc_test_real(v, 0.000, 0.005);
//
// Step 2: we add dataset.
//
// XY contains two points - x0=(-1,0) and x1=(+1,0) -
// and two function values f(x0)=2, f(x1)=3.
//
// We added points, but model was not rebuild yet.
// If we call rbfcalc2(), we still will get 0.0 as result.
//
real_2d_array xy = "[[-1,0,2],[+1,0,3]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
rbfsetpoints(model, xy);
v = rbfcalc2(model, 0.0, 0.0);
_TestResult = _TestResult && doc_test_real(v, 0.000, 0.005);
//
// Step 3: rebuild model
//
// After we've configured model, we should rebuild it -
// it will change coefficients stored internally in the
// rbfmodel structure.
//
// We use hierarchical RBF algorithm with following parameters:
// * RBase - set to 1.0
// * NLayers - three layers are used (although such simple problem
// does not need more than 1 layer)
// * LambdaReg - is set to zero value, no smoothing is required
//
rbfreport rep;
rbfsetalgohierarchical(model, 1.0, 3, 0.0);
rbfbuildmodel(model, rep);
_TestResult = _TestResult && doc_test_int(rep.terminationtype, 1);
//
// Step 4: model was built
//
// After call of rbfbuildmodel(), rbfcalc2() will return
// value of the new model.
//
v = rbfcalc2(model, 0.0, 0.0);
_TestResult = _TestResult && doc_test_real(v, 2.500, 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "rbf_d_hrbf");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST rbf_d_vector
// Working with vector functions
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<6; _spoil_scenario++)
{
try
{
//
// Suppose that we have set of 2-dimensional points with associated VECTOR
// function values, and we want to build a RBF model using our data.
//
// Typical sequence of steps is given below:
// 1. we create RBF model object
// 2. we attach our dataset to the RBF model and tune algorithm settings
// 3. we rebuild RBF model using new data
// 4. we use RBF model (evaluate, serialize, etc.)
//
real_1d_array x;
real_1d_array y;
//
// Step 1: RBF model creation.
//
// We have to specify dimensionality of the space (equal to 2) and
// dimensionality of the function (2-dimensional vector function).
//
// New model is empty - it can be evaluated,
// but we just get zero value at any point.
//
rbfmodel model;
rbfcreate(2, 2, model);
x = "[+1,+1]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(x);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(x);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(x);
rbfcalc(model, x, y);
_TestResult = _TestResult && doc_test_real_vector(y, "[0.000,0.000]", 0.005);
//
// Step 2: we add dataset.
//
// XY arrays containt four points:
// * (x0,y0) = (+1,+1), f(x0,y0)=(0,-1)
// * (x1,y1) = (+1,-1), f(x1,y1)=(-1,0)
// * (x2,y2) = (-1,-1), f(x2,y2)=(0,+1)
// * (x3,y3) = (-1,+1), f(x3,y3)=(+1,0)
//
real_2d_array xy = "[[+1,+1,0,-1],[+1,-1,-1,0],[-1,-1,0,+1],[-1,+1,+1,0]]";
if( _spoil_scenario==3 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==4 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==5 )
spoil_matrix_by_neginf(xy);
rbfsetpoints(model, xy);
// We added points, but model was not rebuild yet.
// If we call rbfcalc(), we still will get 0.0 as result.
rbfcalc(model, x, y);
_TestResult = _TestResult && doc_test_real_vector(y, "[0.000,0.000]", 0.005);
//
// Step 3: rebuild model
//
// We use hierarchical RBF algorithm with following parameters:
// * RBase - set to 1.0
// * NLayers - three layers are used (although such simple problem
// does not need more than 1 layer)
// * LambdaReg - is set to zero value, no smoothing is required
//
// After we've configured model, we should rebuild it -
// it will change coefficients stored internally in the
// rbfmodel structure.
//
rbfreport rep;
rbfsetalgohierarchical(model, 1.0, 3, 0.0);
rbfbuildmodel(model, rep);
_TestResult = _TestResult && doc_test_int(rep.terminationtype, 1);
//
// Step 4: model was built
//
// After call of rbfbuildmodel(), rbfcalc() will return
// value of the new model.
//
rbfcalc(model, x, y);
_TestResult = _TestResult && doc_test_real_vector(y, "[0.000,-1.000]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "rbf_d_vector");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST rbf_d_polterm
// RBF models - working with polynomial term
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// This example show how to work with polynomial term
//
// Suppose that we have set of 2-dimensional points with associated
// scalar function values, and we want to build a RBF model using
// our data.
//
// We use hierarchical RBF algorithm with following parameters:
// * RBase - set to 1.0
// * NLayers - three layers are used (although such simple problem
// does not need more than 1 layer)
// * LambdaReg - is set to zero value, no smoothing is required
//
double v;
rbfmodel model;
real_2d_array xy = "[[-1,0,2],[+1,0,3]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
rbfreport rep;
rbfcreate(2, 1, model);
rbfsetpoints(model, xy);
rbfsetalgohierarchical(model, 1.0, 3, 0.0);
//
// By default, RBF model uses linear term. It means that model
// looks like
// f(x,y) = SUM(RBF[i]) + a*x + b*y + c
// where RBF[i] is I-th radial basis function and a*x+by+c is a
// linear term. Having linear terms in a model gives us:
// (1) improved extrapolation properties
// (2) linearity of the model when data can be perfectly fitted
// by the linear function
// (3) linear asymptotic behavior
//
// Our simple dataset can be modelled by the linear function
// f(x,y) = 0.5*x + 2.5
// and rbfbuildmodel() with default settings should preserve this
// linearity.
//
ae_int_t nx;
ae_int_t ny;
ae_int_t nc;
ae_int_t modelversion;
real_2d_array xwr;
real_2d_array c;
rbfbuildmodel(model, rep);
_TestResult = _TestResult && doc_test_int(rep.terminationtype, 1);
rbfunpack(model, nx, ny, xwr, nc, c, modelversion);
_TestResult = _TestResult && doc_test_real_matrix(c, "[[0.500,0.000,2.500]]", 0.005);
// asymptotic behavior of our function is linear
v = rbfcalc2(model, 1000.0, 0.0);
_TestResult = _TestResult && doc_test_real(v, 502.50, 0.05);
//
// Instead of linear term we can use constant term. In this case
// we will get model which has form
// f(x,y) = SUM(RBF[i]) + c
// where RBF[i] is I-th radial basis function and c is a constant,
// which is equal to the average function value on the dataset.
//
// Because we've already attached dataset to the model the only
// thing we have to do is to call rbfsetconstterm() and then
// rebuild model with rbfbuildmodel().
//
rbfsetconstterm(model);
rbfbuildmodel(model, rep);
_TestResult = _TestResult && doc_test_int(rep.terminationtype, 1);
rbfunpack(model, nx, ny, xwr, nc, c, modelversion);
_TestResult = _TestResult && doc_test_real_matrix(c, "[[0.000,0.000,2.500]]", 0.005);
// asymptotic behavior of our function is constant
v = rbfcalc2(model, 1000.0, 0.0);
_TestResult = _TestResult && doc_test_real(v, 2.500, 0.005);
//
// Finally, we can use zero term. Just plain RBF without polynomial
// part:
// f(x,y) = SUM(RBF[i])
// where RBF[i] is I-th radial basis function.
//
rbfsetzeroterm(model);
rbfbuildmodel(model, rep);
_TestResult = _TestResult && doc_test_int(rep.terminationtype, 1);
rbfunpack(model, nx, ny, xwr, nc, c, modelversion);
_TestResult = _TestResult && doc_test_real_matrix(c, "[[0.000,0.000,0.000]]", 0.005);
// asymptotic behavior of our function is just zero constant
v = rbfcalc2(model, 1000.0, 0.0);
_TestResult = _TestResult && doc_test_real(v, 0.000, 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "rbf_d_polterm");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST rbf_d_serialize
// Serialization/unserialization
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<3; _spoil_scenario++)
{
try
{
//
// This example show how to serialize and unserialize RBF model
//
// Suppose that we have set of 2-dimensional points with associated
// scalar function values, and we want to build a RBF model using
// our data. Then we want to serialize it to string and to unserialize
// from string, loading to another instance of RBF model.
//
// Here we assume that you already know how to create RBF models.
//
std::string s;
double v;
rbfmodel model0;
rbfmodel model1;
real_2d_array xy = "[[-1,0,2],[+1,0,3]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(xy);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(xy);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(xy);
rbfreport rep;
// model initialization
rbfcreate(2, 1, model0);
rbfsetpoints(model0, xy);
rbfsetalgohierarchical(model0, 1.0, 3, 0.0);
rbfbuildmodel(model0, rep);
_TestResult = _TestResult && doc_test_int(rep.terminationtype, 1);
//
// Serialization - it looks easy,
// but you should carefully read next section.
//
alglib::rbfserialize(model0, s);
alglib::rbfunserialize(s, model1);
// both models return same value
v = rbfcalc2(model0, 0.0, 0.0);
_TestResult = _TestResult && doc_test_real(v, 2.500, 0.005);
v = rbfcalc2(model1, 0.0, 0.0);
_TestResult = _TestResult && doc_test_real(v, 2.500, 0.005);
//
// Previous section shows that model state is saved/restored during
// serialization. However, some properties are NOT serialized.
//
// Serialization saves/restores RBF model, but it does NOT saves/restores
// settings which were used to build current model. In particular, dataset
// which was used to build model, is not preserved.
//
// What does it mean in for us?
//
// Do you remember this sequence: rbfcreate-rbfsetpoints-rbfbuildmodel?
// First step creates model, second step adds dataset and tunes model
// settings, third step builds model using current dataset and model
// construction settings.
//
// If you call rbfbuildmodel() without calling rbfsetpoints() first, you
// will get empty (zero) RBF model. In our example, model0 contains
// dataset which was added by rbfsetpoints() call. However, model1 does
// NOT contain dataset - because dataset is NOT serialized.
//
// This, if we call rbfbuildmodel(model0,rep), we will get same model,
// which returns 2.5 at (x,y)=(0,0). However, after same call model1 will
// return zero - because it contains RBF model (coefficients), but does NOT
// contain dataset which was used to build this model.
//
// Basically, it means that:
// * serialization of the RBF model preserves anything related to the model
// EVALUATION
// * but it does NOT creates perfect copy of the original object.
//
rbfbuildmodel(model0, rep);
v = rbfcalc2(model0, 0.0, 0.0);
_TestResult = _TestResult && doc_test_real(v, 2.500, 0.005);
rbfbuildmodel(model1, rep);
v = rbfcalc2(model1, 0.0, 0.0);
_TestResult = _TestResult && doc_test_real(v, 0.000, 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "rbf_d_serialize");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST matdet_d_1
// Determinant calculation, real matrix, short form
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<7; _spoil_scenario++)
{
try
{
real_2d_array b = "[[1,2],[2,1]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(b);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(b);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(b);
if( _spoil_scenario==3 )
spoil_matrix_by_adding_row(b);
if( _spoil_scenario==4 )
spoil_matrix_by_adding_col(b);
if( _spoil_scenario==5 )
spoil_matrix_by_deleting_row(b);
if( _spoil_scenario==6 )
spoil_matrix_by_deleting_col(b);
double a;
a = rmatrixdet(b);
_TestResult = _TestResult && doc_test_real(a, -3, 0.0001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "matdet_d_1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST matdet_d_2
// Determinant calculation, real matrix, full form
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<5; _spoil_scenario++)
{
try
{
real_2d_array b = "[[5,4],[4,5]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(b);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(b);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(b);
if( _spoil_scenario==3 )
spoil_matrix_by_deleting_row(b);
if( _spoil_scenario==4 )
spoil_matrix_by_deleting_col(b);
double a;
a = rmatrixdet(b, 2);
_TestResult = _TestResult && doc_test_real(a, 9, 0.0001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "matdet_d_2");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST matdet_d_3
// Determinant calculation, complex matrix, short form
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<7; _spoil_scenario++)
{
try
{
complex_2d_array b = "[[1+1i,2],[2,1-1i]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(b);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(b);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(b);
if( _spoil_scenario==3 )
spoil_matrix_by_adding_row(b);
if( _spoil_scenario==4 )
spoil_matrix_by_adding_col(b);
if( _spoil_scenario==5 )
spoil_matrix_by_deleting_row(b);
if( _spoil_scenario==6 )
spoil_matrix_by_deleting_col(b);
alglib::complex a;
a = cmatrixdet(b);
_TestResult = _TestResult && doc_test_complex(a, -2, 0.0001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "matdet_d_3");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST matdet_d_4
// Determinant calculation, complex matrix, full form
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<5; _spoil_scenario++)
{
try
{
alglib::complex a;
complex_2d_array b = "[[5i,4],[4i,5]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(b);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(b);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(b);
if( _spoil_scenario==3 )
spoil_matrix_by_deleting_row(b);
if( _spoil_scenario==4 )
spoil_matrix_by_deleting_col(b);
a = cmatrixdet(b, 2);
_TestResult = _TestResult && doc_test_complex(a, alglib::complex(0,9), 0.0001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "matdet_d_4");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST matdet_d_5
// Determinant calculation, complex matrix with zero imaginary part, short form
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<7; _spoil_scenario++)
{
try
{
alglib::complex a;
complex_2d_array b = "[[9,1],[2,1]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(b);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(b);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(b);
if( _spoil_scenario==3 )
spoil_matrix_by_adding_row(b);
if( _spoil_scenario==4 )
spoil_matrix_by_adding_col(b);
if( _spoil_scenario==5 )
spoil_matrix_by_deleting_row(b);
if( _spoil_scenario==6 )
spoil_matrix_by_deleting_col(b);
a = cmatrixdet(b);
_TestResult = _TestResult && doc_test_complex(a, 7, 0.0001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "matdet_d_5");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST matdet_t_0
// Determinant calculation, real matrix, full form
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<5; _spoil_scenario++)
{
try
{
double a;
real_2d_array b = "[[3,4],[-4,3]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(b);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(b);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(b);
if( _spoil_scenario==3 )
spoil_matrix_by_deleting_row(b);
if( _spoil_scenario==4 )
spoil_matrix_by_deleting_col(b);
a = rmatrixdet(b, 2);
_TestResult = _TestResult && doc_test_real(a, 25, 0.0001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "matdet_t_0");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST matdet_t_1
// Determinant calculation, real matrix, LU, short form
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<9; _spoil_scenario++)
{
try
{
double a;
real_2d_array b = "[[1,2],[2,5]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(b);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(b);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(b);
if( _spoil_scenario==3 )
spoil_matrix_by_adding_row(b);
if( _spoil_scenario==4 )
spoil_matrix_by_adding_col(b);
if( _spoil_scenario==5 )
spoil_matrix_by_deleting_row(b);
if( _spoil_scenario==6 )
spoil_matrix_by_deleting_col(b);
integer_1d_array p = "[1,1]";
if( _spoil_scenario==7 )
spoil_vector_by_adding_element(p);
if( _spoil_scenario==8 )
spoil_vector_by_deleting_element(p);
a = rmatrixludet(b, p);
_TestResult = _TestResult && doc_test_real(a, -5, 0.0001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "matdet_t_1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST matdet_t_2
// Determinant calculation, real matrix, LU, full form
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<6; _spoil_scenario++)
{
try
{
double a;
real_2d_array b = "[[5,4],[4,5]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(b);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(b);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(b);
if( _spoil_scenario==3 )
spoil_matrix_by_deleting_row(b);
if( _spoil_scenario==4 )
spoil_matrix_by_deleting_col(b);
integer_1d_array p = "[0,1]";
if( _spoil_scenario==5 )
spoil_vector_by_deleting_element(p);
a = rmatrixludet(b, p, 2);
_TestResult = _TestResult && doc_test_real(a, 25, 0.0001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "matdet_t_2");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST matdet_t_3
// Determinant calculation, complex matrix, full form
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<5; _spoil_scenario++)
{
try
{
alglib::complex a;
complex_2d_array b = "[[5i,4],[-4,5i]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(b);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(b);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(b);
if( _spoil_scenario==3 )
spoil_matrix_by_deleting_row(b);
if( _spoil_scenario==4 )
spoil_matrix_by_deleting_col(b);
a = cmatrixdet(b, 2);
_TestResult = _TestResult && doc_test_complex(a, -9, 0.0001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "matdet_t_3");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST matdet_t_4
// Determinant calculation, complex matrix, LU, short form
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<9; _spoil_scenario++)
{
try
{
alglib::complex a;
complex_2d_array b = "[[1,2],[2,5i]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(b);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(b);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(b);
if( _spoil_scenario==3 )
spoil_matrix_by_adding_row(b);
if( _spoil_scenario==4 )
spoil_matrix_by_adding_col(b);
if( _spoil_scenario==5 )
spoil_matrix_by_deleting_row(b);
if( _spoil_scenario==6 )
spoil_matrix_by_deleting_col(b);
integer_1d_array p = "[1,1]";
if( _spoil_scenario==7 )
spoil_vector_by_adding_element(p);
if( _spoil_scenario==8 )
spoil_vector_by_deleting_element(p);
a = cmatrixludet(b, p);
_TestResult = _TestResult && doc_test_complex(a, alglib::complex(0,-5), 0.0001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "matdet_t_4");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST matdet_t_5
// Determinant calculation, complex matrix, LU, full form
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<6; _spoil_scenario++)
{
try
{
alglib::complex a;
complex_2d_array b = "[[5,4i],[4,5]]";
if( _spoil_scenario==0 )
spoil_matrix_by_nan(b);
if( _spoil_scenario==1 )
spoil_matrix_by_posinf(b);
if( _spoil_scenario==2 )
spoil_matrix_by_neginf(b);
if( _spoil_scenario==3 )
spoil_matrix_by_deleting_row(b);
if( _spoil_scenario==4 )
spoil_matrix_by_deleting_col(b);
integer_1d_array p = "[0,1]";
if( _spoil_scenario==5 )
spoil_vector_by_deleting_element(p);
a = cmatrixludet(b, p, 2);
_TestResult = _TestResult && doc_test_complex(a, 25, 0.0001);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "matdet_t_5");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST solvesks_d_1
// Solving positive definite sparse system using Skyline (SKS) solver
//
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<4; _spoil_scenario++)
{
try
{
//
// This example demonstrates creation/initialization of the sparse matrix
// in the SKS (Skyline) storage format and solution using SKS-based direct
// solver.
//
// First, we have to create matrix and initialize it. Matrix is created
// in the SKS format, using fixed bandwidth initialization function.
// Several points should be noted:
//
// 1. SKS sparse storage format also allows variable bandwidth matrices;
// we just do not want to overcomplicate this example.
//
// 2. SKS format requires you to specify matrix geometry prior to
// initialization of its elements with sparseset(). If you specified
// bandwidth=1, you can not change your mind afterwards and call
// sparseset() for non-existent elements.
//
// 3. Because SKS solver need just one triangle of SPD matrix, we can
// omit initialization of the lower triangle of our matrix.
//
ae_int_t n = 4;
ae_int_t bandwidth = 1;
sparsematrix s;
sparsecreatesksband(n, n, bandwidth, s);
sparseset(s, 0, 0, 2.0);
sparseset(s, 0, 1, 1.0);
sparseset(s, 1, 1, 3.0);
sparseset(s, 1, 2, 1.0);
sparseset(s, 2, 2, 3.0);
sparseset(s, 2, 3, 1.0);
sparseset(s, 3, 3, 2.0);
//
// Now we have symmetric positive definite 4x4 system width bandwidth=1:
//
// [ 2 1 ] [ x0]] [ 4 ]
// [ 1 3 1 ] [ x1 ] [ 10 ]
// [ 1 3 1 ] * [ x2 ] = [ 15 ]
// [ 1 2 ] [ x3 ] [ 11 ]
//
// After successful creation we can call SKS solver.
//
real_1d_array b = "[4,10,15,11]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(b);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(b);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(b);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(b);
sparsesolverreport rep;
real_1d_array x;
bool isuppertriangle = true;
sparsesolvesks(s, n, isuppertriangle, b, rep, x);
_TestResult = _TestResult && doc_test_real_vector(x, "[1.0000, 2.0000, 3.0000, 4.0000]", 0.00005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "solvesks_d_1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
//
// TEST lincg_d_1
// Solution of sparse linear systems with CG
//
printf("150/151\n");
_TestResult = true;
for(_spoil_scenario=-1; _spoil_scenario<4; _spoil_scenario++)
{
try
{
//
// This example illustrates solution of sparse linear systems with
// conjugate gradient method.
//
// Suppose that we have linear system A*x=b with sparse symmetric
// positive definite A (represented by sparsematrix object)
// [ 5 1 ]
// [ 1 7 2 ]
// A = [ 2 8 1 ]
// [ 1 4 1 ]
// [ 1 4 ]
// and right part b
// [ 7 ]
// [ 17 ]
// b = [ 14 ]
// [ 10 ]
// [ 6 ]
// and we want to solve this system using sparse linear CG. In order
// to do so, we have to create left part (sparsematrix object) and
// right part (dense array).
//
// Initially, sparse matrix is created in the Hash-Table format,
// which allows easy initialization, but do not allow matrix to be
// used in the linear solvers. So after construction you should convert
// sparse matrix to CRS format (one suited for linear operations).
//
// It is important to note that in our example we initialize full
// matrix A, both lower and upper triangles. However, it is symmetric
// and sparse solver needs just one half of the matrix. So you may
// save about half of the space by filling only one of the triangles.
//
sparsematrix a;
sparsecreate(5, 5, a);
sparseset(a, 0, 0, 5.0);
sparseset(a, 0, 1, 1.0);
sparseset(a, 1, 0, 1.0);
sparseset(a, 1, 1, 7.0);
sparseset(a, 1, 2, 2.0);
sparseset(a, 2, 1, 2.0);
sparseset(a, 2, 2, 8.0);
sparseset(a, 2, 3, 1.0);
sparseset(a, 3, 2, 1.0);
sparseset(a, 3, 3, 4.0);
sparseset(a, 3, 4, 1.0);
sparseset(a, 4, 3, 1.0);
sparseset(a, 4, 4, 4.0);
//
// Now our matrix is fully initialized, but we have to do one more
// step - convert it from Hash-Table format to CRS format (see
// documentation on sparse matrices for more information about these
// formats).
//
// If you omit this call, ALGLIB will generate exception on the first
// attempt to use A in linear operations.
//
sparseconverttocrs(a);
//
// Initialization of the right part
//
real_1d_array b = "[7,17,14,10,6]";
if( _spoil_scenario==0 )
spoil_vector_by_nan(b);
if( _spoil_scenario==1 )
spoil_vector_by_posinf(b);
if( _spoil_scenario==2 )
spoil_vector_by_neginf(b);
if( _spoil_scenario==3 )
spoil_vector_by_deleting_element(b);
//
// Now we have to create linear solver object and to use it for the
// solution of the linear system.
//
// NOTE: lincgsolvesparse() accepts additional parameter which tells
// what triangle of the symmetric matrix should be used - upper
// or lower. Because we've filled both parts of the matrix, we
// can use any part - upper or lower.
//
lincgstate s;
lincgreport rep;
real_1d_array x;
lincgcreate(5, s);
lincgsolvesparse(s, a, true, b);
lincgresults(s, x, rep);
_TestResult = _TestResult && doc_test_int(rep.terminationtype, 1);
_TestResult = _TestResult && doc_test_real_vector(x, "[1.000,2.000,1.000,2.000,1.000]", 0.005);
_TestResult = _TestResult && (_spoil_scenario==-1);
}
catch(ap_error)
{ _TestResult = _TestResult && (_spoil_scenario!=-1); }
}
if( !_TestResult)
{
printf("%-32s FAILED\n", "lincg_d_1");
fflush(stdout);
}
_TotalResult = _TotalResult && _TestResult;
printf("151/151\n");
}
catch(...)
{
printf("Unhandled exception was raised!\n");
return 1;
}
#ifdef AE_USE_ALLOC_COUNTER
printf("Allocation counter checked... ");
#ifdef _ALGLIB_HAS_WORKSTEALING
alglib_impl::ae_free_disposed_items();
#endif
if( alglib_impl::_alloc_counter!=0 )
{
printf("FAILURE: alloc_counter is non-zero on end!\n");
return 1;
}
else
printf("OK\n");
#endif
return _TotalResult ? 0 : 1;
}
cpp/tests/test_xne.cpp 0000755 0001750 0001750 00000024507 13576650314 014742 0 ustar sergey sergey #include "stdafx.h"
#include
#include
#include "alglibmisc.h"
#include "alglibinternal.h"
#include "linalg.h"
#include "statistics.h"
#include "dataanalysis.h"
#include "specialfunctions.h"
#include "solvers.h"
#include "optimization.h"
#include "diffequations.h"
#include "fasttransforms.h"
#include "integration.h"
#include "interpolation.h"
#if !defined(AE_NO_EXCEPTIONS)
#error "This test should be compiled with AE_NO_EXCEPTIONS defined"
#endif
using namespace alglib;
const char *fmt_str = "%-29s %s\n";
int main()
{
printf("Test exception-free error handling:\n");
#ifdef AE_USE_ALLOC_COUNTER
printf("Allocation counter activated...\n");
alglib_impl::_use_alloc_counter = ae_true;
if( alglib_impl::_alloc_counter!=0 )
{
printf("FAILURE: alloc_counter is non-zero on start!\n");
return 1;
}
{
{
alglib::real_1d_array x;
x.setlength(1);
if( alglib_impl::_alloc_counter==0 )
printf(":::: WARNING: ALLOC_COUNTER IS INACTIVE!!! :::::\\n");
}
if( alglib_impl::_alloc_counter!=0 )
{
printf("FAILURE: alloc_counter does not decrease!\n");
return 1;
}
}
#endif
//
// Test default state of the error flag
//
{
bool passed = true;
passed = passed && !alglib::get_error_flag();
printf(fmt_str, "* default flag value", passed ? "OK" : "FAILED");
fflush(stdout);
if( !passed )
return 1;
}
//
// Test errors during array creation
//
{
bool passed = true;
alglib::clear_error_flag();
// constructors succeeded with working malloc()
alglib::clear_error_flag();
alglib::real_1d_array r1;
passed = passed && !alglib::get_error_flag();
// even with broken malloc() constructor succeeded()
alglib::clear_error_flag();
alglib_impl::_force_malloc_failure = true;
alglib::real_1d_array r2;
passed = passed && !alglib::get_error_flag();
// but setlength() fails without malloc()
alglib::clear_error_flag();
r2.setlength(5);
passed = passed && alglib::get_error_flag();
// clear_error_flag() clears error flag
alglib::clear_error_flag();
passed = passed && !alglib::get_error_flag();
// without clear_error_flag(), error flag is not reset by successful calls
alglib::clear_error_flag();
alglib_impl::_force_malloc_failure = true;
r2.setlength(5);
passed = passed && alglib::get_error_flag() && r2.length()==0;
alglib_impl::_force_malloc_failure = false;
r2.setlength(6);
passed = passed && alglib::get_error_flag() && r2.length()==6;
alglib::clear_error_flag();
r2.setlength(7);
passed = passed && !alglib::get_error_flag() && r2.length()==7;
// assignment to empty array requires malloc()
alglib::clear_error_flag();
alglib_impl::_force_malloc_failure = false;
alglib::real_1d_array r3;
r2.setlength(1);
r2[0] = 123.25;
alglib_impl::_force_malloc_failure = true;
r3 = r2;
passed = passed && alglib::get_error_flag() && r3.length()==0;
alglib_impl::_force_malloc_failure = false;
alglib::clear_error_flag();
r3 = r2;
passed = passed && !alglib::get_error_flag() && r3.length()==1 && r3[0]==123.25;
// assignment to non-empty array does NOT require malloc()
alglib::clear_error_flag();
alglib_impl::_force_malloc_failure = true;
r2[0] = 345;
r3 = r2;
passed = passed && !alglib::get_error_flag() && r3.length()==1 && r3[0]==345;
alglib_impl::_force_malloc_failure = false;
printf(fmt_str, "* 1D arrays", passed ? "OK" : "FAILED");
fflush(stdout);
if( !passed )
return 1;
}
{
bool passed = true;
alglib::clear_error_flag();
// constructors succeeded with working malloc()
alglib::clear_error_flag();
alglib::real_2d_array r1;
passed = passed && !alglib::get_error_flag();
// even with broken malloc() constructor succeeded()
alglib::clear_error_flag();
alglib_impl::_force_malloc_failure = true;
alglib::real_2d_array r2;
passed = passed && !alglib::get_error_flag();
// but setlength() fails without malloc()
alglib::clear_error_flag();
r2.setlength(5,6);
passed = passed && alglib::get_error_flag();
// clear_error_flag() clears error flag
alglib::clear_error_flag();
passed = passed && !alglib::get_error_flag();
// without clear_error_flag(), error flag is not reset by successful calls
alglib::clear_error_flag();
alglib_impl::_force_malloc_failure = true;
r2.setlength(5,6);
passed = passed && alglib::get_error_flag() && r2.rows()==0 && r2.cols()==0;
alglib_impl::_force_malloc_failure = false;
r2.setlength(6,7);
passed = passed && alglib::get_error_flag() && r2.rows()==6 && r2.cols()==7;
alglib::clear_error_flag();
r2.setlength(7,8);
passed = passed && !alglib::get_error_flag() && r2.rows()==7 && r2.cols()==8;
// assignment to empty array requires malloc()
alglib::clear_error_flag();
alglib_impl::_force_malloc_failure = false;
alglib::real_2d_array r3;
r2.setlength(1,1);
r2[0][0] = 123.25;
alglib_impl::_force_malloc_failure = true;
r3 = r2;
passed = passed && alglib::get_error_flag() && r3.rows()==0 && r3.cols()==0;
alglib_impl::_force_malloc_failure = false;
alglib::clear_error_flag();
r3 = r2;
passed = passed && !alglib::get_error_flag() && r3.rows()==1 && r3.cols()==1 && r3[0][0]==123.25;
// assignment to non-empty array does NOT require malloc()
alglib::clear_error_flag();
alglib_impl::_force_malloc_failure = true;
r2[0][0] = 345;
r3 = r2;
passed = passed && !alglib::get_error_flag() && r3.rows()==1 && r3.cols()==1 && r3[0][0]==345;
alglib_impl::_force_malloc_failure = false;
printf(fmt_str, "* 2D arrays", passed ? "OK" : "FAILED");
fflush(stdout);
if( !passed )
return 1;
}
//
// Test ALGLIB objects
//
{
bool passed = true;
alglib::clear_error_flag();
// prepare data for tests
alglib::real_1d_array x, y;
x.setlength(2);
x[0] = 0;
x[1] = 1;
y.setlength(2);
y[0] = 2;
y[1] = 3;
// constructors succeeded with working malloc()
alglib::clear_error_flag();
alglib::spline1dinterpolant s1;
passed = passed && !alglib::get_error_flag();
// with broken malloc() constructor fails()
alglib::clear_error_flag();
alglib_impl::_force_malloc_failure = true;
alglib::spline1dinterpolant s2;
passed = passed && alglib::get_error_flag();
alglib_impl::_force_malloc_failure = false;
// construction with correct malloc() succeeds
alglib::clear_error_flag();
alglib::spline1dbuildlinear(x, y, 2, s1);
passed = passed && !alglib::get_error_flag() && fabs(alglib::spline1dcalc(s1,0.5)-2.5)<1.0E-12;
// assignment with broken malloc() fails
alglib::clear_error_flag();
alglib::spline1dinterpolant s3;
alglib_impl::_force_malloc_failure = true;
s3 = s1;
alglib_impl::_force_malloc_failure = false;
passed = passed && alglib::get_error_flag();
// assignment with broken object fails, but does not crash
alglib::clear_error_flag();
alglib_impl::_force_malloc_failure = true;
alglib::spline1dinterpolant s3b;
passed = passed && s3b.c_ptr()==NULL;
s3b = s1;
alglib_impl::_force_malloc_failure = false;
passed = passed && alglib::get_error_flag();
// assignment with working malloc() succeeds
alglib::clear_error_flag();
s3 = s1;
passed = passed && !alglib::get_error_flag() && fabs(alglib::spline1dcalc(s3,0.5)-2.5)<1.0E-12;
// copy constructor with broken malloc fails
alglib::clear_error_flag();
alglib_impl::_force_malloc_failure = true;
alglib::spline1dinterpolant s4(s1);
alglib_impl::_force_malloc_failure = false;
passed = passed && alglib::get_error_flag();
// copy constructor with working malloc succeeds
alglib::clear_error_flag();
alglib::spline1dinterpolant s5(s1);
passed = passed && !alglib::get_error_flag() && fabs(alglib::spline1dcalc(s5,0.5)-2.5)<1.0E-12;
printf(fmt_str, "* ALGLIB objects", passed ? "OK" : "FAILED");
fflush(stdout);
if( !passed )
return 1;
}
//
// Test ALGLIB functions
//
{
bool passed = true;
//
alglib::clear_error_flag();
alglib::spline1dinterpolant s1;
alglib::real_1d_array x, y;
x.setlength(2);
x[0] = 0;
x[1] = 1;
y.setlength(2);
y[0] = 2;
y[1] = alglib::fp_nan;
passed = passed && !alglib::get_error_flag();
alglib::spline1dbuildlinear(x, y, 2, s1);
passed = passed && alglib::get_error_flag();
printf(fmt_str, "* ALGLIB functions", passed ? "OK" : "FAILED");
fflush(stdout);
if( !passed )
return 1;
}
//
// Allocation counter
//
#ifdef AE_USE_ALLOC_COUNTER
printf("Allocation counter checked... ");
if( alglib_impl::_alloc_counter!=0 )
{
printf("FAILURE: alloc_counter is non-zero on end!\n");
return 1;
}
else
printf("OK\n");
#endif
//
// Return
//
return 0;
}
cpp/tests/test_c.cpp 0000755 0001750 0001750 00022376651 13576650314 014410 0 ustar sergey sergey #include
#include
#include "ap.h"
// disable some irrelevant warnings
#if (AE_COMPILER==AE_MSVC) && !defined(AE_ALL_WARNINGS)
#pragma warning(disable:4100)
#pragma warning(disable:4127)
#pragma warning(disable:4611)
#pragma warning(disable:4702)
#pragma warning(disable:4996)
#endif
#include "alglibinternal.h"
#include "alglibmisc.h"
#include "diffequations.h"
#include "linalg.h"
#include "optimization.h"
#include "solvers.h"
#include "statistics.h"
#include "dataanalysis.h"
#include "specialfunctions.h"
#include "integration.h"
#include "fasttransforms.h"
#include "interpolation.h"
using namespace alglib_impl;
/*************************************************************************
Testing tag sort
*************************************************************************/
ae_bool testtsort(ae_bool silent, ae_state *_state);
ae_bool _pexec_testtsort(ae_bool silent, ae_state *_state);
/*************************************************************************
Testing Nearest Neighbor Search
*************************************************************************/
ae_bool testnearestneighbor(ae_bool silent, ae_state *_state);
ae_bool _pexec_testnearestneighbor(ae_bool silent, ae_state *_state);
ae_bool testhqrnd(ae_bool silent, ae_state *_state);
ae_bool _pexec_testhqrnd(ae_bool silent, ae_state *_state);
/*************************************************************************
Function for test HQRNDContinuous function
*************************************************************************/
ae_bool hqrndcontinuoustest(ae_bool silent, ae_state *_state);
/*************************************************************************
Function for test HQRNDContinuous function
*************************************************************************/
ae_bool hqrnddiscretetest(ae_bool silent, ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testodesolver(ae_bool silent, ae_state *_state);
ae_bool _pexec_testodesolver(ae_bool silent, ae_state *_state);
typedef struct
{
ae_int_t n;
ae_int_t m;
ae_int_t matkind;
ae_int_t triangle;
ae_matrix bufa;
hqrndstate rs;
rcommstate rcs;
} sparsegenerator;
ae_bool testsparse(ae_bool silent, ae_state *_state);
ae_bool _pexec_testsparse(ae_bool silent, ae_state *_state);
/*************************************************************************
Function for testing basic SKS functional.
Returns True on errors, False on success.
-- ALGLIB PROJECT --
Copyright 16.01.1014 by Bochkanov Sergey
*************************************************************************/
ae_bool skstest(ae_state *_state);
/*************************************************************************
Function for testing CRS-specific functionality.
On failure sets ErrorFlag, on success does not touch it.
-- ALGLIB PROJECT --
Copyright 30.01.2018 by Bochkanov Sergey
*************************************************************************/
void crstest(ae_bool* errorflag, ae_state *_state);
/*************************************************************************
Function for testing basic functional
-- ALGLIB PROJECT --
Copyright 14.10.2011 by Bochkanov Sergey
*************************************************************************/
ae_bool basicfunctest(ae_state *_state);
/*************************************************************************
Function for testing Level 2 unsymmetric linear algebra functions.
Additionally it tests SparseGet() for several matrix formats.
Returns True on failure.
-- ALGLIB PROJECT --
Copyright 20.01.2014 by Bochkanov Sergey
*************************************************************************/
ae_bool testlevel2unsymmetric(ae_state *_state);
/*************************************************************************
Function for testing Level 3 unsymmetric linear algebra functions.
Additionally it tests SparseGet() for several matrix formats.
Returns True on failure.
-- ALGLIB PROJECT --
Copyright 20.01.2014 by Bochkanov Sergey
*************************************************************************/
ae_bool testlevel3unsymmetric(ae_state *_state);
/*************************************************************************
Function for testing Level 2 symmetric linear algebra functions.
Additionally it tests SparseGet() for several matrix formats.
Returns True on failure.
-- ALGLIB PROJECT --
Copyright 20.01.2014 by Bochkanov Sergey
*************************************************************************/
ae_bool testlevel2symmetric(ae_state *_state);
/*************************************************************************
Function for testing Level 2 symmetric linear algebra functions.
Additionally it tests SparseGet() for several matrix formats.
Returns True on failure.
-- ALGLIB PROJECT --
Copyright 14.10.2011 by Bochkanov Sergey
*************************************************************************/
ae_bool testlevel3symmetric(ae_state *_state);
/*************************************************************************
Function for testing Level 2 triangular linear algebra functions.
Returns True on failure.
-- ALGLIB PROJECT --
Copyright 20.01.2014 by Bochkanov Sergey
*************************************************************************/
ae_bool testlevel2triangular(ae_state *_state);
/*************************************************************************
Function for testing basic functional
-- ALGLIB PROJECT --
Copyright 14.10.2011 by Bochkanov Sergey
*************************************************************************/
ae_bool basicfuncrandomtest(ae_state *_state);
/*************************************************************************
Function for testing multyplication matrix with vector
-- ALGLIB PROJECT --
Copyright 14.10.2011 by Bochkanov Sergey
*************************************************************************/
ae_bool linearfunctionstest(ae_state *_state);
/*************************************************************************
Function for testing multyplication for simmetric matrix with vector
-- ALGLIB PROJECT --
Copyright 14.10.2011 by Bochkanov Sergey
*************************************************************************/
ae_bool linearfunctionsstest(ae_state *_state);
/*************************************************************************
Function for testing multyplication sparse matrix with nerrow dense matrix
-- ALGLIB PROJECT --
Copyright 14.10.2011 by Bochkanov Sergey
*************************************************************************/
ae_bool linearfunctionsmmtest(ae_state *_state);
/*************************************************************************
Function for testing multyplication for simmetric sparse matrix with narrow
dense matrix
-- ALGLIB PROJECT --
Copyright 14.10.2011 by Bochkanov Sergey
*************************************************************************/
ae_bool linearfunctionssmmtest(ae_state *_state);
/*************************************************************************
Function for basic test SparseCopy
-- ALGLIB PROJECT --
Copyright 14.10.2011 by Bochkanov Sergey
*************************************************************************/
ae_bool basiccopyfunctest(ae_bool silent, ae_state *_state);
/*************************************************************************
Function for testing SparseCopy
-- ALGLIB PROJECT --
Copyright 14.10.2011 by Bochkanov Sergey
*************************************************************************/
ae_bool copyfunctest(ae_bool silent, ae_state *_state);
void _sparsegenerator_init(void* _p, ae_state *_state, ae_bool make_automatic);
void _sparsegenerator_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic);
void _sparsegenerator_clear(void* _p);
void _sparsegenerator_destroy(void* _p);
ae_bool testablas(ae_bool silent, ae_state *_state);
ae_bool _pexec_testablas(ae_bool silent, ae_state *_state);
ae_bool testcreflections(ae_bool silent, ae_state *_state);
ae_bool _pexec_testcreflections(ae_bool silent, ae_state *_state);
ae_bool testmatgen(ae_bool silent, ae_state *_state);
ae_bool _pexec_testmatgen(ae_bool silent, ae_state *_state);
ae_bool testtrfac(ae_bool silent, ae_state *_state);
ae_bool _pexec_testtrfac(ae_bool silent, ae_state *_state);
/*************************************************************************
Function for testing sparse real Cholesky.
Returns True on errors, False on success.
-- ALGLIB PROJECT --
Copyright 16.01.1014 by Bochkanov Sergey
*************************************************************************/
ae_bool sparserealcholeskytest(ae_state *_state);
/*************************************************************************
Function for testing sparse real LU decomposition.
Sets error flag on failure, leave is unchanged on success.
-- ALGLIB PROJECT --
Copyright 16.01.1014 by Bochkanov Sergey
*************************************************************************/
void sparsereallutest(ae_bool* err, ae_state *_state);
/*************************************************************************
Main unittest subroutine
*************************************************************************/
ae_bool testtrlinsolve(ae_bool silent, ae_state *_state);
ae_bool _pexec_testtrlinsolve(ae_bool silent, ae_state *_state);
/*************************************************************************
Main unittest subroutine
*************************************************************************/
ae_bool testsafesolve(ae_bool silent, ae_state *_state);
ae_bool _pexec_testsafesolve(ae_bool silent, ae_state *_state);
ae_bool testrcond(ae_bool silent, ae_state *_state);
ae_bool _pexec_testrcond(ae_bool silent, ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testmatinv(ae_bool silent, ae_state *_state);
ae_bool _pexec_testmatinv(ae_bool silent, ae_state *_state);
ae_bool testhblas(ae_bool silent, ae_state *_state);
ae_bool _pexec_testhblas(ae_bool silent, ae_state *_state);
ae_bool testsblas(ae_bool silent, ae_state *_state);
ae_bool _pexec_testsblas(ae_bool silent, ae_state *_state);
/*************************************************************************
Main unittest subroutine
*************************************************************************/
ae_bool testortfac(ae_bool silent, ae_state *_state);
ae_bool _pexec_testortfac(ae_bool silent, ae_state *_state);
/*************************************************************************
Testing
*************************************************************************/
ae_bool testfbls(ae_bool silent, ae_state *_state);
ae_bool _pexec_testfbls(ae_bool silent, ae_state *_state);
ae_bool testcqmodels(ae_bool silent, ae_state *_state);
ae_bool _pexec_testcqmodels(ae_bool silent, ae_state *_state);
/*************************************************************************
Testing bidiagonal SVD decomposition subroutine
*************************************************************************/
ae_bool testbdsvd(ae_bool silent, ae_state *_state);
ae_bool _pexec_testbdsvd(ae_bool silent, ae_state *_state);
ae_bool testblas(ae_bool silent, ae_state *_state);
ae_bool _pexec_testblas(ae_bool silent, ae_state *_state);
/*************************************************************************
Testing SVD decomposition subroutine
*************************************************************************/
ae_bool testsvd(ae_bool silent, ae_state *_state);
ae_bool _pexec_testsvd(ae_bool silent, ae_state *_state);
ae_bool testoptserv(ae_bool silent, ae_state *_state);
ae_bool _pexec_testoptserv(ae_bool silent, ae_state *_state);
ae_bool testsnnls(ae_bool silent, ae_state *_state);
ae_bool _pexec_testsnnls(ae_bool silent, ae_state *_state);
ae_bool testsactivesets(ae_bool silent, ae_state *_state);
ae_bool _pexec_testsactivesets(ae_bool silent, ae_state *_state);
ae_bool testxblas(ae_bool silent, ae_state *_state);
ae_bool _pexec_testxblas(ae_bool silent, ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testdirectdensesolvers(ae_bool silent, ae_state *_state);
ae_bool _pexec_testdirectdensesolvers(ae_bool silent, ae_state *_state);
ae_bool testlinmin(ae_bool silent, ae_state *_state);
ae_bool _pexec_testlinmin(ae_bool silent, ae_state *_state);
ae_bool testminlbfgs(ae_bool silent, ae_state *_state);
ae_bool _pexec_testminlbfgs(ae_bool silent, ae_state *_state);
ae_bool testnormestimator(ae_bool silent, ae_state *_state);
ae_bool _pexec_testnormestimator(ae_bool silent, ae_state *_state);
ae_bool testlinlsqr(ae_bool silent, ae_state *_state);
ae_bool _pexec_testlinlsqr(ae_bool silent, ae_state *_state);
ae_bool testminbleic(ae_bool silent, ae_state *_state);
ae_bool _pexec_testminbleic(ae_bool silent, ae_state *_state);
ae_bool testminqp(ae_bool silent, ae_state *_state);
ae_bool _pexec_testminqp(ae_bool silent, ae_state *_state);
/*************************************************************************
Function to test: 'MinQPCreate', 'MinQPSetQuadraticTerm', 'MinQPSetBC',
'MinQPSetOrigin', 'MinQPSetStartingPoint', 'MinQPOptimize', 'MinQPResults'.
Test problem:
A = diag(aii), aii>0 (random)
b = 0
random bounds (either no bounds, one bound, two bounds a 0
without bounds
random start point
dimension - from 1 to 5.
*************************************************************************/
ae_bool functest1(ae_state *_state);
/*************************************************************************
Function to test: 'MinQPCreate', 'MinQPSetLinearTerm', 'MinQPSetQuadraticTerm',
'MinQPSetBC', 'MinQPSetOrigin', 'MinQPSetStartingPoint', 'MinQPOptimize',
'MinQPResults'.
Test problem:
A = positive-definite matrix, obtained by 'SPDMatrixRndCond' function
b <> 0
boundary constraints
random start point
dimension - from 1 to 5.
*************************************************************************/
ae_bool functest2(ae_state *_state);
/*************************************************************************
ConsoleTest.
*************************************************************************/
ae_bool consoletest(ae_state *_state);
/*************************************************************************
This function performs tests specific for QuickQP solver
Returns True on failure.
*************************************************************************/
ae_bool quickqptests(ae_state *_state);
/*************************************************************************
This function performs tests specific for BLEIC solver
Returns True on error, False on success.
*************************************************************************/
ae_bool bleictests(ae_state *_state);
ae_bool testminlp(ae_bool silent, ae_state *_state);
ae_bool _pexec_testminlp(ae_bool silent, ae_state *_state);
ae_bool testminnlc(ae_bool silent, ae_state *_state);
ae_bool _pexec_testminnlc(ae_bool silent, ae_state *_state);
ae_bool testminbc(ae_bool silent, ae_state *_state);
ae_bool _pexec_testminbc(ae_bool silent, ae_state *_state);
ae_bool testminns(ae_bool silent, ae_state *_state);
ae_bool _pexec_testminns(ae_bool silent, ae_state *_state);
ae_bool testmincg(ae_bool silent, ae_state *_state);
ae_bool _pexec_testmincg(ae_bool silent, ae_state *_state);
/*************************************************************************
Other properties
*************************************************************************/
void testother(ae_bool* err, ae_state *_state);
ae_bool testminlm(ae_bool silent, ae_state *_state);
ae_bool _pexec_testminlm(ae_bool silent, ae_state *_state);
/*************************************************************************
Testing symmetric EVD subroutine
*************************************************************************/
ae_bool testevd(ae_bool silent, ae_state *_state);
ae_bool _pexec_testevd(ae_bool silent, ae_state *_state);
ae_bool testbasestat(ae_bool silent, ae_state *_state);
ae_bool _pexec_testbasestat(ae_bool silent, ae_state *_state);
ae_bool testpca(ae_bool silent, ae_state *_state);
ae_bool _pexec_testpca(ae_bool silent, ae_state *_state);
/*************************************************************************
Testing BDSS operations
*************************************************************************/
ae_bool testbdss(ae_bool silent, ae_state *_state);
ae_bool _pexec_testbdss(ae_bool silent, ae_state *_state);
ae_bool testmlpbase(ae_bool silent, ae_state *_state);
ae_bool _pexec_testmlpbase(ae_bool silent, ae_state *_state);
ae_bool testlda(ae_bool silent, ae_state *_state);
ae_bool _pexec_testlda(ae_bool silent, ae_state *_state);
ae_bool testssa(ae_bool silent, ae_state *_state);
ae_bool _pexec_testssa(ae_bool silent, ae_state *_state);
ae_bool testgammafunc(ae_bool silent, ae_state *_state);
ae_bool _pexec_testgammafunc(ae_bool silent, ae_state *_state);
ae_bool testnormaldistr(ae_bool silent, ae_state *_state);
ae_bool _pexec_testnormaldistr(ae_bool silent, ae_state *_state);
ae_bool testlinreg(ae_bool silent, ae_state *_state);
ae_bool _pexec_testlinreg(ae_bool silent, ae_state *_state);
ae_bool testfilters(ae_bool silent, ae_state *_state);
ae_bool _pexec_testfilters(ae_bool silent, ae_state *_state);
/*************************************************************************
This function tests SMA(k) filter. It returns True on error.
Additional IsSilent parameter controls detailed error reporting.
*************************************************************************/
ae_bool testsma(ae_bool issilent, ae_state *_state);
/*************************************************************************
This function tests EMA(alpha) filter. It returns True on error.
Additional IsSilent parameter controls detailed error reporting.
*************************************************************************/
ae_bool testema(ae_bool issilent, ae_state *_state);
/*************************************************************************
This function tests LRMA(k) filter. It returns True on error.
Additional IsSilent parameter controls detailed error reporting.
*************************************************************************/
ae_bool testlrma(ae_bool issilent, ae_state *_state);
ae_bool testmcpd(ae_bool silent, ae_state *_state);
ae_bool _pexec_testmcpd(ae_bool silent, ae_state *_state);
ae_bool testmlpe(ae_bool silent, ae_state *_state);
ae_bool _pexec_testmlpe(ae_bool silent, ae_state *_state);
ae_bool testmlptrain(ae_bool silent, ae_state *_state);
ae_bool _pexec_testmlptrain(ae_bool silent, ae_state *_state);
/*************************************************************************
Testing clustering
*************************************************************************/
ae_bool testclustering(ae_bool silent, ae_state *_state);
ae_bool _pexec_testclustering(ae_bool silent, ae_state *_state);
ae_bool testdforest(ae_bool silent, ae_state *_state);
ae_bool _pexec_testdforest(ae_bool silent, ae_state *_state);
ae_bool testknn(ae_bool silent, ae_state *_state);
ae_bool _pexec_testknn(ae_bool silent, ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testgq(ae_bool silent, ae_state *_state);
ae_bool _pexec_testgq(ae_bool silent, ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testgkq(ae_bool silent, ae_state *_state);
ae_bool _pexec_testgkq(ae_bool silent, ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testautogk(ae_bool silent, ae_state *_state);
ae_bool _pexec_testautogk(ae_bool silent, ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testfft(ae_bool silent, ae_state *_state);
ae_bool _pexec_testfft(ae_bool silent, ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testfht(ae_bool silent, ae_state *_state);
ae_bool _pexec_testfht(ae_bool silent, ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testconv(ae_bool silent, ae_state *_state);
ae_bool _pexec_testconv(ae_bool silent, ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testcorr(ae_bool silent, ae_state *_state);
ae_bool _pexec_testcorr(ae_bool silent, ae_state *_state);
/*************************************************************************
Testing IDW interpolation
*************************************************************************/
ae_bool testidw(ae_bool silent, ae_state *_state);
ae_bool _pexec_testidw(ae_bool silent, ae_state *_state);
ae_bool testratint(ae_bool silent, ae_state *_state);
ae_bool _pexec_testratint(ae_bool silent, ae_state *_state);
ae_bool testfitsphere(ae_bool silent, ae_state *_state);
ae_bool _pexec_testfitsphere(ae_bool silent, ae_state *_state);
ae_bool testspline1d(ae_bool silent, ae_state *_state);
ae_bool _pexec_testspline1d(ae_bool silent, ae_state *_state);
ae_bool testparametric(ae_bool silent, ae_state *_state);
ae_bool _pexec_testparametric(ae_bool silent, ae_state *_state);
ae_bool testspline3d(ae_bool silence, ae_state *_state);
ae_bool _pexec_testspline3d(ae_bool silence, ae_state *_state);
/*************************************************************************
Unit test
*************************************************************************/
ae_bool testpolint(ae_bool silent, ae_state *_state);
ae_bool _pexec_testpolint(ae_bool silent, ae_state *_state);
ae_bool testlsfit(ae_bool silent, ae_state *_state);
ae_bool _pexec_testlsfit(ae_bool silent, ae_state *_state);
ae_bool testspline2d(ae_bool silent, ae_state *_state);
ae_bool _pexec_testspline2d(ae_bool silent, ae_state *_state);
ae_bool testrbf(ae_bool silent, ae_state *_state);
ae_bool _pexec_testrbf(ae_bool silent, ae_state *_state);
/*************************************************************************
The test has to check, that algorithm can solve problems of matrix are
degenerate.
* used model with linear term;
* points locate in a subspace of dimension less than an original space.
-- ALGLIB --
Copyright 13.12.2011 by Bochkanov Sergey
*************************************************************************/
ae_bool sqrdegmatrixrbftest(ae_bool silent, ae_state *_state);
/*************************************************************************
Function for testing basic functionality of RBF module on regular grids with
multi-layer algorithm in 1D.
-- ALGLIB --
Copyright 2.03.2012 by Bochkanov Sergey
*************************************************************************/
ae_bool basicmultilayerrbf1dtest(ae_state *_state);
ae_bool testhermite(ae_bool silent, ae_state *_state);
ae_bool _pexec_testhermite(ae_bool silent, ae_state *_state);
ae_bool testlaguerre(ae_bool silent, ae_state *_state);
ae_bool _pexec_testlaguerre(ae_bool silent, ae_state *_state);
ae_bool testlegendre(ae_bool silent, ae_state *_state);
ae_bool _pexec_testlegendre(ae_bool silent, ae_state *_state);
ae_bool testchebyshev(ae_bool silent, ae_state *_state);
ae_bool _pexec_testchebyshev(ae_bool silent, ae_state *_state);
ae_bool testwsr(ae_bool silent, ae_state *_state);
ae_bool _pexec_testwsr(ae_bool silent, ae_state *_state);
ae_bool teststest(ae_bool silent, ae_state *_state);
ae_bool _pexec_teststest(ae_bool silent, ae_state *_state);
ae_bool teststudentttests(ae_bool silent, ae_state *_state);
ae_bool _pexec_teststudentttests(ae_bool silent, ae_state *_state);
ae_bool testmannwhitneyu(ae_bool silent, ae_state *_state);
ae_bool _pexec_testmannwhitneyu(ae_bool silent, ae_state *_state);
/*************************************************************************
Testing Schur decomposition subroutine
*************************************************************************/
ae_bool testschur(ae_bool silent, ae_state *_state);
ae_bool _pexec_testschur(ae_bool silent, ae_state *_state);
/*************************************************************************
Testing bidiagonal SVD decomposition subroutine
*************************************************************************/
ae_bool testspdgevd(ae_bool silent, ae_state *_state);
ae_bool _pexec_testspdgevd(ae_bool silent, ae_state *_state);
ae_bool testinverseupdate(ae_bool silent, ae_state *_state);
ae_bool _pexec_testinverseupdate(ae_bool silent, ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testpolynomialsolver(ae_bool silent, ae_state *_state);
ae_bool _pexec_testpolynomialsolver(ae_bool silent, ae_state *_state);
ae_bool testnleq(ae_bool silent, ae_state *_state);
ae_bool _pexec_testnleq(ae_bool silent, ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testdirectsparsesolvers(ae_bool silent, ae_state *_state);
ae_bool _pexec_testdirectsparsesolvers(ae_bool silent, ae_state *_state);
ae_bool testlincg(ae_bool silent, ae_state *_state);
ae_bool _pexec_testlincg(ae_bool silent, ae_state *_state);
typedef struct
{
ae_bool bfield;
double rfield;
ae_int_t ifield;
ae_complex cfield;
ae_vector b1field;
ae_vector r1field;
ae_vector i1field;
ae_vector c1field;
ae_matrix b2field;
ae_matrix r2field;
ae_matrix i2field;
ae_matrix c2field;
} rec1;
typedef struct
{
ae_vector b;
ae_vector i;
ae_vector r;
} rec4serialization;
typedef struct
{
ae_complex cval;
double rval;
ae_int_t ival;
ae_bool bval;
ae_vector i1val;
} poolrec1;
typedef struct
{
ae_bool bval;
poolrec1 recval;
ae_shared_pool pool;
} poolrec2;
typedef struct
{
ae_int_t val;
} poolsummand;
void rec4serializationalloc(ae_serializer* s,
rec4serialization* v,
ae_state *_state);
void rec4serializationserialize(ae_serializer* s,
rec4serialization* v,
ae_state *_state);
void rec4serializationunserialize(ae_serializer* s,
rec4serialization* v,
ae_state *_state);
ae_bool testalglibbasics(ae_bool silent, ae_state *_state);
ae_bool _pexec_testalglibbasics(ae_bool silent, ae_state *_state);
void _rec1_init(void* _p, ae_state *_state, ae_bool make_automatic);
void _rec1_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic);
void _rec1_clear(void* _p);
void _rec1_destroy(void* _p);
void _rec4serialization_init(void* _p, ae_state *_state, ae_bool make_automatic);
void _rec4serialization_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic);
void _rec4serialization_clear(void* _p);
void _rec4serialization_destroy(void* _p);
void _poolrec1_init(void* _p, ae_state *_state, ae_bool make_automatic);
void _poolrec1_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic);
void _poolrec1_clear(void* _p);
void _poolrec1_destroy(void* _p);
void _poolrec2_init(void* _p, ae_state *_state, ae_bool make_automatic);
void _poolrec2_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic);
void _poolrec2_clear(void* _p);
void _poolrec2_destroy(void* _p);
void _poolsummand_init(void* _p, ae_state *_state, ae_bool make_automatic);
void _poolsummand_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic);
void _poolsummand_clear(void* _p);
void _poolsummand_destroy(void* _p);
static void testtsortunit_unset1di(/* Integer */ ae_vector* a,
ae_state *_state);
static void testtsortunit_testsortresults(/* Real */ ae_vector* asorted,
/* Integer */ ae_vector* p1,
/* Integer */ ae_vector* p2,
/* Real */ ae_vector* aoriginal,
ae_int_t n,
ae_bool* waserrors,
ae_state *_state);
/*************************************************************************
Testing tag sort
*************************************************************************/
ae_bool testtsort(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_bool waserrors;
ae_int_t n;
ae_int_t i;
ae_int_t m;
ae_int_t offs;
ae_int_t pass;
ae_int_t passcount;
ae_int_t maxn;
ae_vector a;
ae_vector a0;
ae_vector a1;
ae_vector a2;
ae_vector a3;
ae_vector i1;
ae_vector i2;
ae_vector i3;
ae_vector a4;
ae_vector a5;
ae_vector pa4;
ae_vector ar;
ae_vector ar2;
ae_vector ai;
ae_vector p1;
ae_vector p2;
ae_vector bufr1;
ae_vector bufr2;
ae_vector bufi1;
ae_bool distinctvals;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&a0, 0, sizeof(a0));
memset(&a1, 0, sizeof(a1));
memset(&a2, 0, sizeof(a2));
memset(&a3, 0, sizeof(a3));
memset(&i1, 0, sizeof(i1));
memset(&i2, 0, sizeof(i2));
memset(&i3, 0, sizeof(i3));
memset(&a4, 0, sizeof(a4));
memset(&a5, 0, sizeof(a5));
memset(&pa4, 0, sizeof(pa4));
memset(&ar, 0, sizeof(ar));
memset(&ar2, 0, sizeof(ar2));
memset(&ai, 0, sizeof(ai));
memset(&p1, 0, sizeof(p1));
memset(&p2, 0, sizeof(p2));
memset(&bufr1, 0, sizeof(bufr1));
memset(&bufr2, 0, sizeof(bufr2));
memset(&bufi1, 0, sizeof(bufi1));
ae_vector_init(&a, 0, DT_REAL, _state, ae_true);
ae_vector_init(&a0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&a1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&a2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&a3, 0, DT_REAL, _state, ae_true);
ae_vector_init(&i1, 0, DT_INT, _state, ae_true);
ae_vector_init(&i2, 0, DT_INT, _state, ae_true);
ae_vector_init(&i3, 0, DT_INT, _state, ae_true);
ae_vector_init(&a4, 0, DT_INT, _state, ae_true);
ae_vector_init(&a5, 0, DT_INT, _state, ae_true);
ae_vector_init(&pa4, 0, DT_INT, _state, ae_true);
ae_vector_init(&ar, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ar2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ai, 0, DT_INT, _state, ae_true);
ae_vector_init(&p1, 0, DT_INT, _state, ae_true);
ae_vector_init(&p2, 0, DT_INT, _state, ae_true);
ae_vector_init(&bufr1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bufr2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bufi1, 0, DT_INT, _state, ae_true);
waserrors = ae_false;
maxn = 100;
passcount = 10;
/*
* Test tagsort
*/
for(n=1; n<=maxn; n++)
{
for(pass=1; pass<=passcount; pass++)
{
/*
* Pprobably distinct sort:
* * generate array of integer random numbers.
* Because of birthday paradox, random numbers have to be VERY large
* in order to avoid situation when we have distinct values.
* * sort A0 using TagSort and test sort results
* * now we can use A0 as reference point and test other functions
*/
testtsortunit_unset1di(&p1, _state);
testtsortunit_unset1di(&p2, _state);
ae_vector_set_length(&a, n, _state);
ae_vector_set_length(&a0, n, _state);
ae_vector_set_length(&a1, n, _state);
ae_vector_set_length(&a2, n, _state);
ae_vector_set_length(&a3, n, _state);
ae_vector_set_length(&a4, n, _state);
ae_vector_set_length(&a5, n, _state);
ae_vector_set_length(&ar, n, _state);
ae_vector_set_length(&ar2, n, _state);
ae_vector_set_length(&ai, n, _state);
for(i=0; i<=n-1; i++)
{
a.ptr.p_double[i] = (double)(ae_randominteger(100000000, _state));
a0.ptr.p_double[i] = a.ptr.p_double[i];
a1.ptr.p_double[i] = a.ptr.p_double[i];
a2.ptr.p_double[i] = a.ptr.p_double[i];
a3.ptr.p_double[i] = a.ptr.p_double[i];
a4.ptr.p_int[i] = ae_round(a.ptr.p_double[i], _state);
a5.ptr.p_int[i] = ae_round(a.ptr.p_double[i], _state);
ar.ptr.p_double[i] = (double)(i);
ar2.ptr.p_double[i] = (double)(i);
ai.ptr.p_int[i] = i;
}
tagsort(&a0, n, &p1, &p2, _state);
testtsortunit_testsortresults(&a0, &p1, &p2, &a, n, &waserrors, _state);
distinctvals = ae_true;
for(i=1; i<=n-1; i++)
{
distinctvals = distinctvals&&ae_fp_neq(a0.ptr.p_double[i],a0.ptr.p_double[i-1]);
}
if( distinctvals )
{
tagsortfasti(&a1, &ai, &bufr1, &bufi1, n, _state);
for(i=0; i<=n-1; i++)
{
waserrors = (waserrors||ae_fp_neq(a1.ptr.p_double[i],a0.ptr.p_double[i]))||ai.ptr.p_int[i]!=p1.ptr.p_int[i];
}
tagsortfastr(&a2, &ar, &bufr1, &bufr2, n, _state);
for(i=0; i<=n-1; i++)
{
waserrors = (waserrors||ae_fp_neq(a2.ptr.p_double[i],a0.ptr.p_double[i]))||ae_fp_neq(ar.ptr.p_double[i],(double)(p1.ptr.p_int[i]));
}
tagsortfast(&a3, &bufr1, n, _state);
for(i=0; i<=n-1; i++)
{
waserrors = waserrors||ae_fp_neq(a3.ptr.p_double[i],a0.ptr.p_double[i]);
}
tagsortmiddleir(&a4, &ar2, 0, n, _state);
for(i=0; i<=n-1; i++)
{
waserrors = (waserrors||ae_fp_neq((double)(a4.ptr.p_int[i]),a0.ptr.p_double[i]))||ae_fp_neq(ar2.ptr.p_double[i],(double)(p1.ptr.p_int[i]));
}
sortmiddlei(&a5, 0, n, _state);
for(i=0; i<=n-1; i++)
{
waserrors = waserrors||ae_fp_neq((double)(a5.ptr.p_int[i]),a0.ptr.p_double[i]);
}
}
/*
* Non-distinct sort.
* We test that keys are correctly reordered, but do NOT test order of values.
*/
testtsortunit_unset1di(&p1, _state);
testtsortunit_unset1di(&p2, _state);
ae_vector_set_length(&a, n, _state);
ae_vector_set_length(&a0, n, _state);
ae_vector_set_length(&a1, n, _state);
ae_vector_set_length(&a2, n, _state);
ae_vector_set_length(&a3, n, _state);
ae_vector_set_length(&a4, n, _state);
ae_vector_set_length(&a5, n, _state);
ae_vector_set_length(&ar, n, _state);
ae_vector_set_length(&ar2, n, _state);
ae_vector_set_length(&ai, n, _state);
for(i=0; i<=n-1; i++)
{
a.ptr.p_double[i] = (double)((n-i)/2);
a0.ptr.p_double[i] = a.ptr.p_double[i];
a1.ptr.p_double[i] = a.ptr.p_double[i];
a2.ptr.p_double[i] = a.ptr.p_double[i];
a3.ptr.p_double[i] = a.ptr.p_double[i];
a4.ptr.p_int[i] = ae_round(a.ptr.p_double[i], _state);
a5.ptr.p_int[i] = ae_round(a.ptr.p_double[i], _state);
ar.ptr.p_double[i] = (double)(i);
ar2.ptr.p_double[i] = (double)(i);
ai.ptr.p_int[i] = i;
}
tagsort(&a0, n, &p1, &p2, _state);
testtsortunit_testsortresults(&a0, &p1, &p2, &a, n, &waserrors, _state);
tagsortfasti(&a1, &ai, &bufr1, &bufi1, n, _state);
for(i=0; i<=n-1; i++)
{
waserrors = waserrors||ae_fp_neq(a1.ptr.p_double[i],a0.ptr.p_double[i]);
}
tagsortfastr(&a2, &ar, &bufr1, &bufr2, n, _state);
for(i=0; i<=n-1; i++)
{
waserrors = waserrors||ae_fp_neq(a2.ptr.p_double[i],a0.ptr.p_double[i]);
}
tagsortfast(&a3, &bufr1, n, _state);
for(i=0; i<=n-1; i++)
{
waserrors = waserrors||ae_fp_neq(a3.ptr.p_double[i],a0.ptr.p_double[i]);
}
tagsortmiddleir(&a4, &ar2, 0, n, _state);
for(i=0; i<=n-1; i++)
{
waserrors = waserrors||ae_fp_neq((double)(a4.ptr.p_int[i]),a0.ptr.p_double[i]);
}
sortmiddlei(&a5, 0, n, _state);
for(i=0; i<=n-1; i++)
{
waserrors = waserrors||ae_fp_neq((double)(a5.ptr.p_int[i]),a0.ptr.p_double[i]);
}
/*
* 'All same' sort
* We test that keys are correctly reordered, but do NOT test order of values.
*/
testtsortunit_unset1di(&p1, _state);
testtsortunit_unset1di(&p2, _state);
ae_vector_set_length(&a, n, _state);
ae_vector_set_length(&a0, n, _state);
ae_vector_set_length(&a1, n, _state);
ae_vector_set_length(&a2, n, _state);
ae_vector_set_length(&a3, n, _state);
ae_vector_set_length(&a4, n, _state);
ae_vector_set_length(&ar, n, _state);
ae_vector_set_length(&ar2, n, _state);
ae_vector_set_length(&ai, n, _state);
for(i=0; i<=n-1; i++)
{
a.ptr.p_double[i] = (double)(0);
a0.ptr.p_double[i] = a.ptr.p_double[i];
a1.ptr.p_double[i] = a.ptr.p_double[i];
a2.ptr.p_double[i] = a.ptr.p_double[i];
a3.ptr.p_double[i] = a.ptr.p_double[i];
a4.ptr.p_int[i] = ae_round(a.ptr.p_double[i], _state);
ar.ptr.p_double[i] = (double)(i);
ar2.ptr.p_double[i] = (double)(i);
ai.ptr.p_int[i] = i;
}
tagsort(&a0, n, &p1, &p2, _state);
testtsortunit_testsortresults(&a0, &p1, &p2, &a, n, &waserrors, _state);
tagsortfasti(&a1, &ai, &bufr1, &bufi1, n, _state);
for(i=0; i<=n-1; i++)
{
waserrors = waserrors||ae_fp_neq(a1.ptr.p_double[i],a0.ptr.p_double[i]);
}
tagsortfastr(&a2, &ar, &bufr1, &bufr2, n, _state);
for(i=0; i<=n-1; i++)
{
waserrors = waserrors||ae_fp_neq(a2.ptr.p_double[i],a0.ptr.p_double[i]);
}
tagsortfast(&a3, &bufr1, n, _state);
for(i=0; i<=n-1; i++)
{
waserrors = waserrors||ae_fp_neq(a3.ptr.p_double[i],a0.ptr.p_double[i]);
}
tagsortmiddleir(&a4, &ar2, 0, n, _state);
for(i=0; i<=n-1; i++)
{
waserrors = waserrors||ae_fp_neq((double)(a4.ptr.p_int[i]),a0.ptr.p_double[i]);
}
/*
* 0-1 sort
* We test that keys are correctly reordered, but do NOT test order of values.
*/
testtsortunit_unset1di(&p1, _state);
testtsortunit_unset1di(&p2, _state);
ae_vector_set_length(&a, n, _state);
ae_vector_set_length(&a0, n, _state);
ae_vector_set_length(&a1, n, _state);
ae_vector_set_length(&a2, n, _state);
ae_vector_set_length(&a3, n, _state);
ae_vector_set_length(&a4, n, _state);
ae_vector_set_length(&ar, n, _state);
ae_vector_set_length(&ar2, n, _state);
ae_vector_set_length(&ai, n, _state);
for(i=0; i<=n-1; i++)
{
a.ptr.p_double[i] = (double)(ae_randominteger(2, _state));
a0.ptr.p_double[i] = a.ptr.p_double[i];
a1.ptr.p_double[i] = a.ptr.p_double[i];
a2.ptr.p_double[i] = a.ptr.p_double[i];
a3.ptr.p_double[i] = a.ptr.p_double[i];
a4.ptr.p_int[i] = ae_round(a.ptr.p_double[i], _state);
ar.ptr.p_double[i] = (double)(i);
ar2.ptr.p_double[i] = (double)(i);
ai.ptr.p_int[i] = i;
}
tagsort(&a0, n, &p1, &p2, _state);
testtsortunit_testsortresults(&a0, &p1, &p2, &a, n, &waserrors, _state);
tagsortfasti(&a1, &ai, &bufr1, &bufi1, n, _state);
for(i=0; i<=n-1; i++)
{
waserrors = waserrors||ae_fp_neq(a1.ptr.p_double[i],a0.ptr.p_double[i]);
}
tagsortfastr(&a2, &ar, &bufr1, &bufr2, n, _state);
for(i=0; i<=n-1; i++)
{
waserrors = waserrors||ae_fp_neq(a2.ptr.p_double[i],a0.ptr.p_double[i]);
}
tagsortfast(&a3, &bufr1, n, _state);
for(i=0; i<=n-1; i++)
{
waserrors = waserrors||ae_fp_neq(a3.ptr.p_double[i],a0.ptr.p_double[i]);
}
tagsortmiddleir(&a4, &ar2, 0, n, _state);
for(i=0; i<=n-1; i++)
{
waserrors = waserrors||ae_fp_neq((double)(a4.ptr.p_int[i]),a0.ptr.p_double[i]);
}
/*
* Special test for TagSortMiddleIR: sorting in the middle gives same results
* as sorting in the beginning of the array
*/
m = 3*n;
offs = ae_randominteger(n, _state);
ae_vector_set_length(&i1, m, _state);
ae_vector_set_length(&i2, m, _state);
ae_vector_set_length(&i3, m, _state);
ae_vector_set_length(&ar, m, _state);
ae_vector_set_length(&ar2, m, _state);
for(i=0; i<=m-1; i++)
{
i1.ptr.p_int[i] = ae_randominteger(100000000, _state);
i2.ptr.p_int[i] = i1.ptr.p_int[i];
i3.ptr.p_int[i] = i1.ptr.p_int[i];
ar.ptr.p_double[i] = (double)(i);
ar2.ptr.p_double[i] = (double)(i);
}
for(i=0; i<=n-1; i++)
{
i1.ptr.p_int[i] = i1.ptr.p_int[offs+i];
ar.ptr.p_double[i] = ar.ptr.p_double[offs+i];
}
tagsortmiddleir(&i1, &ar, 0, n, _state);
for(i=1; i<=n-1; i++)
{
distinctvals = distinctvals&&i1.ptr.p_int[i]!=i1.ptr.p_int[i-1];
}
if( distinctvals )
{
tagsortmiddleir(&i2, &ar2, offs, n, _state);
for(i=0; i<=n-1; i++)
{
waserrors = (waserrors||i2.ptr.p_int[offs+i]!=i1.ptr.p_int[i])||ae_fp_neq(ar2.ptr.p_double[offs+i],ar.ptr.p_double[i]);
}
}
}
}
/*
* report
*/
if( !silent )
{
printf("TESTING TAGSORT\n");
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Unsets 1D array.
*************************************************************************/
static void testtsortunit_unset1di(/* Integer */ ae_vector* a,
ae_state *_state)
{
ae_vector_set_length(a, 0+1, _state);
a->ptr.p_int[0] = ae_randominteger(3, _state)-1;
}
static void testtsortunit_testsortresults(/* Real */ ae_vector* asorted,
/* Integer */ ae_vector* p1,
/* Integer */ ae_vector* p2,
/* Real */ ae_vector* aoriginal,
ae_int_t n,
ae_bool* waserrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_vector a2;
double t;
ae_vector f;
ae_frame_make(_state, &_frame_block);
memset(&a2, 0, sizeof(a2));
memset(&f, 0, sizeof(f));
ae_vector_init(&a2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&f, 0, DT_INT, _state, ae_true);
ae_vector_set_length(&a2, n-1+1, _state);
ae_vector_set_length(&f, n-1+1, _state);
/*
* is set ordered?
*/
for(i=0; i<=n-2; i++)
{
*waserrors = *waserrors||ae_fp_greater(asorted->ptr.p_double[i],asorted->ptr.p_double[i+1]);
}
/*
* P1 correctness
*/
for(i=0; i<=n-1; i++)
{
*waserrors = *waserrors||ae_fp_neq(asorted->ptr.p_double[i],aoriginal->ptr.p_double[p1->ptr.p_int[i]]);
}
for(i=0; i<=n-1; i++)
{
f.ptr.p_int[i] = 0;
}
for(i=0; i<=n-1; i++)
{
f.ptr.p_int[p1->ptr.p_int[i]] = f.ptr.p_int[p1->ptr.p_int[i]]+1;
}
for(i=0; i<=n-1; i++)
{
*waserrors = *waserrors||f.ptr.p_int[i]!=1;
}
/*
* P2 correctness
*/
for(i=0; i<=n-1; i++)
{
a2.ptr.p_double[i] = aoriginal->ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
if( p2->ptr.p_int[i]!=i )
{
t = a2.ptr.p_double[i];
a2.ptr.p_double[i] = a2.ptr.p_double[p2->ptr.p_int[i]];
a2.ptr.p_double[p2->ptr.p_int[i]] = t;
}
}
for(i=0; i<=n-1; i++)
{
*waserrors = *waserrors||ae_fp_neq(asorted->ptr.p_double[i],a2.ptr.p_double[i]);
}
ae_frame_leave(_state);
}
static ae_bool testnearestneighborunit_kdtresultsdifferent(/* Real */ ae_matrix* refxy,
ae_int_t ntotal,
/* Real */ ae_matrix* qx,
/* Real */ ae_matrix* qxy,
/* Integer */ ae_vector* qt,
ae_int_t n,
ae_int_t nx,
ae_int_t ny,
ae_state *_state);
static double testnearestneighborunit_vnorm(/* Real */ ae_vector* x,
ae_int_t n,
ae_int_t normtype,
ae_state *_state);
static void testnearestneighborunit_testkdtuniform(/* Real */ ae_matrix* xy,
ae_int_t n,
ae_int_t nx,
ae_int_t ny,
ae_int_t normtype,
ae_bool* kdterrors,
ae_state *_state);
static void testnearestneighborunit_testkdtreeserialization(ae_bool* err,
ae_state *_state);
static ae_bool testnearestneighborunit_testspecialcases(ae_state *_state);
/*************************************************************************
Testing Nearest Neighbor Search
*************************************************************************/
ae_bool testnearestneighbor(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_matrix xy;
ae_int_t i;
ae_int_t j;
double v;
ae_int_t normtype;
ae_int_t nx;
ae_int_t ny;
ae_int_t n;
ae_int_t smalln;
ae_int_t largen;
ae_int_t passcount;
ae_int_t pass;
ae_bool waserrors;
ae_bool kdterrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
kdterrors = ae_false;
passcount = 2;
smalln = 256;
largen = 2048;
ny = 3;
/*
*
*/
testnearestneighborunit_testkdtreeserialization(&kdterrors, _state);
for(pass=1; pass<=passcount; pass++)
{
for(normtype=0; normtype<=2; normtype++)
{
for(nx=1; nx<=3; nx++)
{
/*
* Test in hypercube
*/
ae_matrix_set_length(&xy, largen, nx+ny, _state);
for(i=0; i<=largen-1; i++)
{
for(j=0; j<=nx+ny-1; j++)
{
xy.ptr.pp_double[i][j] = 10*ae_randomreal(_state)-5;
}
}
for(n=1; n<=10; n++)
{
testnearestneighborunit_testkdtuniform(&xy, n, nx, ae_randominteger(ny+1, _state), normtype, &kdterrors, _state);
}
testnearestneighborunit_testkdtuniform(&xy, largen, nx, ae_randominteger(ny+1, _state), normtype, &kdterrors, _state);
/*
* Test clustered (2*N points, pairs of equal points)
*/
ae_matrix_set_length(&xy, 2*smalln, nx+ny, _state);
for(i=0; i<=smalln-1; i++)
{
for(j=0; j<=nx+ny-1; j++)
{
xy.ptr.pp_double[2*i+0][j] = 10*ae_randomreal(_state)-5;
xy.ptr.pp_double[2*i+1][j] = xy.ptr.pp_double[2*i+0][j];
}
}
testnearestneighborunit_testkdtuniform(&xy, 2*smalln, nx, ae_randominteger(ny+1, _state), normtype, &kdterrors, _state);
/*
* Test degenerate case: all points are same except for one
*/
ae_matrix_set_length(&xy, smalln, nx+ny, _state);
v = ae_randomreal(_state);
for(i=0; i<=smalln-2; i++)
{
for(j=0; j<=nx+ny-1; j++)
{
xy.ptr.pp_double[i][j] = v;
}
}
for(j=0; j<=nx+ny-1; j++)
{
xy.ptr.pp_double[smalln-1][j] = 10*ae_randomreal(_state)-5;
}
testnearestneighborunit_testkdtuniform(&xy, smalln, nx, ae_randominteger(ny+1, _state), normtype, &kdterrors, _state);
}
}
}
kdterrors = kdterrors||testnearestneighborunit_testspecialcases(_state);
/*
* report
*/
waserrors = kdterrors;
if( !silent )
{
printf("TESTING NEAREST NEIGHBOR SEARCH\n");
printf("* KD TREES: ");
if( !kdterrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Compare results from different queries:
* X just X-values
* XY X-values and Y-values
* XT X-values and tag values
*************************************************************************/
static ae_bool testnearestneighborunit_kdtresultsdifferent(/* Real */ ae_matrix* refxy,
ae_int_t ntotal,
/* Real */ ae_matrix* qx,
/* Real */ ae_matrix* qxy,
/* Integer */ ae_vector* qt,
ae_int_t n,
ae_int_t nx,
ae_int_t ny,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_bool result;
result = ae_false;
for(i=0; i<=n-1; i++)
{
if( qt->ptr.p_int[i]<0||qt->ptr.p_int[i]>=ntotal )
{
result = ae_true;
return result;
}
for(j=0; j<=nx-1; j++)
{
result = result||ae_fp_neq(qx->ptr.pp_double[i][j],refxy->ptr.pp_double[qt->ptr.p_int[i]][j]);
result = result||ae_fp_neq(qxy->ptr.pp_double[i][j],refxy->ptr.pp_double[qt->ptr.p_int[i]][j]);
}
for(j=0; j<=ny-1; j++)
{
result = result||ae_fp_neq(qxy->ptr.pp_double[i][nx+j],refxy->ptr.pp_double[qt->ptr.p_int[i]][nx+j]);
}
}
return result;
}
/*************************************************************************
Returns norm
*************************************************************************/
static double testnearestneighborunit_vnorm(/* Real */ ae_vector* x,
ae_int_t n,
ae_int_t normtype,
ae_state *_state)
{
ae_int_t i;
double result;
result = ae_randomreal(_state);
if( normtype==0 )
{
result = (double)(0);
for(i=0; i<=n-1; i++)
{
result = ae_maxreal(result, ae_fabs(x->ptr.p_double[i], _state), _state);
}
return result;
}
if( normtype==1 )
{
result = (double)(0);
for(i=0; i<=n-1; i++)
{
result = result+ae_fabs(x->ptr.p_double[i], _state);
}
return result;
}
if( normtype==2 )
{
result = (double)(0);
for(i=0; i<=n-1; i++)
{
result = result+ae_sqr(x->ptr.p_double[i], _state);
}
result = ae_sqrt(result, _state);
return result;
}
return result;
}
/*************************************************************************
Testing Nearest Neighbor Search on uniformly distributed hypercube
NormType: 0, 1, 2
D: space dimension
N: points count
*************************************************************************/
static void testnearestneighborunit_testkdtuniform(/* Real */ ae_matrix* xy,
ae_int_t n,
ae_int_t nx,
ae_int_t ny,
ae_int_t normtype,
ae_bool* kdterrors,
ae_state *_state)
{
ae_frame _frame_block;
double errtol;
ae_vector tags;
ae_vector ptx;
ae_vector tmpx;
ae_vector tmpb;
kdtree treex;
kdtree treexy;
kdtree treext;
kdtreerequestbuffer bufx;
kdtreerequestbuffer bufxy;
kdtreerequestbuffer bufxt;
ae_matrix qx;
ae_matrix qxy;
ae_vector qtags;
ae_vector qr;
ae_vector boxmin;
ae_vector boxmax;
ae_vector qmin;
ae_vector qmax;
double spread;
ae_int_t kx;
ae_int_t kxy;
ae_int_t kt;
double eps;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t task;
ae_bool isequal;
double r;
ae_int_t q;
ae_int_t qcount;
double v;
ae_bool inthebox;
ae_bool orderedrnn;
ae_frame_make(_state, &_frame_block);
memset(&tags, 0, sizeof(tags));
memset(&ptx, 0, sizeof(ptx));
memset(&tmpx, 0, sizeof(tmpx));
memset(&tmpb, 0, sizeof(tmpb));
memset(&treex, 0, sizeof(treex));
memset(&treexy, 0, sizeof(treexy));
memset(&treext, 0, sizeof(treext));
memset(&bufx, 0, sizeof(bufx));
memset(&bufxy, 0, sizeof(bufxy));
memset(&bufxt, 0, sizeof(bufxt));
memset(&qx, 0, sizeof(qx));
memset(&qxy, 0, sizeof(qxy));
memset(&qtags, 0, sizeof(qtags));
memset(&qr, 0, sizeof(qr));
memset(&boxmin, 0, sizeof(boxmin));
memset(&boxmax, 0, sizeof(boxmax));
memset(&qmin, 0, sizeof(qmin));
memset(&qmax, 0, sizeof(qmax));
ae_vector_init(&tags, 0, DT_INT, _state, ae_true);
ae_vector_init(&ptx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmpx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmpb, 0, DT_BOOL, _state, ae_true);
_kdtree_init(&treex, _state, ae_true);
_kdtree_init(&treexy, _state, ae_true);
_kdtree_init(&treext, _state, ae_true);
_kdtreerequestbuffer_init(&bufx, _state, ae_true);
_kdtreerequestbuffer_init(&bufxy, _state, ae_true);
_kdtreerequestbuffer_init(&bufxt, _state, ae_true);
ae_matrix_init(&qx, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&qxy, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&qtags, 0, DT_INT, _state, ae_true);
ae_vector_init(&qr, 0, DT_REAL, _state, ae_true);
ae_vector_init(&boxmin, 0, DT_REAL, _state, ae_true);
ae_vector_init(&boxmax, 0, DT_REAL, _state, ae_true);
ae_vector_init(&qmin, 0, DT_REAL, _state, ae_true);
ae_vector_init(&qmax, 0, DT_REAL, _state, ae_true);
qcount = 10;
ae_assert(n>0, "Assertion failed", _state);
/*
* Tol - roundoff error tolerance (for '>=' comparisons)
*/
errtol = 100000*ae_machineepsilon;
/*
* Evaluate bounding box and spread.
*/
ae_vector_set_length(&boxmin, nx, _state);
ae_vector_set_length(&boxmax, nx, _state);
for(j=0; j<=nx-1; j++)
{
boxmin.ptr.p_double[j] = xy->ptr.pp_double[0][j];
boxmax.ptr.p_double[j] = xy->ptr.pp_double[0][j];
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=nx-1; j++)
{
boxmin.ptr.p_double[j] = ae_minreal(boxmin.ptr.p_double[j], xy->ptr.pp_double[i][j], _state);
boxmax.ptr.p_double[j] = ae_maxreal(boxmax.ptr.p_double[j], xy->ptr.pp_double[i][j], _state);
}
}
spread = (double)(0);
for(j=0; j<=nx-1; j++)
{
spread = ae_maxreal(spread, boxmax.ptr.p_double[j]-boxmin.ptr.p_double[j], _state);
}
if( ae_fp_eq(spread,(double)(0)) )
{
spread = (double)(1);
}
/*
* fill tags
*/
ae_vector_set_length(&tags, n, _state);
for(i=0; i<=n-1; i++)
{
tags.ptr.p_int[i] = i;
}
/*
* build trees
*/
kdtreebuild(xy, n, nx, 0, normtype, &treex, _state);
kdtreebuild(xy, n, nx, ny, normtype, &treexy, _state);
kdtreebuildtagged(xy, &tags, n, nx, 0, normtype, &treext, _state);
/*
* allocate arrays
*/
ae_vector_set_length(&tmpx, nx, _state);
ae_vector_set_length(&tmpb, n, _state);
ae_matrix_set_length(&qx, n, nx, _state);
ae_matrix_set_length(&qxy, n, nx+ny, _state);
ae_vector_set_length(&qtags, n, _state);
ae_vector_set_length(&qr, n, _state);
ae_vector_set_length(&ptx, nx, _state);
/*
* test general K-NN queries (with self-matches):
* * compare results from different trees (must be equal) and
* check that correct (value,tag) pairs are returned
* * test results from XT tree - let R be radius of query result.
* then all points not in result must be not closer than R.
*/
for(q=1; q<=qcount; q++)
{
/*
* Select K: 1..N
*/
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
k = 1+ae_randominteger(n, _state);
}
else
{
k = 1;
}
/*
* Select point (either one of the points, or random)
*/
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
i = ae_randominteger(n, _state);
ae_v_move(&ptx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1));
}
else
{
for(i=0; i<=nx-1; i++)
{
ptx.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
}
/*
* Test functions which use internal buffer:
* * consistency of results from different queries
* * points in query are IN the R-sphere (or at the boundary),
* and points not in query are outside of the R-sphere (or at the boundary)
* * distances are correct and are ordered
*/
kx = kdtreequeryknn(&treex, &ptx, k, ae_true, _state);
kxy = kdtreequeryknn(&treexy, &ptx, k, ae_true, _state);
kt = kdtreequeryknn(&treext, &ptx, k, ae_true, _state);
if( (kx!=k||kxy!=k)||kt!=k )
{
*kdterrors = ae_true;
ae_frame_leave(_state);
return;
}
unsetrealmatrix(&qx, _state);
unsetrealmatrix(&qxy, _state);
unsetintegerarray(&qtags, _state);
unsetrealarray(&qr, _state);
kdtreequeryresultsxi(&treex, &qx, _state);
kdtreequeryresultsxyi(&treexy, &qxy, _state);
kdtreequeryresultstagsi(&treext, &qtags, _state);
kdtreequeryresultsdistancesi(&treext, &qr, _state);
*kdterrors = *kdterrors||testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, k, nx, ny, _state);
unsetrealmatrix(&qx, _state);
unsetrealmatrix(&qxy, _state);
unsetintegerarray(&qtags, _state);
unsetrealarray(&qr, _state);
kdtreequeryresultsx(&treex, &qx, _state);
kdtreequeryresultsxy(&treexy, &qxy, _state);
kdtreequeryresultstags(&treext, &qtags, _state);
kdtreequeryresultsdistances(&treext, &qr, _state);
*kdterrors = *kdterrors||testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, k, nx, ny, _state);
for(i=0; i<=n-1; i++)
{
tmpb.ptr.p_bool[i] = ae_true;
}
r = (double)(0);
for(i=0; i<=k-1; i++)
{
tmpb.ptr.p_bool[qtags.ptr.p_int[i]] = ae_false;
ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1));
ae_v_sub(&tmpx.ptr.p_double[0], 1, &qx.ptr.pp_double[i][0], 1, ae_v_len(0,nx-1));
r = ae_maxreal(r, testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state), _state);
}
for(i=0; i<=n-1; i++)
{
if( tmpb.ptr.p_bool[i] )
{
ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1));
ae_v_sub(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1));
*kdterrors = *kdterrors||ae_fp_less(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state),r*(1-errtol));
}
}
for(i=0; i<=k-2; i++)
{
*kdterrors = *kdterrors||ae_fp_greater(qr.ptr.p_double[i],qr.ptr.p_double[i+1]);
}
for(i=0; i<=k-1; i++)
{
ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1));
ae_v_sub(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[qtags.ptr.p_int[i]][0], 1, ae_v_len(0,nx-1));
*kdterrors = *kdterrors||ae_fp_greater(ae_fabs(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state)-qr.ptr.p_double[i], _state),errtol);
}
/*
* Test functions which use external buffer:
* * create external request buffer, perform buffered request
* * reset status of internal buffer by performing 1-NN query, it is essential
* to test the fact that external buffer is used
* * check consistency of results from different queries
* * check that points in query are IN the R-sphere (or at the boundary),
* and points not in query are outside of the R-sphere (or at the boundary)
* * check that distances are correct and are ordered
*/
kdtreecreaterequestbuffer(&treex, &bufx, _state);
kdtreecreaterequestbuffer(&treexy, &bufxy, _state);
kdtreecreaterequestbuffer(&treext, &bufxt, _state);
kx = kdtreetsqueryknn(&treex, &bufx, &ptx, k, ae_true, _state);
kxy = kdtreetsqueryknn(&treexy, &bufxy, &ptx, k, ae_true, _state);
kt = kdtreetsqueryknn(&treext, &bufxt, &ptx, k, ae_true, _state);
kdtreequeryknn(&treex, &ptx, 1, ae_true, _state);
kdtreequeryknn(&treexy, &ptx, 1, ae_true, _state);
kdtreequeryknn(&treext, &ptx, 1, ae_true, _state);
if( (kx!=k||kxy!=k)||kt!=k )
{
*kdterrors = ae_true;
ae_frame_leave(_state);
return;
}
unsetrealmatrix(&qx, _state);
unsetrealmatrix(&qxy, _state);
unsetintegerarray(&qtags, _state);
unsetrealarray(&qr, _state);
kdtreetsqueryresultsx(&treex, &bufx, &qx, _state);
kdtreetsqueryresultsxy(&treexy, &bufxy, &qxy, _state);
kdtreetsqueryresultstags(&treext, &bufxt, &qtags, _state);
kdtreetsqueryresultsdistances(&treext, &bufxt, &qr, _state);
*kdterrors = *kdterrors||testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, k, nx, ny, _state);
for(i=0; i<=n-1; i++)
{
tmpb.ptr.p_bool[i] = ae_true;
}
r = (double)(0);
for(i=0; i<=k-1; i++)
{
tmpb.ptr.p_bool[qtags.ptr.p_int[i]] = ae_false;
ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1));
ae_v_sub(&tmpx.ptr.p_double[0], 1, &qx.ptr.pp_double[i][0], 1, ae_v_len(0,nx-1));
r = ae_maxreal(r, testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state), _state);
}
for(i=0; i<=n-1; i++)
{
if( tmpb.ptr.p_bool[i] )
{
ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1));
ae_v_sub(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1));
*kdterrors = *kdterrors||ae_fp_less(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state),r*(1-errtol));
}
}
for(i=0; i<=k-2; i++)
{
*kdterrors = *kdterrors||ae_fp_greater(qr.ptr.p_double[i],qr.ptr.p_double[i+1]);
}
for(i=0; i<=k-1; i++)
{
ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1));
ae_v_sub(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[qtags.ptr.p_int[i]][0], 1, ae_v_len(0,nx-1));
*kdterrors = *kdterrors||ae_fp_greater(ae_fabs(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state)-qr.ptr.p_double[i], _state),errtol);
}
/*
* Test reallocation properties: functions must automatically
* resize array which is too small, but leave unchanged array which is
* too large.
*/
if( n>=2 )
{
/*
* First step: array is too small, two elements are required
*/
k = 2;
kx = kdtreequeryknn(&treex, &ptx, k, ae_true, _state);
kxy = kdtreequeryknn(&treexy, &ptx, k, ae_true, _state);
kt = kdtreequeryknn(&treext, &ptx, k, ae_true, _state);
if( (kx!=k||kxy!=k)||kt!=k )
{
*kdterrors = ae_true;
ae_frame_leave(_state);
return;
}
ae_matrix_set_length(&qx, 1, 1, _state);
ae_matrix_set_length(&qxy, 1, 1, _state);
ae_vector_set_length(&qtags, 1, _state);
ae_vector_set_length(&qr, 1, _state);
kdtreequeryresultsx(&treex, &qx, _state);
kdtreequeryresultsxy(&treexy, &qxy, _state);
kdtreequeryresultstags(&treext, &qtags, _state);
kdtreequeryresultsdistances(&treext, &qr, _state);
*kdterrors = *kdterrors||testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, k, nx, ny, _state);
/*
* Second step: array is one row larger than needed, so only first
* row is overwritten. Test it.
*/
k = 1;
kx = kdtreequeryknn(&treex, &ptx, k, ae_true, _state);
kxy = kdtreequeryknn(&treexy, &ptx, k, ae_true, _state);
kt = kdtreequeryknn(&treext, &ptx, k, ae_true, _state);
if( (kx!=k||kxy!=k)||kt!=k )
{
*kdterrors = ae_true;
ae_frame_leave(_state);
return;
}
for(i=0; i<=nx-1; i++)
{
qx.ptr.pp_double[1][i] = _state->v_nan;
}
for(i=0; i<=nx+ny-1; i++)
{
qxy.ptr.pp_double[1][i] = _state->v_nan;
}
qtags.ptr.p_int[1] = 999;
qr.ptr.p_double[1] = _state->v_nan;
kdtreequeryresultsx(&treex, &qx, _state);
kdtreequeryresultsxy(&treexy, &qxy, _state);
kdtreequeryresultstags(&treext, &qtags, _state);
kdtreequeryresultsdistances(&treext, &qr, _state);
*kdterrors = *kdterrors||testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, k, nx, ny, _state);
for(i=0; i<=nx-1; i++)
{
*kdterrors = *kdterrors||!ae_isnan(qx.ptr.pp_double[1][i], _state);
}
for(i=0; i<=nx+ny-1; i++)
{
*kdterrors = *kdterrors||!ae_isnan(qxy.ptr.pp_double[1][i], _state);
}
*kdterrors = *kdterrors||!(qtags.ptr.p_int[1]==999);
*kdterrors = *kdterrors||!ae_isnan(qr.ptr.p_double[1], _state);
}
/*
* Test reallocation properties: 'interactive' functions must allocate
* new array on each call.
*/
if( n>=2 )
{
/*
* On input array is either too small or too large
*/
for(k=1; k<=2; k++)
{
ae_assert(k==1||k==2, "KNN: internal error (unexpected K)!", _state);
kx = kdtreequeryknn(&treex, &ptx, k, ae_true, _state);
kxy = kdtreequeryknn(&treexy, &ptx, k, ae_true, _state);
kt = kdtreequeryknn(&treext, &ptx, k, ae_true, _state);
if( (kx!=k||kxy!=k)||kt!=k )
{
*kdterrors = ae_true;
ae_frame_leave(_state);
return;
}
ae_matrix_set_length(&qx, 3-k, 3-k, _state);
ae_matrix_set_length(&qxy, 3-k, 3-k, _state);
ae_vector_set_length(&qtags, 3-k, _state);
ae_vector_set_length(&qr, 3-k, _state);
kdtreequeryresultsxi(&treex, &qx, _state);
kdtreequeryresultsxyi(&treexy, &qxy, _state);
kdtreequeryresultstagsi(&treext, &qtags, _state);
kdtreequeryresultsdistancesi(&treext, &qr, _state);
*kdterrors = *kdterrors||testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, k, nx, ny, _state);
*kdterrors = (*kdterrors||qx.rows!=k)||qx.cols!=nx;
*kdterrors = (*kdterrors||qxy.rows!=k)||qxy.cols!=nx+ny;
*kdterrors = *kdterrors||qtags.cnt!=k;
*kdterrors = *kdterrors||qr.cnt!=k;
}
}
}
/*
* test general approximate K-NN queries (with self-matches):
* * compare results from different trees (must be equal) and
* check that correct (value,tag) pairs are returned
* * test results from XT tree - let R be radius of query result.
* then all points not in result must be not closer than R/(1+Eps).
*/
for(q=1; q<=qcount; q++)
{
/*
* Select K: 1..N
*/
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
k = 1+ae_randominteger(n, _state);
}
else
{
k = 1;
}
/*
* Select Eps
*/
eps = 0.5+ae_randomreal(_state);
/*
* Select point (either one of the points, or random)
*/
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
i = ae_randominteger(n, _state);
ae_v_move(&ptx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1));
}
else
{
for(i=0; i<=nx-1; i++)
{
ptx.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
}
/*
* Test functions which use internal buffer:
* * consistency of results from different queries
* * points in query are IN the R-sphere (or at the boundary),
* and points not in query are outside of the R-sphere (or at the boundary)
* * distances are correct and are ordered
*/
kx = kdtreequeryaknn(&treex, &ptx, k, ae_true, eps, _state);
kxy = kdtreequeryaknn(&treexy, &ptx, k, ae_true, eps, _state);
kt = kdtreequeryaknn(&treext, &ptx, k, ae_true, eps, _state);
if( (kx!=k||kxy!=k)||kt!=k )
{
*kdterrors = ae_true;
ae_frame_leave(_state);
return;
}
unsetrealmatrix(&qx, _state);
unsetrealmatrix(&qxy, _state);
unsetintegerarray(&qtags, _state);
unsetrealarray(&qr, _state);
kdtreequeryresultsxi(&treex, &qx, _state);
kdtreequeryresultsxyi(&treexy, &qxy, _state);
kdtreequeryresultstagsi(&treext, &qtags, _state);
kdtreequeryresultsdistancesi(&treext, &qr, _state);
*kdterrors = *kdterrors||testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, k, nx, ny, _state);
unsetrealmatrix(&qx, _state);
unsetrealmatrix(&qxy, _state);
unsetintegerarray(&qtags, _state);
unsetrealarray(&qr, _state);
kdtreequeryresultsx(&treex, &qx, _state);
kdtreequeryresultsxy(&treexy, &qxy, _state);
kdtreequeryresultstags(&treext, &qtags, _state);
kdtreequeryresultsdistances(&treext, &qr, _state);
*kdterrors = *kdterrors||testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, k, nx, ny, _state);
for(i=0; i<=n-1; i++)
{
tmpb.ptr.p_bool[i] = ae_true;
}
r = (double)(0);
for(i=0; i<=k-1; i++)
{
tmpb.ptr.p_bool[qtags.ptr.p_int[i]] = ae_false;
ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1));
ae_v_sub(&tmpx.ptr.p_double[0], 1, &qx.ptr.pp_double[i][0], 1, ae_v_len(0,nx-1));
r = ae_maxreal(r, testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state), _state);
}
for(i=0; i<=n-1; i++)
{
if( tmpb.ptr.p_bool[i] )
{
ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1));
ae_v_sub(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1));
*kdterrors = *kdterrors||ae_fp_less(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state),r*(1-errtol)/(1+eps));
}
}
for(i=0; i<=k-2; i++)
{
*kdterrors = *kdterrors||ae_fp_greater(qr.ptr.p_double[i],qr.ptr.p_double[i+1]);
}
for(i=0; i<=k-1; i++)
{
ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1));
ae_v_sub(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[qtags.ptr.p_int[i]][0], 1, ae_v_len(0,nx-1));
*kdterrors = *kdterrors||ae_fp_greater(ae_fabs(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state)-qr.ptr.p_double[i], _state),errtol);
}
/*
* Test functions which use external buffer:
* * create external request buffer, perform buffered request
* * reset status of internal buffer by performing 1-NN query, it is essential
* to test the fact that external buffer is used
* * check consistency of results from different queries
* * check that points in query are IN the R-sphere (or at the boundary),
* and points not in query are outside of the R-sphere (or at the boundary)
* * check that distances are correct and are ordered
*/
kdtreecreaterequestbuffer(&treex, &bufx, _state);
kdtreecreaterequestbuffer(&treexy, &bufxy, _state);
kdtreecreaterequestbuffer(&treext, &bufxt, _state);
kx = kdtreetsqueryaknn(&treex, &bufx, &ptx, k, ae_true, eps, _state);
kxy = kdtreetsqueryaknn(&treexy, &bufxy, &ptx, k, ae_true, eps, _state);
kt = kdtreetsqueryaknn(&treext, &bufxt, &ptx, k, ae_true, eps, _state);
kdtreequeryknn(&treex, &ptx, 1, ae_true, _state);
kdtreequeryknn(&treexy, &ptx, 1, ae_true, _state);
kdtreequeryknn(&treext, &ptx, 1, ae_true, _state);
if( (kx!=k||kxy!=k)||kt!=k )
{
*kdterrors = ae_true;
ae_frame_leave(_state);
return;
}
unsetrealmatrix(&qx, _state);
unsetrealmatrix(&qxy, _state);
unsetintegerarray(&qtags, _state);
unsetrealarray(&qr, _state);
kdtreetsqueryresultsx(&treex, &bufx, &qx, _state);
kdtreetsqueryresultsxy(&treexy, &bufxy, &qxy, _state);
kdtreetsqueryresultstags(&treext, &bufxt, &qtags, _state);
kdtreetsqueryresultsdistances(&treext, &bufxt, &qr, _state);
*kdterrors = *kdterrors||testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, k, nx, ny, _state);
for(i=0; i<=n-1; i++)
{
tmpb.ptr.p_bool[i] = ae_true;
}
r = (double)(0);
for(i=0; i<=k-1; i++)
{
tmpb.ptr.p_bool[qtags.ptr.p_int[i]] = ae_false;
ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1));
ae_v_sub(&tmpx.ptr.p_double[0], 1, &qx.ptr.pp_double[i][0], 1, ae_v_len(0,nx-1));
r = ae_maxreal(r, testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state), _state);
}
for(i=0; i<=n-1; i++)
{
if( tmpb.ptr.p_bool[i] )
{
ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1));
ae_v_sub(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1));
*kdterrors = *kdterrors||ae_fp_less(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state),r*(1-errtol)/(1+eps));
}
}
for(i=0; i<=k-2; i++)
{
*kdterrors = *kdterrors||ae_fp_greater(qr.ptr.p_double[i],qr.ptr.p_double[i+1]);
}
for(i=0; i<=k-1; i++)
{
ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1));
ae_v_sub(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[qtags.ptr.p_int[i]][0], 1, ae_v_len(0,nx-1));
*kdterrors = *kdterrors||ae_fp_greater(ae_fabs(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state)-qr.ptr.p_double[i], _state),errtol);
}
}
/*
* test ordered/unordered R-NN queries (with self-matches):
* * compare results from different trees (must be equal) and
* check that correct (value,tag) pairs are returned
* * test results from XT tree - let R be radius of query result.
* then all points not in result must be not closer than R.
*/
for(q=1; q<=qcount; q++)
{
/*
* Use ordering?
*/
orderedrnn = ae_fp_greater(ae_randomreal(_state),0.5);
/*
* Select R
*/
if( ae_fp_greater(ae_randomreal(_state),0.3) )
{
r = ae_maxreal(ae_randomreal(_state), ae_machineepsilon, _state);
}
else
{
r = ae_machineepsilon;
}
/*
* Select point (either one of the points, or random)
*/
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
i = ae_randominteger(n, _state);
ae_v_move(&ptx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1));
}
else
{
for(i=0; i<=nx-1; i++)
{
ptx.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
}
/*
* Test functions which use internal buffer:
* * consistency of results from different queries
* * points in query are IN the R-sphere (or at the boundary),
* and points not in query are outside of the R-sphere (or at the boundary)
* * distances are correct and are ordered
*/
if( orderedrnn )
{
kx = kdtreequeryrnn(&treex, &ptx, r, ae_true, _state);
kxy = kdtreequeryrnn(&treexy, &ptx, r, ae_true, _state);
kt = kdtreequeryrnn(&treext, &ptx, r, ae_true, _state);
}
else
{
kx = kdtreequeryrnnu(&treex, &ptx, r, ae_true, _state);
kxy = kdtreequeryrnnu(&treexy, &ptx, r, ae_true, _state);
kt = kdtreequeryrnnu(&treext, &ptx, r, ae_true, _state);
}
if( kxy!=kx||kt!=kx )
{
ae_set_error_flag(kdterrors, ae_true, __FILE__, __LINE__, "testnearestneighborunit.ap:648");
ae_frame_leave(_state);
return;
}
unsetrealmatrix(&qx, _state);
unsetrealmatrix(&qxy, _state);
unsetintegerarray(&qtags, _state);
unsetrealarray(&qr, _state);
kdtreequeryresultsxi(&treex, &qx, _state);
kdtreequeryresultsxyi(&treexy, &qxy, _state);
kdtreequeryresultstagsi(&treext, &qtags, _state);
kdtreequeryresultsdistancesi(&treext, &qr, _state);
ae_set_error_flag(kdterrors, testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, kx, nx, ny, _state), __FILE__, __LINE__, "testnearestneighborunit.ap:659");
unsetrealmatrix(&qx, _state);
unsetrealmatrix(&qxy, _state);
unsetintegerarray(&qtags, _state);
unsetrealarray(&qr, _state);
kdtreequeryresultsx(&treex, &qx, _state);
kdtreequeryresultsxy(&treexy, &qxy, _state);
kdtreequeryresultstags(&treext, &qtags, _state);
kdtreequeryresultsdistances(&treext, &qr, _state);
ae_set_error_flag(kdterrors, testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, kx, nx, ny, _state), __FILE__, __LINE__, "testnearestneighborunit.ap:668");
for(i=0; i<=n-1; i++)
{
tmpb.ptr.p_bool[i] = ae_true;
}
for(i=0; i<=kx-1; i++)
{
tmpb.ptr.p_bool[qtags.ptr.p_int[i]] = ae_false;
}
for(i=0; i<=n-1; i++)
{
ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1));
ae_v_sub(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1));
if( tmpb.ptr.p_bool[i] )
{
ae_set_error_flag(kdterrors, ae_fp_less(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state),r*(1-errtol)), __FILE__, __LINE__, "testnearestneighborunit.ap:678");
}
else
{
ae_set_error_flag(kdterrors, ae_fp_greater(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state),r*(1+errtol)), __FILE__, __LINE__, "testnearestneighborunit.ap:680");
}
}
if( orderedrnn )
{
for(i=0; i<=kx-2; i++)
{
ae_set_error_flag(kdterrors, ae_fp_greater(qr.ptr.p_double[i],qr.ptr.p_double[i+1]), __FILE__, __LINE__, "testnearestneighborunit.ap:685");
}
}
/*
* Test functions which use external buffer:
* * create external request buffer, perform buffered request
* * reset status of internal buffer by performing 1-NN query, it is essential
* to test the fact that external buffer is used
* * check consistency of results from different queries
* * check that points in query are IN the R-sphere (or at the boundary),
* and points not in query are outside of the R-sphere (or at the boundary)
* * check that distances are correct and are ordered
*/
kdtreecreaterequestbuffer(&treex, &bufx, _state);
kdtreecreaterequestbuffer(&treexy, &bufxy, _state);
kdtreecreaterequestbuffer(&treext, &bufxt, _state);
if( orderedrnn )
{
kx = kdtreetsqueryrnn(&treex, &bufx, &ptx, r, ae_true, _state);
kxy = kdtreetsqueryrnn(&treexy, &bufxy, &ptx, r, ae_true, _state);
kt = kdtreetsqueryrnn(&treext, &bufxt, &ptx, r, ae_true, _state);
}
else
{
kx = kdtreetsqueryrnnu(&treex, &bufx, &ptx, r, ae_true, _state);
kxy = kdtreetsqueryrnnu(&treexy, &bufxy, &ptx, r, ae_true, _state);
kt = kdtreetsqueryrnnu(&treext, &bufxt, &ptx, r, ae_true, _state);
}
kdtreequeryknn(&treex, &ptx, 1, ae_true, _state);
kdtreequeryknn(&treexy, &ptx, 1, ae_true, _state);
kdtreequeryknn(&treext, &ptx, 1, ae_true, _state);
if( kxy!=kx||kt!=kx )
{
ae_set_error_flag(kdterrors, ae_true, __FILE__, __LINE__, "testnearestneighborunit.ap:718");
ae_frame_leave(_state);
return;
}
unsetrealmatrix(&qx, _state);
unsetrealmatrix(&qxy, _state);
unsetintegerarray(&qtags, _state);
unsetrealarray(&qr, _state);
kdtreetsqueryresultsx(&treex, &bufx, &qx, _state);
kdtreetsqueryresultsxy(&treexy, &bufxy, &qxy, _state);
kdtreetsqueryresultstags(&treext, &bufxt, &qtags, _state);
kdtreetsqueryresultsdistances(&treext, &bufxt, &qr, _state);
ae_set_error_flag(kdterrors, testnearestneighborunit_kdtresultsdifferent(xy, n, &qx, &qxy, &qtags, kx, nx, ny, _state), __FILE__, __LINE__, "testnearestneighborunit.ap:729");
for(i=0; i<=n-1; i++)
{
tmpb.ptr.p_bool[i] = ae_true;
}
for(i=0; i<=kx-1; i++)
{
tmpb.ptr.p_bool[qtags.ptr.p_int[i]] = ae_false;
}
for(i=0; i<=n-1; i++)
{
ae_v_move(&tmpx.ptr.p_double[0], 1, &ptx.ptr.p_double[0], 1, ae_v_len(0,nx-1));
ae_v_sub(&tmpx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1));
if( tmpb.ptr.p_bool[i] )
{
ae_set_error_flag(kdterrors, ae_fp_less(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state),r*(1-errtol)), __FILE__, __LINE__, "testnearestneighborunit.ap:739");
}
else
{
ae_set_error_flag(kdterrors, ae_fp_greater(testnearestneighborunit_vnorm(&tmpx, nx, normtype, _state),r*(1+errtol)), __FILE__, __LINE__, "testnearestneighborunit.ap:741");
}
}
if( orderedrnn )
{
for(i=0; i<=kx-2; i++)
{
ae_set_error_flag(kdterrors, ae_fp_greater(qr.ptr.p_double[i],qr.ptr.p_double[i+1]), __FILE__, __LINE__, "testnearestneighborunit.ap:746");
}
}
}
/*
* test box queries
*/
ae_vector_set_length(&qmin, nx, _state);
ae_vector_set_length(&qmax, nx, _state);
for(q=1; q<=qcount; q++)
{
/*
* Test for box exactly equal to one of the points.
* More than one exactly equal point may be found.
* Only thread-safe version is tested.
*/
kdtreecreaterequestbuffer(&treext, &bufxt, _state);
k = ae_randominteger(n, _state);
for(j=0; j<=nx-1; j++)
{
qmin.ptr.p_double[j] = xy->ptr.pp_double[k][j];
qmax.ptr.p_double[j] = xy->ptr.pp_double[k][j];
}
kx = kdtreetsquerybox(&treext, &bufxt, &qmin, &qmax, _state);
if( kx<1 )
{
*kdterrors = ae_true;
ae_frame_leave(_state);
return;
}
unsetrealmatrix(&qx, _state);
unsetintegerarray(&qtags, _state);
unsetrealarray(&qr, _state);
kdtreetsqueryresultsx(&treext, &bufxt, &qx, _state);
kdtreetsqueryresultstags(&treext, &bufxt, &qtags, _state);
kdtreetsqueryresultsdistances(&treext, &bufxt, &qr, _state);
for(i=0; i<=kx-1; i++)
{
ae_set_error_flag(kdterrors, ae_fp_neq(qr.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testnearestneighborunit.ap:783");
}
for(i=0; i<=kx-1; i++)
{
for(j=0; j<=nx-1; j++)
{
ae_set_error_flag(kdterrors, ae_fp_neq(qx.ptr.pp_double[i][j],xy->ptr.pp_double[k][j]), __FILE__, __LINE__, "testnearestneighborunit.ap:788");
ae_set_error_flag(kdterrors, ae_fp_neq(qx.ptr.pp_double[i][j],xy->ptr.pp_double[qtags.ptr.p_int[i]][j]), __FILE__, __LINE__, "testnearestneighborunit.ap:789");
}
}
/*
* Test for randomly generated box (thread-safe version)
*/
for(j=0; j<=nx-1; j++)
{
qmin.ptr.p_double[j] = boxmin.ptr.p_double[j]+ae_randomreal(_state)*(boxmax.ptr.p_double[j]-boxmin.ptr.p_double[j]);
qmax.ptr.p_double[j] = qmin.ptr.p_double[j];
v = spread*ae_pow((double)(10), -2*ae_randomreal(_state), _state);
qmin.ptr.p_double[j] = qmin.ptr.p_double[j]-v;
qmax.ptr.p_double[j] = qmax.ptr.p_double[j]+v;
}
kx = kdtreetsquerybox(&treext, &bufxt, &qmin, &qmax, _state);
unsetrealmatrix(&qx, _state);
unsetintegerarray(&qtags, _state);
unsetrealarray(&qr, _state);
kdtreetsqueryresultsx(&treext, &bufxt, &qx, _state);
kdtreetsqueryresultstags(&treext, &bufxt, &qtags, _state);
kdtreetsqueryresultsdistances(&treext, &bufxt, &qr, _state);
for(i=0; i<=kx-1; i++)
{
ae_set_error_flag(kdterrors, ae_fp_neq(qr.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testnearestneighborunit.ap:812");
}
for(i=0; i<=n-1; i++)
{
tmpb.ptr.p_bool[i] = ae_false;
}
for(i=0; i<=kx-1; i++)
{
tmpb.ptr.p_bool[qtags.ptr.p_int[i]] = ae_true;
}
for(i=0; i<=n-1; i++)
{
inthebox = ae_true;
for(j=0; j<=nx-1; j++)
{
inthebox = inthebox&&ae_fp_greater_eq(xy->ptr.pp_double[i][j],qmin.ptr.p_double[j]);
inthebox = inthebox&&ae_fp_less_eq(xy->ptr.pp_double[i][j],qmax.ptr.p_double[j]);
}
if( tmpb.ptr.p_bool[i] )
{
ae_set_error_flag(kdterrors, !inthebox, __FILE__, __LINE__, "testnearestneighborunit.ap:826");
}
else
{
ae_set_error_flag(kdterrors, inthebox, __FILE__, __LINE__, "testnearestneighborunit.ap:828");
}
}
/*
* Test for randomly generated box (non-thread-safe version)
*/
for(j=0; j<=nx-1; j++)
{
qmin.ptr.p_double[j] = boxmin.ptr.p_double[j]+ae_randomreal(_state)*(boxmax.ptr.p_double[j]-boxmin.ptr.p_double[j]);
qmax.ptr.p_double[j] = qmin.ptr.p_double[j];
v = spread*ae_pow((double)(10), -2*ae_randomreal(_state), _state);
qmin.ptr.p_double[j] = qmin.ptr.p_double[j]-v;
qmax.ptr.p_double[j] = qmax.ptr.p_double[j]+v;
}
kx = kdtreequerybox(&treext, &qmin, &qmax, _state);
unsetrealmatrix(&qx, _state);
unsetintegerarray(&qtags, _state);
unsetrealarray(&qr, _state);
kdtreequeryresultsx(&treext, &qx, _state);
kdtreequeryresultstags(&treext, &qtags, _state);
kdtreequeryresultsdistances(&treext, &qr, _state);
for(i=0; i<=kx-1; i++)
{
ae_set_error_flag(kdterrors, ae_fp_neq(qr.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testnearestneighborunit.ap:850");
}
for(i=0; i<=n-1; i++)
{
tmpb.ptr.p_bool[i] = ae_false;
}
for(i=0; i<=kx-1; i++)
{
tmpb.ptr.p_bool[qtags.ptr.p_int[i]] = ae_true;
}
for(i=0; i<=n-1; i++)
{
inthebox = ae_true;
for(j=0; j<=nx-1; j++)
{
inthebox = inthebox&&ae_fp_greater_eq(xy->ptr.pp_double[i][j],qmin.ptr.p_double[j]);
inthebox = inthebox&&ae_fp_less_eq(xy->ptr.pp_double[i][j],qmax.ptr.p_double[j]);
}
if( tmpb.ptr.p_bool[i] )
{
ae_set_error_flag(kdterrors, !inthebox, __FILE__, __LINE__, "testnearestneighborunit.ap:864");
}
else
{
ae_set_error_flag(kdterrors, inthebox, __FILE__, __LINE__, "testnearestneighborunit.ap:866");
}
}
}
/*
* Test self-matching:
* * self-match - nearest neighbor of each point in XY is the point itself
* * no self-match - nearest neighbor is NOT the point itself
*/
if( n>1 )
{
/*
* test for N=1 have non-general form, but it is not really needed
*/
for(task=0; task<=1; task++)
{
for(i=0; i<=n-1; i++)
{
ae_v_move(&ptx.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nx-1));
kx = kdtreequeryknn(&treex, &ptx, 1, task==0, _state);
kdtreequeryresultsxi(&treex, &qx, _state);
if( kx!=1 )
{
*kdterrors = ae_true;
ae_frame_leave(_state);
return;
}
isequal = ae_true;
for(j=0; j<=nx-1; j++)
{
isequal = isequal&&ae_fp_eq(qx.ptr.pp_double[0][j],ptx.ptr.p_double[j]);
}
if( task==0 )
{
*kdterrors = *kdterrors||!isequal;
}
else
{
*kdterrors = *kdterrors||isequal;
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Testing serialization of KD trees
This function sets Err to True on errors, but leaves it unchanged on success
*************************************************************************/
static void testnearestneighborunit_testkdtreeserialization(ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t nx;
ae_int_t ny;
ae_int_t normtype;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t q;
ae_matrix xy;
ae_vector x;
ae_vector tags;
ae_vector qsizes;
double threshold;
kdtree tree0;
kdtree tree1;
ae_int_t k0;
ae_int_t k1;
ae_matrix xy0;
ae_matrix xy1;
ae_vector tags0;
ae_vector tags1;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
memset(&x, 0, sizeof(x));
memset(&tags, 0, sizeof(tags));
memset(&qsizes, 0, sizeof(qsizes));
memset(&tree0, 0, sizeof(tree0));
memset(&tree1, 0, sizeof(tree1));
memset(&xy0, 0, sizeof(xy0));
memset(&xy1, 0, sizeof(xy1));
memset(&tags0, 0, sizeof(tags0));
memset(&tags1, 0, sizeof(tags1));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tags, 0, DT_INT, _state, ae_true);
ae_vector_init(&qsizes, 0, DT_INT, _state, ae_true);
_kdtree_init(&tree0, _state, ae_true);
_kdtree_init(&tree1, _state, ae_true);
ae_matrix_init(&xy0, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy1, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tags0, 0, DT_INT, _state, ae_true);
ae_vector_init(&tags1, 0, DT_INT, _state, ae_true);
threshold = 100*ae_machineepsilon;
/*
* different N, NX, NY, NormType
*/
n = 1;
while(n<=51)
{
/*
* prepare array with query sizes
*/
ae_vector_set_length(&qsizes, 4, _state);
qsizes.ptr.p_int[0] = 1;
qsizes.ptr.p_int[1] = ae_minint(2, n, _state);
qsizes.ptr.p_int[2] = ae_minint(4, n, _state);
qsizes.ptr.p_int[3] = n;
/*
* different NX/NY/NormType
*/
for(nx=1; nx<=2; nx++)
{
for(ny=0; ny<=2; ny++)
{
for(normtype=0; normtype<=2; normtype++)
{
/*
* Prepare data
*/
ae_matrix_set_length(&xy, n, nx+ny, _state);
ae_vector_set_length(&tags, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=nx+ny-1; j++)
{
xy.ptr.pp_double[i][j] = ae_randomreal(_state);
}
tags.ptr.p_int[i] = ae_randominteger(100, _state);
}
/*
* Build tree, pass it through serializer
*/
kdtreebuildtagged(&xy, &tags, n, nx, ny, normtype, &tree0, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
kdtreealloc(&_local_serializer, &tree0, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
kdtreeserialize(&_local_serializer, &tree0, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
kdtreeunserialize(&_local_serializer, &tree1, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
/*
* For each point of XY we make queries with different sizes
*/
ae_vector_set_length(&x, nx, _state);
for(k=0; k<=n-1; k++)
{
for(q=0; q<=qsizes.cnt-1; q++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xy.ptr.pp_double[k][0], 1, ae_v_len(0,nx-1));
k0 = kdtreequeryknn(&tree0, &x, qsizes.ptr.p_int[q], ae_true, _state);
k1 = kdtreequeryknn(&tree1, &x, qsizes.ptr.p_int[q], ae_true, _state);
if( k0!=k1 )
{
*err = ae_true;
ae_frame_leave(_state);
return;
}
kdtreequeryresultsxy(&tree0, &xy0, _state);
kdtreequeryresultsxy(&tree1, &xy1, _state);
for(i=0; i<=k0-1; i++)
{
for(j=0; j<=nx+ny-1; j++)
{
if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[i][j]-xy1.ptr.pp_double[i][j], _state),threshold) )
{
*err = ae_true;
ae_frame_leave(_state);
return;
}
}
}
kdtreequeryresultstags(&tree0, &tags0, _state);
kdtreequeryresultstags(&tree1, &tags1, _state);
for(i=0; i<=k0-1; i++)
{
if( tags0.ptr.p_int[i]!=tags1.ptr.p_int[i] )
{
*err = ae_true;
ae_frame_leave(_state);
return;
}
}
}
}
}
}
}
/*
* Next N
*/
n = n+25;
}
ae_frame_leave(_state);
}
/*************************************************************************
This function tests different special cases:
* Kd-tree for a zero number of points
* Kd-tree for array with a lot of duplicates (early versions of ALGLIB
raised stack overflow on such datasets)
It returns True on errors, False on success.
*************************************************************************/
static ae_bool testnearestneighborunit_testspecialcases(ae_state *_state)
{
ae_frame _frame_block;
kdtree kdt;
ae_matrix xy;
ae_vector tags;
ae_vector x;
ae_int_t n;
ae_int_t nk;
ae_int_t nx;
ae_int_t ny;
ae_int_t normtype;
ae_int_t i;
ae_int_t j;
double v;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&kdt, 0, sizeof(kdt));
memset(&xy, 0, sizeof(xy));
memset(&tags, 0, sizeof(tags));
memset(&x, 0, sizeof(x));
_kdtree_init(&kdt, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tags, 0, DT_INT, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
result = ae_false;
for(nx=1; nx<=3; nx++)
{
for(ny=0; ny<=3; ny++)
{
for(normtype=0; normtype<=2; normtype++)
{
/*
* Build tree
*/
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
kdtreebuildtagged(&xy, &tags, 0, nx, ny, normtype, &kdt, _state);
}
else
{
kdtreebuild(&xy, 0, nx, ny, normtype, &kdt, _state);
}
/*
* Test different queries
*/
ae_vector_set_length(&x, nx, _state);
for(i=0; i<=nx-1; i++)
{
x.ptr.p_double[i] = ae_randomreal(_state);
}
result = result||kdtreequeryknn(&kdt, &x, 1, ae_true, _state)>0;
result = result||kdtreequeryrnn(&kdt, &x, 1.0E6, ae_true, _state)>0;
result = result||kdtreequeryaknn(&kdt, &x, 1, ae_true, 2.0, _state)>0;
}
}
}
/*
* Ability to handle array with a lot of duplicates without causing
* stack overflow.
*
* Two situations are handled:
* * array where ALL N elements are duplicates
* * array where there are NK distinct elements and N-NK duplicates
*/
nx = 2;
ny = 1;
n = 100000;
nk = 100;
v = ae_randomreal(_state);
ae_matrix_set_length(&xy, n, nx+ny, _state);
ae_vector_set_length(&x, nx, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=nx+ny-1; j++)
{
xy.ptr.pp_double[i][j] = v;
}
}
kdtreebuild(&xy, n, nx, ny, 2, &kdt, _state);
for(j=0; j<=nx-1; j++)
{
x.ptr.p_double[j] = v;
}
result = result||kdtreequeryrnn(&kdt, &x, 0.0001, ae_true, _state)!=n;
for(i=0; i<=nk-1; i++)
{
for(j=0; j<=nx+ny-1; j++)
{
xy.ptr.pp_double[i][j] = ae_randomreal(_state);
}
}
kdtreebuild(&xy, n, nx, ny, 2, &kdt, _state);
result = result||kdtreequeryrnn(&kdt, &x, 0.0001, ae_true, _state)=bins.cnt )
{
k = bins.cnt-1;
}
bins.ptr.p_int[k] = bins.ptr.p_int[k]+1;
}
for(i=0; i<=bins.cnt-1; i++)
{
ae_set_error_flag(&unit2errors, ae_fp_less((double)(bins.ptr.p_int[i]),0.9*n/bins.cnt)||ae_fp_greater((double)(bins.ptr.p_int[i]),1.1*n/bins.cnt), __FILE__, __LINE__, "testhqrndunit.ap:250");
}
/*
* Test exponential
*/
testhqrndunit_unsetstate(&state, _state);
hqrndrandomize(&state, _state);
expsigmaerr = (double)(0);
lambdav = 2+5*ae_randomreal(_state);
for(i=0; i<=samplesize-1; i++)
{
x.ptr.p_double[i] = hqrndexponential(&state, lambdav, _state);
}
for(i=0; i<=samplesize-1; i++)
{
uierrors = uierrors||ae_fp_less(x.ptr.p_double[i],(double)(0));
}
testhqrndunit_calculatemv(&x, samplesize, &mean, &means, &stddev, &stddevs, _state);
if( ae_fp_neq(means,(double)(0)) )
{
expsigmaerr = ae_maxreal(expsigmaerr, ae_fabs((mean-1.0/lambdav)/means, _state), _state);
}
else
{
experrors = ae_true;
}
if( ae_fp_neq(stddevs,(double)(0)) )
{
expsigmaerr = ae_maxreal(expsigmaerr, ae_fabs((stddev-1.0/lambdav)/stddevs, _state), _state);
}
else
{
experrors = ae_true;
}
experrors = experrors||ae_fp_greater(expsigmaerr,sigmathreshold);
/*
*Discrete/Continuous tests
*/
discreteerr = hqrnddiscretetest(ae_true, _state);
continuouserr = hqrndcontinuoustest(ae_true, _state);
/*
* Final report
*/
waserrors = ((((((seederrors||urerrors)||uierrors)||normerrors)||unit2errors)||experrors)||discreteerr)||continuouserr;
if( !silent )
{
printf("RNG TEST\n");
printf("SEED TEST: ");
if( !seederrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("UNIFORM CONTINUOUS: ");
if( !urerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("UNIFORM INTEGER: ");
if( !uierrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("NORMAL: ");
if( !normerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("UNIT2: ");
if( !unit2errors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("EXPONENTIAL: ");
if( !experrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("DISCRETE: ");
if( !discreteerr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("CONTINUOUS: ");
if( !continuouserr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST SUMMARY: FAILED\n");
}
else
{
printf("TEST SUMMARY: PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Function for test HQRNDContinuous function
*************************************************************************/
ae_bool hqrndcontinuoustest(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_vector sample;
ae_vector bins;
ae_vector binbounds;
ae_int_t nb;
ae_int_t samplesize;
hqrndstate state;
ae_int_t xp;
ae_int_t i;
ae_int_t j;
double v;
double sigma;
double sigmamax;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&sample, 0, sizeof(sample));
memset(&bins, 0, sizeof(bins));
memset(&binbounds, 0, sizeof(binbounds));
memset(&state, 0, sizeof(state));
ae_vector_init(&sample, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bins, 0, DT_INT, _state, ae_true);
ae_vector_init(&binbounds, 0, DT_REAL, _state, ae_true);
_hqrndstate_init(&state, _state, ae_true);
result = ae_false;
/*
* Test for sample size equal to 1
*/
ae_vector_set_length(&sample, 1, _state);
sample.ptr.p_double[0] = ae_randomreal(_state);
hqrndrandomize(&state, _state);
result = result||ae_fp_neq(hqrndcontinuous(&state, &sample, 1, _state),sample.ptr.p_double[0]);
/*
* Test for larger samples
*/
xp = 100000;
sigmamax = 10.0;
for(samplesize=2; samplesize<=5; samplesize++)
{
/*
* 1. Generate random sample with SampleSize points
* 2. Generate NB=3*(SampleSize-1) bins, with bounds as prescribed by (BinBounds[I],BinBounds[I+1]).
* Bin bounds are generated in such a way that value can fall into any bin with same probability
* 3. Generate many random values
* 4. Calculate number of values which fall into each bin
* 5. Bins[I] should have binomial distribution with mean XP/NB and
* variance XP*(1/NB)*(1-1/NB)
*/
nb = 3*(samplesize-1);
sigma = ae_sqrt(xp*((double)1/(double)nb)*(1-(double)1/(double)nb), _state);
ae_vector_set_length(&sample, samplesize, _state);
sample.ptr.p_double[0] = 2*ae_randomreal(_state)-1;
for(i=0; i<=samplesize-2; i++)
{
sample.ptr.p_double[i+1] = sample.ptr.p_double[i]+0.1+ae_randomreal(_state);
}
ae_vector_set_length(&bins, nb, _state);
ae_vector_set_length(&binbounds, nb+1, _state);
for(i=0; i<=samplesize-2; i++)
{
bins.ptr.p_int[3*i+0] = 0;
bins.ptr.p_int[3*i+1] = 0;
bins.ptr.p_int[3*i+2] = 0;
binbounds.ptr.p_double[3*i+0] = sample.ptr.p_double[i];
binbounds.ptr.p_double[3*i+1] = sample.ptr.p_double[i]+(sample.ptr.p_double[i+1]-sample.ptr.p_double[i])/3;
binbounds.ptr.p_double[3*i+2] = sample.ptr.p_double[i]+(sample.ptr.p_double[i+1]-sample.ptr.p_double[i])*2/3;
}
binbounds.ptr.p_double[nb] = sample.ptr.p_double[samplesize-1];
hqrndrandomize(&state, _state);
for(i=0; i<=xp-1; i++)
{
v = hqrndcontinuous(&state, &sample, samplesize, _state);
for(j=0; j<=nb-1; j++)
{
if( ae_fp_greater(v,binbounds.ptr.p_double[j])&&ae_fp_less(v,binbounds.ptr.p_double[j+1]) )
{
bins.ptr.p_int[j] = bins.ptr.p_int[j]+1;
break;
}
}
}
for(i=0; i<=nb-1; i++)
{
result = result||ae_fp_greater(ae_fabs(bins.ptr.p_int[i]-(double)xp/(double)nb, _state),sigma*sigmamax);
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Function for test HQRNDContinuous function
*************************************************************************/
ae_bool hqrnddiscretetest(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_vector sample;
double sigma;
double sigmathreshold;
double tsample;
double max;
double min;
ae_int_t i;
ae_int_t j;
ae_int_t s1;
ae_int_t s2;
ae_int_t binscount;
ae_int_t xp;
ae_vector nn;
hqrndstate state;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&sample, 0, sizeof(sample));
memset(&nn, 0, sizeof(nn));
memset(&state, 0, sizeof(state));
ae_vector_init(&sample, 0, DT_REAL, _state, ae_true);
ae_vector_init(&nn, 0, DT_INT, _state, ae_true);
_hqrndstate_init(&state, _state, ae_true);
/*
* We test that all values from discrete sample are generated with same probability.
* To do this, we generate random values many times, then we calculate actual probabilities
* and compare them with theoretical ones.
*/
max = (double)(100);
min = (double)(-100);
xp = 100000;
sigmathreshold = 10.0;
for(binscount=1; binscount<=5; binscount++)
{
sigma = ae_sqrt(xp*((double)1/(double)binscount)*(1-(double)1/(double)binscount), _state);
ae_vector_set_length(&nn, binscount, _state);
for(i=0; i<=binscount-1; i++)
{
nn.ptr.p_int[i] = 0;
}
ae_vector_set_length(&sample, binscount, _state);
sample.ptr.p_double[0] = (max-min)*ae_randomreal(_state)+min;
for(i=1; i<=binscount-1; i++)
{
sample.ptr.p_double[i] = sample.ptr.p_double[i-1]+max*ae_randomreal(_state)+0.001;
}
s1 = 1+ae_randominteger(32000, _state);
s2 = 1+ae_randominteger(32000, _state);
hqrndseed(s1, s2, &state, _state);
for(i=0; i<=xp-1; i++)
{
tsample = hqrnddiscrete(&state, &sample, binscount, _state);
for(j=0; j<=binscount-1; j++)
{
if( ae_fp_eq(tsample,sample.ptr.p_double[j]) )
{
nn.ptr.p_int[j] = nn.ptr.p_int[j]+1;
break;
}
}
}
for(i=0; i<=binscount-1; i++)
{
if( ae_fp_less((double)(nn.ptr.p_int[i]),(double)xp/(double)binscount-sigmathreshold*sigma)||ae_fp_greater((double)(nn.ptr.p_int[i]),(double)xp/(double)binscount+sigmathreshold*sigma) )
{
if( !silent )
{
printf("HQRNDDiscreteTest::ErrorReport::\n");
printf("nn[%0d]=%0d;\n xp/BinsCount=%0.5f;\n C*sigma=%0.5f\n",
(int)(i),
(int)(nn.ptr.p_int[i]),
(double)((double)xp/(double)binscount),
(double)(sigmathreshold*sigma));
printf("HQRNDDiscreteTest: test is FAILED!\n");
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
if( !silent )
{
printf("HQRNDDiscreteTest: test is OK.\n");
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
static void testhqrndunit_calculatemv(/* Real */ ae_vector* x,
ae_int_t n,
double* mean,
double* means,
double* stddev,
double* stddevs,
ae_state *_state)
{
ae_int_t i;
double v1;
double v2;
double variance;
*mean = 0;
*means = 0;
*stddev = 0;
*stddevs = 0;
*mean = (double)(0);
*means = (double)(1);
*stddev = (double)(0);
*stddevs = (double)(1);
variance = (double)(0);
if( n<=1 )
{
return;
}
/*
* Mean
*/
for(i=0; i<=n-1; i++)
{
*mean = *mean+x->ptr.p_double[i];
}
*mean = *mean/n;
/*
* Variance (using corrected two-pass algorithm)
*/
if( n!=1 )
{
v1 = (double)(0);
for(i=0; i<=n-1; i++)
{
v1 = v1+ae_sqr(x->ptr.p_double[i]-(*mean), _state);
}
v2 = (double)(0);
for(i=0; i<=n-1; i++)
{
v2 = v2+(x->ptr.p_double[i]-(*mean));
}
v2 = ae_sqr(v2, _state)/n;
variance = (v1-v2)/(n-1);
if( ae_fp_less(variance,(double)(0)) )
{
variance = (double)(0);
}
*stddev = ae_sqrt(variance, _state);
}
/*
* Errors
*/
*means = *stddev/ae_sqrt((double)(n), _state);
*stddevs = *stddev*ae_sqrt((double)(2), _state)/ae_sqrt((double)(n-1), _state);
}
/*************************************************************************
Unsets HQRNDState structure
*************************************************************************/
static void testhqrndunit_unsetstate(hqrndstate* state, ae_state *_state)
{
state->s1 = 0;
state->s2 = 0;
state->magicv = 0;
}
/*************************************************************************
Test
*************************************************************************/
ae_bool testodesolver(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t passcount;
ae_bool curerrors;
ae_bool rkckerrors;
ae_bool waserrors;
ae_vector xtbl;
ae_matrix ytbl;
odesolverreport rep;
ae_vector xg;
ae_vector y;
double h;
double eps;
ae_int_t solver;
ae_int_t pass;
ae_int_t mynfev;
double v;
ae_int_t m;
ae_int_t m2;
ae_int_t i;
double err;
odesolverstate state;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&xtbl, 0, sizeof(xtbl));
memset(&ytbl, 0, sizeof(ytbl));
memset(&rep, 0, sizeof(rep));
memset(&xg, 0, sizeof(xg));
memset(&y, 0, sizeof(y));
memset(&state, 0, sizeof(state));
ae_vector_init(&xtbl, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ytbl, 0, 0, DT_REAL, _state, ae_true);
_odesolverreport_init(&rep, _state, ae_true);
ae_vector_init(&xg, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
_odesolverstate_init(&state, _state, ae_true);
rkckerrors = ae_false;
waserrors = ae_false;
passcount = 10;
/*
* simple test: just A*sin(x)+B*cos(x)
*/
ae_assert(passcount>=2, "Assertion failed", _state);
for(pass=0; pass<=passcount-1; pass++)
{
for(solver=0; solver<=0; solver++)
{
/*
* prepare
*/
h = 1.0E-2;
eps = 1.0E-5;
if( pass%2==0 )
{
eps = -eps;
}
ae_vector_set_length(&y, 2, _state);
for(i=0; i<=1; i++)
{
y.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
m = 2+ae_randominteger(10, _state);
ae_vector_set_length(&xg, m, _state);
xg.ptr.p_double[0] = (m-1)*ae_randomreal(_state);
for(i=1; i<=m-1; i++)
{
xg.ptr.p_double[i] = xg.ptr.p_double[i-1]+ae_randomreal(_state);
}
v = 2*ae_pi/(xg.ptr.p_double[m-1]-xg.ptr.p_double[0]);
ae_v_muld(&xg.ptr.p_double[0], 1, ae_v_len(0,m-1), v);
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
ae_v_muld(&xg.ptr.p_double[0], 1, ae_v_len(0,m-1), -1);
}
mynfev = 0;
/*
* choose solver
*/
if( solver==0 )
{
odesolverrkck(&y, 2, &xg, m, eps, h, &state, _state);
}
/*
* solve
*/
while(odesolveriteration(&state, _state))
{
state.dy.ptr.p_double[0] = state.y.ptr.p_double[1];
state.dy.ptr.p_double[1] = -state.y.ptr.p_double[0];
mynfev = mynfev+1;
}
odesolverresults(&state, &m2, &xtbl, &ytbl, &rep, _state);
/*
* check results
*/
curerrors = ae_false;
if( rep.terminationtype<=0 )
{
curerrors = ae_true;
}
else
{
curerrors = curerrors||m2!=m;
err = (double)(0);
for(i=0; i<=m-1; i++)
{
err = ae_maxreal(err, ae_fabs(ytbl.ptr.pp_double[i][0]-(y.ptr.p_double[0]*ae_cos(xtbl.ptr.p_double[i]-xtbl.ptr.p_double[0], _state)+y.ptr.p_double[1]*ae_sin(xtbl.ptr.p_double[i]-xtbl.ptr.p_double[0], _state)), _state), _state);
err = ae_maxreal(err, ae_fabs(ytbl.ptr.pp_double[i][1]-(-y.ptr.p_double[0]*ae_sin(xtbl.ptr.p_double[i]-xtbl.ptr.p_double[0], _state)+y.ptr.p_double[1]*ae_cos(xtbl.ptr.p_double[i]-xtbl.ptr.p_double[0], _state)), _state), _state);
}
curerrors = curerrors||ae_fp_greater(err,10*ae_fabs(eps, _state));
curerrors = curerrors||mynfev!=rep.nfev;
}
if( solver==0 )
{
rkckerrors = rkckerrors||curerrors;
}
}
}
/*
* another test:
*
* y(0) = 0
* dy/dx = f(x,y)
* f(x,y) = 0, x<1
* x-1, x>=1
*
* with BOTH absolute and fractional tolerances.
* Starting from zero will be real challenge for
* fractional tolerance.
*/
ae_assert(passcount>=2, "Assertion failed", _state);
for(pass=0; pass<=passcount-1; pass++)
{
h = 1.0E-4;
eps = 1.0E-4;
if( pass%2==0 )
{
eps = -eps;
}
ae_vector_set_length(&y, 1, _state);
y.ptr.p_double[0] = (double)(0);
m = 21;
ae_vector_set_length(&xg, m, _state);
for(i=0; i<=m-1; i++)
{
xg.ptr.p_double[i] = (double)(2*i)/(double)(m-1);
}
mynfev = 0;
odesolverrkck(&y, 1, &xg, m, eps, h, &state, _state);
while(odesolveriteration(&state, _state))
{
state.dy.ptr.p_double[0] = ae_maxreal(state.x-1, (double)(0), _state);
mynfev = mynfev+1;
}
odesolverresults(&state, &m2, &xtbl, &ytbl, &rep, _state);
if( rep.terminationtype<=0 )
{
rkckerrors = ae_true;
}
else
{
rkckerrors = rkckerrors||m2!=m;
err = (double)(0);
for(i=0; i<=m-1; i++)
{
err = ae_maxreal(err, ae_fabs(ytbl.ptr.pp_double[i][0]-ae_sqr(ae_maxreal(xg.ptr.p_double[i]-1, (double)(0), _state), _state)/2, _state), _state);
}
rkckerrors = rkckerrors||ae_fp_greater(err,ae_fabs(eps, _state));
rkckerrors = rkckerrors||mynfev!=rep.nfev;
}
}
/*
* end
*/
waserrors = rkckerrors;
if( !silent )
{
printf("TESTING ODE SOLVER\n");
printf("* RK CASH-KARP: ");
if( rkckerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
static void testsparseunit_initgenerator(ae_int_t m,
ae_int_t n,
ae_int_t matkind,
ae_int_t triangle,
sparsegenerator* g,
ae_state *_state);
static ae_bool testsparseunit_generatenext(sparsegenerator* g,
/* Real */ ae_matrix* da,
sparsematrix* sa,
ae_state *_state);
static void testsparseunit_createrandom(ae_int_t m,
ae_int_t n,
ae_int_t pkind,
ae_int_t ckind,
ae_int_t p0,
ae_int_t p1,
/* Real */ ae_matrix* da,
sparsematrix* sa,
ae_state *_state);
static ae_bool testsparseunit_enumeratetest(ae_state *_state);
static ae_bool testsparseunit_rewriteexistingtest(ae_state *_state);
static void testsparseunit_testgetrow(ae_bool* err, ae_state *_state);
static ae_bool testsparseunit_testconvertsm(ae_state *_state);
static ae_bool testsparseunit_testgcmatrixtype(ae_state *_state);
ae_bool testsparse(ae_bool silent, ae_state *_state)
{
ae_bool waserrors;
ae_bool basicerrors;
ae_bool linearerrors;
ae_bool basicrnderrors;
ae_bool level2unsymmetricerrors;
ae_bool level2symmetricerrors;
ae_bool level2triangularerrors;
ae_bool level3unsymmetricerrors;
ae_bool level3symmetricerrors;
ae_bool linearserrors;
ae_bool linearmmerrors;
ae_bool linearsmmerrors;
ae_bool getrowerrors;
ae_bool copyerrors;
ae_bool basiccopyerrors;
ae_bool enumerateerrors;
ae_bool rewriteexistingerr;
ae_bool skserrors;
ae_bool crserrors;
ae_bool result;
getrowerrors = ae_false;
crserrors = ae_false;
skserrors = skstest(_state);
crstest(&crserrors, _state);
basicerrors = basicfunctest(_state)||testsparseunit_testgcmatrixtype(_state);
basicrnderrors = basicfuncrandomtest(_state);
linearerrors = linearfunctionstest(_state);
level2unsymmetricerrors = testlevel2unsymmetric(_state);
level2symmetricerrors = testlevel2symmetric(_state);
level2triangularerrors = testlevel2triangular(_state);
level3unsymmetricerrors = testlevel3unsymmetric(_state);
level3symmetricerrors = testlevel3symmetric(_state);
linearserrors = linearfunctionsstest(_state);
linearmmerrors = linearfunctionsmmtest(_state);
linearsmmerrors = linearfunctionssmmtest(_state);
copyerrors = copyfunctest(ae_true, _state)||testsparseunit_testconvertsm(_state);
basiccopyerrors = basiccopyfunctest(ae_true, _state);
enumerateerrors = testsparseunit_enumeratetest(_state);
rewriteexistingerr = testsparseunit_rewriteexistingtest(_state);
testsparseunit_testgetrow(&getrowerrors, _state);
/*
* report
*/
waserrors = ((((((((((((((((skserrors||crserrors)||getrowerrors)||basicerrors)||linearerrors)||basicrnderrors)||level2unsymmetricerrors)||level2symmetricerrors)||level2triangularerrors)||level3unsymmetricerrors)||level3symmetricerrors)||linearserrors)||linearmmerrors)||linearsmmerrors)||copyerrors)||basiccopyerrors)||enumerateerrors)||rewriteexistingerr;
if( !silent )
{
printf("TESTING SPARSE\n");
printf("STORAGE FORMAT SPECIFICS:\n");
printf("* SKS: ");
if( !skserrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* CRS: ");
if( !crserrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("OPERATIONS:\n");
printf("* GETROW: ");
if( !getrowerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("BLAS:\n");
printf("* LEVEL 2 GENERAL: ");
if( !level2unsymmetricerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* LEVEL 2 SYMMETRIC: ");
if( !level2symmetricerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* LEVEL 2 TRIANGULAR: ");
if( !level2triangularerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* LEVEL 3 GENERAL: ");
if( !level3unsymmetricerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* LEVEL 3 SYMMETRIC: ");
if( !level3symmetricerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("BASIC TEST: ");
if( !basicerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("COPY TEST: ");
if( !copyerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("BASIC_COPY TEST: ");
if( !basiccopyerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("BASIC_RND TEST: ");
if( !basicrnderrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("LINEAR TEST: ");
if( !linearerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("LINEAR TEST FOR SYMMETRIC MATRICES: ");
if( !linearserrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("LINEAR MxM TEST: ");
if( !linearmmerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("LINEAR MxM TEST FOR SYMMETRIC MATRICES: ");
if( !linearsmmerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("ENUMERATE TEST: ");
if( !enumerateerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("REWRITE EXISTING TEST: ");
if( !rewriteexistingerr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
return result;
}
/*************************************************************************
Function for testing basic SKS functional.
Returns True on errors, False on success.
-- ALGLIB PROJECT --
Copyright 16.01.1014 by Bochkanov Sergey
*************************************************************************/
ae_bool skstest(ae_state *_state)
{
ae_frame _frame_block;
sparsematrix s0;
sparsematrix s1;
sparsematrix s2;
sparsematrix s3;
sparsematrix s4;
sparsematrix s5;
sparsematrix s6;
ae_int_t n;
ae_int_t nz;
double pnz;
ae_int_t i;
ae_int_t j;
ae_int_t t0;
ae_int_t t1;
ae_matrix a;
ae_matrix wasenumerated;
ae_vector d;
ae_vector u;
hqrndstate rs;
double v0;
double v1;
ae_int_t uppercnt;
ae_int_t lowercnt;
ae_int_t bw;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s0, 0, sizeof(s0));
memset(&s1, 0, sizeof(s1));
memset(&s2, 0, sizeof(s2));
memset(&s3, 0, sizeof(s3));
memset(&s4, 0, sizeof(s4));
memset(&s5, 0, sizeof(s5));
memset(&s6, 0, sizeof(s6));
memset(&a, 0, sizeof(a));
memset(&wasenumerated, 0, sizeof(wasenumerated));
memset(&d, 0, sizeof(d));
memset(&u, 0, sizeof(u));
memset(&rs, 0, sizeof(rs));
_sparsematrix_init(&s0, _state, ae_true);
_sparsematrix_init(&s1, _state, ae_true);
_sparsematrix_init(&s2, _state, ae_true);
_sparsematrix_init(&s3, _state, ae_true);
_sparsematrix_init(&s4, _state, ae_true);
_sparsematrix_init(&s5, _state, ae_true);
_sparsematrix_init(&s6, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&wasenumerated, 0, 0, DT_BOOL, _state, ae_true);
ae_vector_init(&d, 0, DT_INT, _state, ae_true);
ae_vector_init(&u, 0, DT_INT, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
result = ae_false;
hqrndrandomize(&rs, _state);
for(n=1; n<=20; n++)
{
nz = n*n-n;
for(;;)
{
/*
* Generate N*N matrix where probability of non-diagonal element
* being non-zero is PNZ. We also generate D and U - subdiagonal
* and superdiagonal profile sizes.
*
* Create matrix with either general SKS or banded SKS constructor function
*/
if( n>1 )
{
pnz = (double)nz/(double)(n*n-n);
}
else
{
pnz = 1.0;
}
ae_vector_set_length(&d, n, _state);
ae_vector_set_length(&u, n, _state);
ae_matrix_set_length(&a, n, n, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
/*
* Test SparseCreateSKS() functionality
*/
for(i=0; i<=n-1; i++)
{
d.ptr.p_int[i] = 0;
u.ptr.p_int[i] = 0;
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( i==j||ae_fp_less_eq(hqrnduniformr(&rs, _state),pnz) )
{
a.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5;
if( j=j&&i-j>d.ptr.p_int[i])||(i<=j&&j-i>u.ptr.p_int[j]) )
{
ae_set_error_flag(&result, sparserewriteexisting(&s0, i, j, 1.0, _state), __FILE__, __LINE__, "testsparseunit.ap:455");
}
}
}
/*
* Convert to several different formats, check their contents with SparseGet().
*/
sparsecopy(&s0, &s1, _state);
sparseconverttocrs(&s1, _state);
sparsecopytocrs(&s0, &s2, _state);
sparsecopytocrsbuf(&s0, &s3, _state);
sparsecopytohash(&s0, &s4, _state);
sparsecopytohashbuf(&s0, &s5, _state);
sparsecopy(&s0, &s6, _state);
sparseconverttohash(&s6, _state);
ae_set_error_flag(&result, sparsegetnrows(&s0, _state)!=n, __FILE__, __LINE__, "testsparseunit.ap:468");
ae_set_error_flag(&result, sparsegetncols(&s0, _state)!=n, __FILE__, __LINE__, "testsparseunit.ap:469");
ae_set_error_flag(&result, sparsegetmatrixtype(&s0, _state)!=2, __FILE__, __LINE__, "testsparseunit.ap:470");
ae_set_error_flag(&result, !sparseissks(&s0, _state), __FILE__, __LINE__, "testsparseunit.ap:471");
ae_set_error_flag(&result, sparseiscrs(&s0, _state), __FILE__, __LINE__, "testsparseunit.ap:472");
ae_set_error_flag(&result, sparseishash(&s0, _state), __FILE__, __LINE__, "testsparseunit.ap:473");
ae_set_error_flag(&result, sparseissks(&s1, _state), __FILE__, __LINE__, "testsparseunit.ap:474");
ae_set_error_flag(&result, !sparseiscrs(&s1, _state), __FILE__, __LINE__, "testsparseunit.ap:475");
ae_set_error_flag(&result, sparseishash(&s1, _state), __FILE__, __LINE__, "testsparseunit.ap:476");
for(i=0; i<=n-1; i++)
{
v1 = a.ptr.pp_double[i][i];
v0 = sparsegetdiagonal(&s0, i, _state);
ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:481");
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v1 = a.ptr.pp_double[i][j];
v0 = sparseget(&s0, i, j, _state);
ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:488");
v0 = sparseget(&s1, i, j, _state);
ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:490");
v0 = sparseget(&s2, i, j, _state);
ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:492");
v0 = sparseget(&s3, i, j, _state);
ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:494");
v0 = sparseget(&s4, i, j, _state);
ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:496");
v0 = sparseget(&s5, i, j, _state);
ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:498");
v0 = sparseget(&s6, i, j, _state);
ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:500");
}
}
/*
* Check enumeration capabilities:
* * each element returned by SparseEnumerate() is returned only once
* * each non-zero element of A was enumerated
*/
ae_matrix_set_length(&wasenumerated, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
wasenumerated.ptr.pp_bool[i][j] = ae_false;
}
}
t0 = 0;
t1 = 0;
while(sparseenumerate(&s0, &t0, &t1, &i, &j, &v0, _state))
{
ae_set_error_flag(&result, wasenumerated.ptr.pp_bool[i][j], __FILE__, __LINE__, "testsparseunit.ap:516");
wasenumerated.ptr.pp_bool[i][j] = ae_true;
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_neq(a.ptr.pp_double[i][j],(double)(0)) )
{
ae_set_error_flag(&result, !wasenumerated.ptr.pp_bool[i][j], __FILE__, __LINE__, "testsparseunit.ap:522");
}
}
}
/*
* Check UpperCnt()/LowerCnt()
*/
ae_set_error_flag(&result, sparsegetuppercount(&s0, _state)!=uppercnt, __FILE__, __LINE__, "testsparseunit.ap:527");
ae_set_error_flag(&result, sparsegetlowercount(&s0, _state)!=lowercnt, __FILE__, __LINE__, "testsparseunit.ap:528");
/*
* Check in-place transposition
*/
sparsecopy(&s0, &s1, _state);
sparsetransposesks(&s1, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v0 = sparseget(&s0, i, j, _state);
v1 = sparseget(&s1, j, i, _state);
ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:540");
}
}
/*
* One more check - matrix is initially created in some other format
* (CRS or Hash) and converted to SKS later.
*/
sparsecreate(n, n, 0, &s0, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_neq(a.ptr.pp_double[i][j],(double)(0)) )
{
sparseset(&s0, i, j, a.ptr.pp_double[i][j], _state);
}
}
}
sparsecopy(&s0, &s1, _state);
sparseconverttosks(&s1, _state);
sparsecopytosks(&s0, &s2, _state);
sparsecopytosksbuf(&s0, &s3, _state);
ae_set_error_flag(&result, !sparseissks(&s1, _state), __FILE__, __LINE__, "testsparseunit.ap:556");
ae_set_error_flag(&result, sparseiscrs(&s1, _state), __FILE__, __LINE__, "testsparseunit.ap:557");
ae_set_error_flag(&result, sparseishash(&s1, _state), __FILE__, __LINE__, "testsparseunit.ap:558");
ae_set_error_flag(&result, !sparseissks(&s2, _state), __FILE__, __LINE__, "testsparseunit.ap:559");
ae_set_error_flag(&result, sparseiscrs(&s2, _state), __FILE__, __LINE__, "testsparseunit.ap:560");
ae_set_error_flag(&result, sparseishash(&s2, _state), __FILE__, __LINE__, "testsparseunit.ap:561");
ae_set_error_flag(&result, !sparseissks(&s3, _state), __FILE__, __LINE__, "testsparseunit.ap:562");
ae_set_error_flag(&result, sparseiscrs(&s3, _state), __FILE__, __LINE__, "testsparseunit.ap:563");
ae_set_error_flag(&result, sparseishash(&s3, _state), __FILE__, __LINE__, "testsparseunit.ap:564");
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v1 = a.ptr.pp_double[i][j];
v0 = sparseget(&s1, i, j, _state);
ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:570");
v0 = sparseget(&s2, i, j, _state);
ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:572");
v0 = sparseget(&s3, i, j, _state);
ae_set_error_flag(&result, ae_fp_neq(v0,v1), __FILE__, __LINE__, "testsparseunit.ap:574");
}
}
/*
* Increase problem sparcity and try one more time.
* Stop after testing NZ=0.
*/
if( nz==0 )
{
break;
}
nz = ae_minint(ae_round(nz*0.95, _state), nz-1, _state);
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Function for testing CRS-specific functionality.
On failure sets ErrorFlag, on success does not touch it.
-- ALGLIB PROJECT --
Copyright 30.01.2018 by Bochkanov Sergey
*************************************************************************/
void crstest(ae_bool* errorflag, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t m;
ae_int_t nz;
double pnz;
hqrndstate rs;
sparsematrix s0;
sparsematrix s1;
sparsematrix s2;
sparsematrix s3;
sparsematrix s4;
ae_int_t i;
ae_int_t j;
ae_frame_make(_state, &_frame_block);
memset(&rs, 0, sizeof(rs));
memset(&s0, 0, sizeof(s0));
memset(&s1, 0, sizeof(s1));
memset(&s2, 0, sizeof(s2));
memset(&s3, 0, sizeof(s3));
memset(&s4, 0, sizeof(s4));
_hqrndstate_init(&rs, _state, ae_true);
_sparsematrix_init(&s0, _state, ae_true);
_sparsematrix_init(&s1, _state, ae_true);
_sparsematrix_init(&s2, _state, ae_true);
_sparsematrix_init(&s3, _state, ae_true);
_sparsematrix_init(&s4, _state, ae_true);
hqrndrandomize(&rs, _state);
for(n=1; n<=10; n++)
{
for(m=1; m<=10; m++)
{
nz = n*m;
for(;;)
{
/*
* Generate N*N matrix where probability of non-diagonal element
* being non-zero is PNZ. We also generate D and U - subdiagonal
* and superdiagonal profile sizes.
*
* Create matrix with either general SKS or banded SKS constructor function
*/
if( n>1 )
{
pnz = (double)nz/(double)(m*n);
}
else
{
pnz = 1.0;
}
/*
* Generate random matrix in HASH format, copy it to CRS format, compare with original
*/
sparsecreate(m, n, ae_round(nz*hqrnduniformr(&rs, _state), _state), &s0, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_less_eq(hqrnduniformr(&rs, _state),pnz) )
{
sparseset(&s0, i, j, hqrndnormal(&rs, _state), _state);
}
}
}
sparsecopytocrs(&s0, &s1, _state);
ae_set_error_flag(errorflag, !sparseiscrs(&s1, _state), __FILE__, __LINE__, "testsparseunit.ap:642");
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
ae_set_error_flag(errorflag, ae_fp_neq(sparseget(&s0, i, j, _state),sparseget(&s1, i, j, _state)), __FILE__, __LINE__, "testsparseunit.ap:645");
}
}
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
/*
* Check transposition
*/
sparsecopytocrs(&s1, &s2, _state);
sparsetransposecrs(&s2, _state);
ae_set_error_flag(errorflag, !sparseiscrs(&s2, _state), __FILE__, __LINE__, "testsparseunit.ap:654");
ae_set_error_flag(errorflag, sparsegetnrows(&s1, _state)!=sparsegetncols(&s2, _state), __FILE__, __LINE__, "testsparseunit.ap:655");
ae_set_error_flag(errorflag, sparsegetncols(&s1, _state)!=sparsegetnrows(&s2, _state), __FILE__, __LINE__, "testsparseunit.ap:656");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
ae_set_error_flag(errorflag, ae_fp_neq(sparseget(&s1, i, j, _state),sparseget(&s2, j, i, _state)), __FILE__, __LINE__, "testsparseunit.ap:661");
}
}
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
/*
* Check transposition
*/
sparsecopytransposecrs(&s1, &s3, _state);
ae_set_error_flag(errorflag, !sparseiscrs(&s3, _state), __FILE__, __LINE__, "testsparseunit.ap:669");
ae_set_error_flag(errorflag, sparsegetnrows(&s1, _state)!=sparsegetncols(&s3, _state), __FILE__, __LINE__, "testsparseunit.ap:670");
ae_set_error_flag(errorflag, sparsegetncols(&s1, _state)!=sparsegetnrows(&s3, _state), __FILE__, __LINE__, "testsparseunit.ap:671");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
ae_set_error_flag(errorflag, ae_fp_neq(sparseget(&s1, i, j, _state),sparseget(&s3, j, i, _state)), __FILE__, __LINE__, "testsparseunit.ap:676");
}
}
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
/*
* Check transposition
*/
sparsecopytransposecrs(&s1, &s4, _state);
ae_set_error_flag(errorflag, !sparseiscrs(&s4, _state), __FILE__, __LINE__, "testsparseunit.ap:684");
ae_set_error_flag(errorflag, sparsegetnrows(&s1, _state)!=sparsegetncols(&s4, _state), __FILE__, __LINE__, "testsparseunit.ap:685");
ae_set_error_flag(errorflag, sparsegetncols(&s1, _state)!=sparsegetnrows(&s4, _state), __FILE__, __LINE__, "testsparseunit.ap:686");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
ae_set_error_flag(errorflag, ae_fp_neq(sparseget(&s1, i, j, _state),sparseget(&s4, j, i, _state)), __FILE__, __LINE__, "testsparseunit.ap:691");
}
}
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
/*
* Increase problem sparcity and try one more time.
* Stop after testing NZ=0.
*/
if( nz==0 )
{
break;
}
nz = ae_minint(ae_round(nz*0.95, _state), nz-1, _state);
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Function for testing basic functional
-- ALGLIB PROJECT --
Copyright 14.10.2011 by Bochkanov Sergey
*************************************************************************/
ae_bool basicfunctest(ae_state *_state)
{
ae_frame _frame_block;
sparsematrix s;
ae_int_t n;
ae_int_t m;
ae_int_t i;
ae_int_t j;
ae_int_t i1;
ae_int_t j1;
ae_int_t uppercnt;
ae_int_t lowercnt;
ae_matrix a;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&a, 0, sizeof(a));
_sparsematrix_init(&s, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
n = 10;
m = 10;
result = ae_false;
for(i=1; i<=m-1; i++)
{
for(j=1; j<=n-1; j++)
{
sparsecreate(i, j, 1, &s, _state);
ae_matrix_set_length(&a, i, j, _state);
/*
* Checking for Matrix with hash table type
*/
uppercnt = 0;
lowercnt = 0;
for(i1=0; i1<=i-1; i1++)
{
for(j1=0; j1<=j-1; j1++)
{
if( j1>i1 )
{
inc(&uppercnt, _state);
}
if( j1N
* * with 50% probability to CRS or SKS, if M=N
*/
if( m!=n||ae_fp_less(hqrnduniformr(&rs, _state),0.5) )
{
sparsecopytocrs(&sa, &s0, _state);
}
else
{
sparsecopytosks(&sa, &s0, _state);
}
/*
* Test SparseGet() for SA and S0 against matrix returned in A
*/
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(sparseget(&sa, i, j, _state)-a.ptr.pp_double[i][j], _state),eps), __FILE__, __LINE__, "testsparseunit.ap:839");
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(sparseget(&s0, i, j, _state)-a.ptr.pp_double[i][j], _state),eps), __FILE__, __LINE__, "testsparseunit.ap:840");
}
}
/*
* Test SparseMV
*/
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&x1, n, _state);
for(j=0; j<=n-1; j++)
{
x0.ptr.p_double[j] = hqrnduniformr(&rs, _state)-0.5;
x1.ptr.p_double[j] = x0.ptr.p_double[j];
}
sparsemv(&s0, &x0, &y0, _state);
ae_set_error_flag(&result, y0.cntN
* * with 50% probability to CRS or SKS, if M=N
*/
if( m!=n||ae_fp_less(hqrnduniformr(&rs, _state),0.5) )
{
sparsecopytocrs(&sa, &s0, _state);
}
else
{
sparsecopytosks(&sa, &s0, _state);
}
/*
* Test SparseGet() for SA and S0 against matrix returned in A
*/
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
ae_set_error_flag(&result, ae_fp_neq(sparseget(&sa, i, j, _state),a.ptr.pp_double[i][j]), __FILE__, __LINE__, "testsparseunit.ap:1029");
ae_set_error_flag(&result, ae_fp_neq(sparseget(&s0, i, j, _state),a.ptr.pp_double[i][j]), __FILE__, __LINE__, "testsparseunit.ap:1030");
}
}
/*
* Test SparseMV
*/
ae_matrix_set_length(&x0, n, k, _state);
ae_matrix_set_length(&x1, n, k, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=k-1; j++)
{
x0.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5;
x1.ptr.pp_double[i][j] = x0.ptr.pp_double[i][j];
}
}
sparsemm(&s0, &x0, k, &y0, _state);
ae_set_error_flag(&result, y0.rows0 )
{
isupper = ae_true;
}
testsparseunit_initgenerator(n, n, 0, triangletype, &g, _state);
while(testsparseunit_generatenext(&g, &a, &sa, _state))
{
/*
* Convert SA to desired storage format:
* * S0 stores unmodified copy
* * S1 stores copy with unmodified triangle corresponding
* to IsUpper and another triangle being spoiled by random
* trash
*/
sparsecopytohash(&sa, &s1, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (ji&&!isupper) )
{
sparseset(&s1, i, j, hqrnduniformr(&rs, _state), _state);
}
}
}
if( ae_fp_less(hqrnduniformr(&rs, _state),0.5) )
{
sparsecopytocrs(&sa, &s0, _state);
sparseconverttocrs(&s1, _state);
}
else
{
sparsecopytosks(&sa, &s0, _state);
sparseconverttosks(&s1, _state);
}
/*
* Test SparseGet() for SA and S0 against matrix returned in A
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(sparseget(&sa, i, j, _state)-a.ptr.pp_double[i][j], _state),eps), __FILE__, __LINE__, "testsparseunit.ap:1184");
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(sparseget(&s0, i, j, _state)-a.ptr.pp_double[i][j], _state),eps), __FILE__, __LINE__, "testsparseunit.ap:1185");
ae_set_error_flag(&result, (ji&&triangletype==-1)&&ae_fp_neq(sparseget(&s0, i, j, _state),(double)(0)), __FILE__, __LINE__, "testsparseunit.ap:1187");
}
}
/*
* Before we proceed with testing, update empty triangle of A
* with its copy from another part of the matrix.
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (ji&&!isupper) )
{
a.ptr.pp_double[i][j] = a.ptr.pp_double[j][i];
}
}
}
/*
* Test SparseSMV
*/
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&x1, n, _state);
for(j=0; j<=n-1; j++)
{
x0.ptr.p_double[j] = hqrnduniformr(&rs, _state)-0.5;
x1.ptr.p_double[j] = x0.ptr.p_double[j];
}
sparsesmv(&s0, isupper, &x0, &y0, _state);
ae_set_error_flag(&result, y0.cnt0 )
{
isupper = ae_true;
}
testsparseunit_initgenerator(n, n, 0, triangletype, &g, _state);
while(testsparseunit_generatenext(&g, &a, &sa, _state))
{
/*
* Choose matrix width K
*/
k = 1+hqrnduniformi(&rs, 20, _state);
/*
* Convert SA to desired storage format:
* * S0 stores unmodified copy
* * S1 stores copy with unmodified triangle corresponding
* to IsUpper and another triangle being spoiled by random
* trash
*/
sparsecopytohash(&sa, &s1, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (ji&&!isupper) )
{
sparseset(&s1, i, j, hqrnduniformr(&rs, _state), _state);
}
}
}
if( ae_fp_less(hqrnduniformr(&rs, _state),0.5) )
{
sparsecopytocrs(&sa, &s0, _state);
sparseconverttocrs(&s1, _state);
}
else
{
sparsecopytosks(&sa, &s0, _state);
sparseconverttosks(&s1, _state);
}
/*
* Test SparseGet() for SA and S0 against matrix returned in A
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(sparseget(&sa, i, j, _state)-a.ptr.pp_double[i][j], _state),eps), __FILE__, __LINE__, "testsparseunit.ap:1326");
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(sparseget(&s0, i, j, _state)-a.ptr.pp_double[i][j], _state),eps), __FILE__, __LINE__, "testsparseunit.ap:1327");
ae_set_error_flag(&result, (ji&&triangletype==-1)&&ae_fp_neq(sparseget(&s0, i, j, _state),(double)(0)), __FILE__, __LINE__, "testsparseunit.ap:1329");
}
}
/*
* Before we proceed with testing, update empty triangle of A
* with its copy from another part of the matrix.
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (ji&&!isupper) )
{
a.ptr.pp_double[i][j] = a.ptr.pp_double[j][i];
}
}
}
/*
* Test SparseSMM
*/
ae_matrix_set_length(&x0, n, k, _state);
ae_matrix_set_length(&x1, n, k, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=k-1; j++)
{
x0.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5;
x1.ptr.pp_double[i][j] = x0.ptr.pp_double[i][j];
}
}
sparsesmm(&s0, isupper, &x0, k, &y0, _state);
ae_set_error_flag(&result, y0.rows0 )
{
isupper = ae_true;
}
testsparseunit_initgenerator(n, n, 0, triangletype, &g, _state);
while(testsparseunit_generatenext(&g, &a, &sa, _state))
{
/*
* Settings (IsUpper was already set, handle the rest)
*/
isunit = ae_fp_less(hqrnduniformr(&rs, _state),0.5);
optype = hqrnduniformi(&rs, 2, _state);
/*
* Convert SA to desired storage format:
* * S0 stores unmodified copy
* * S1 stores copy with unmodified triangle corresponding
* to IsUpper and another triangle being spoiled by random
* trash
*/
sparsecopytohash(&sa, &s1, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (ji&&!isupper) )
{
sparseset(&s1, i, j, hqrnduniformr(&rs, _state), _state);
}
}
}
if( ae_fp_less(hqrnduniformr(&rs, _state),0.5) )
{
sparsecopytocrs(&sa, &s0, _state);
sparseconverttocrs(&s1, _state);
}
else
{
sparsecopytosks(&sa, &s0, _state);
sparseconverttosks(&s1, _state);
}
/*
* Generate "effective A"
*/
ae_matrix_set_length(&ea, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
ea.ptr.pp_double[i][j] = (double)(0);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (j>=i&&isupper)||(j<=i&&!isupper) )
{
i1 = i;
j1 = j;
if( optype==1 )
{
swapi(&i1, &j1, _state);
}
ea.ptr.pp_double[i1][j1] = a.ptr.pp_double[i][j];
if( isunit&&i1==j1 )
{
ea.ptr.pp_double[i1][j1] = 1.0;
}
}
}
}
/*
* Test SparseTRMV
*/
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&x1, n, _state);
for(j=0; j<=n-1; j++)
{
x0.ptr.p_double[j] = hqrnduniformr(&rs, _state)-0.5;
x1.ptr.p_double[j] = x0.ptr.p_double[j];
}
sparsetrmv(&s0, isupper, isunit, optype, &x0, &y0, _state);
ae_set_error_flag(&result, y0.cnti&&!isupper) )
{
sparseset(&s1, i, j, hqrnduniformr(&rs, _state), _state);
}
}
}
if( ae_fp_less(hqrnduniformr(&rs, _state),0.5) )
{
sparsecopytocrs(&sa, &s0, _state);
sparseconverttocrs(&s1, _state);
}
else
{
sparsecopytosks(&sa, &s0, _state);
sparseconverttosks(&s1, _state);
}
/*
* Generate "effective A" and EY = inv(EA)*x0
*/
ae_matrix_set_length(&ea, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
ea.ptr.pp_double[i][j] = (double)(0);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (j>=i&&isupper)||(j<=i&&!isupper) )
{
i1 = i;
j1 = j;
if( optype==1 )
{
swapi(&i1, &j1, _state);
}
ea.ptr.pp_double[i1][j1] = a.ptr.pp_double[i][j];
if( isunit&&i1==j1 )
{
ea.ptr.pp_double[i1][j1] = 1.0;
}
}
}
}
ae_vector_set_length(&ey, n, _state);
for(i=0; i<=n-1; i++)
{
ey.ptr.p_double[i] = hqrnduniformr(&rs, _state)-0.5;
}
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&x1, n, _state);
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&ea.ptr.pp_double[i][0], 1, &ey.ptr.p_double[0], 1, ae_v_len(0,n-1));
x0.ptr.p_double[i] = v;
x1.ptr.p_double[i] = v;
}
/*
* Test SparseTRSV
*/
sparsetrsv(&s0, isupper, isunit, optype, &x0, _state);
ae_set_error_flag(&result, x0.cnti1&&j1<=i1+2 )
{
a.ptr.pp_double[i1][j1] = (double)(i1+j1+1);
sparseset(&s, i1, j1, a.ptr.pp_double[i1][j1], _state);
sparseadd(&s, i1, j1, (double)(0), _state);
sparseset(&sss, i1, j1, a.ptr.pp_double[i1][j1], _state);
}
else
{
a.ptr.pp_double[i1][j1] = (double)(0);
sparseset(&s, i1, j1, a.ptr.pp_double[i1][j1], _state);
sparseadd(&s, i1, j1, (double)(0), _state);
}
/*
* Check for SparseCreate
*/
sparsecopy(&s, &ss, _state);
a0 = sparseget(&s, i1, j1, _state);
a1 = sparseget(&ss, i1, j1, _state);
if( ae_fp_neq(a0,a1) )
{
if( !silent )
{
printf("BasicCopyFuncTest::Report::SparseGet\n");
printf("S::[%0d,%0d]=%0.5f\n",
(int)(i1),
(int)(j1),
(double)(a0));
printf("SS::[%0d,%0d]=%0.5f\n",
(int)(i1),
(int)(j1),
(double)(a1));
printf(" TEST FAILED.\n");
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
/*
* Check for SparseCreateCRS
*/
for(i1=0; i1<=i-1; i1++)
{
for(j1=0; j1<=j-1; j1++)
{
sparsecopy(&sss, &ss, _state);
a0 = sparseget(&sss, i1, j1, _state);
a1 = sparseget(&ss, i1, j1, _state);
if( ae_fp_neq(a0,a1) )
{
if( !silent )
{
printf("BasicCopyFuncTest::Report::SparseGet\n");
printf("S::[%0d,%0d]=%0.5f\n",
(int)(i1),
(int)(j1),
(double)(a0));
printf("SS::[%0d,%0d]=%0.5f\n",
(int)(i1),
(int)(j1),
(double)(a1));
printf(" TEST FAILED.\n");
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
/*
* Check for Matrix with CRS type
*/
sparseconverttocrs(&s, _state);
sparsecopy(&s, &ss, _state);
for(i1=0; i1<=i-1; i1++)
{
for(j1=0; j1<=j-1; j1++)
{
a0 = sparseget(&s, i1, j1, _state);
a1 = sparseget(&ss, i1, j1, _state);
if( ae_fp_neq(a0,a1) )
{
if( !silent )
{
printf("BasicCopyFuncTest::Report::SparseGet\n");
printf("S::[%0d,%0d]=%0.5f\n",
(int)(i1),
(int)(j1),
(double)(a0));
printf("SS::[%0d,%0d]=%0.5f\n",
(int)(i1),
(int)(j1),
(double)(a1));
printf(" TEST FAILED.\n");
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
}
if( !silent )
{
printf(" TEST IS PASSED.\n");
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Function for testing SparseCopy
-- ALGLIB PROJECT --
Copyright 14.10.2011 by Bochkanov Sergey
*************************************************************************/
ae_bool copyfunctest(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
sparsematrix s;
sparsematrix ss;
ae_int_t n;
ae_int_t m;
ae_int_t mtype;
ae_int_t i;
ae_int_t j;
ae_int_t i1;
ae_int_t j1;
double lb;
double rb;
ae_matrix a;
ae_vector x0;
ae_vector x1;
ae_vector ty;
ae_vector tyt;
ae_vector y;
ae_vector yt;
ae_vector y0;
ae_vector yt0;
ae_vector cpy;
ae_vector cpyt;
ae_vector cpy0;
ae_vector cpyt0;
double eps;
double a0;
double a1;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&ss, 0, sizeof(ss));
memset(&a, 0, sizeof(a));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&ty, 0, sizeof(ty));
memset(&tyt, 0, sizeof(tyt));
memset(&y, 0, sizeof(y));
memset(&yt, 0, sizeof(yt));
memset(&y0, 0, sizeof(y0));
memset(&yt0, 0, sizeof(yt0));
memset(&cpy, 0, sizeof(cpy));
memset(&cpyt, 0, sizeof(cpyt));
memset(&cpy0, 0, sizeof(cpy0));
memset(&cpyt0, 0, sizeof(cpyt0));
_sparsematrix_init(&s, _state, ae_true);
_sparsematrix_init(&ss, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ty, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tyt, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&yt, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&yt0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&cpy, 0, DT_REAL, _state, ae_true);
ae_vector_init(&cpyt, 0, DT_REAL, _state, ae_true);
ae_vector_init(&cpy0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&cpyt0, 0, DT_REAL, _state, ae_true);
/*
* Accuracy
*/
eps = 1000*ae_machineepsilon;
/*
* Size of the matrix (m*n)
*/
n = 30;
m = 30;
/*
* Left and right borders, limiting matrix values
*/
lb = (double)(-10);
rb = (double)(10);
/*
* Test linear algebra functions for:
* a) sparse matrix converted to CRS from Hash-Table
* b) sparse matrix initially created as CRS
*/
for(i=1; i<=m-1; i++)
{
for(j=1; j<=n-1; j++)
{
for(mtype=0; mtype<=1; mtype++)
{
/*
* Prepare test problem
*/
testsparseunit_createrandom(i, j, -1, mtype, -1, -1, &a, &s, _state);
sparsecopy(&s, &ss, _state);
/*
* Initialize temporaries
*/
ae_vector_set_length(&ty, i, _state);
ae_vector_set_length(&tyt, j, _state);
for(i1=0; i1<=i-1; i1++)
{
ty.ptr.p_double[i1] = (double)(0);
}
for(i1=0; i1<=j-1; i1++)
{
tyt.ptr.p_double[i1] = (double)(0);
}
ae_vector_set_length(&x0, j, _state);
ae_vector_set_length(&x1, i, _state);
for(i1=0; i1<=j-1; i1++)
{
x0.ptr.p_double[i1] = (rb-lb)*ae_randomreal(_state)+lb;
}
for(i1=0; i1<=i-1; i1++)
{
x1.ptr.p_double[i1] = (rb-lb)*ae_randomreal(_state)+lb;
}
/*
* Consider two cases: square matrix, and non-square matrix
*/
if( i!=j )
{
/*
* Searching true result
*/
for(i1=0; i1<=i-1; i1++)
{
for(j1=0; j1<=j-1; j1++)
{
ty.ptr.p_double[i1] = ty.ptr.p_double[i1]+a.ptr.pp_double[i1][j1]*x0.ptr.p_double[j1];
tyt.ptr.p_double[j1] = tyt.ptr.p_double[j1]+a.ptr.pp_double[i1][j1]*x1.ptr.p_double[i1];
}
}
/*
* Multiplication
*/
sparsemv(&s, &x0, &y, _state);
sparsemtv(&s, &x1, &yt, _state);
sparsemv(&ss, &x0, &cpy, _state);
sparsemtv(&ss, &x1, &cpyt, _state);
/*
* Check for MV-result
*/
for(i1=0; i1<=i-1; i1++)
{
if( (ae_fp_greater_eq(ae_fabs(y.ptr.p_double[i1]-ty.ptr.p_double[i1], _state),eps)||ae_fp_greater_eq(ae_fabs(cpy.ptr.p_double[i1]-ty.ptr.p_double[i1], _state),eps))||ae_fp_neq(cpy.ptr.p_double[i1]-y.ptr.p_double[i1],(double)(0)) )
{
if( !silent )
{
printf("CopyFuncTest::Report::RES_MV\n");
printf("Y[%0d]=%0.5f; tY[%0d]=%0.5f\n",
(int)(i1),
(double)(y.ptr.p_double[i1]),
(int)(i1),
(double)(ty.ptr.p_double[i1]));
printf("cpY[%0d]=%0.5f;\n",
(int)(i1),
(double)(cpy.ptr.p_double[i1]));
printf(" TEST FAILED.\n");
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
/*
* Check for MTV-result
*/
for(i1=0; i1<=j-1; i1++)
{
if( (ae_fp_greater_eq(ae_fabs(yt.ptr.p_double[i1]-tyt.ptr.p_double[i1], _state),eps)||ae_fp_greater_eq(ae_fabs(cpyt.ptr.p_double[i1]-tyt.ptr.p_double[i1], _state),eps))||ae_fp_neq(cpyt.ptr.p_double[i1]-yt.ptr.p_double[i1],(double)(0)) )
{
if( !silent )
{
printf("CopyFuncTest::Report::RES_MTV\n");
printf("Yt[%0d]=%0.5f; tYt[%0d]=%0.5f\n",
(int)(i1),
(double)(yt.ptr.p_double[i1]),
(int)(i1),
(double)(tyt.ptr.p_double[i1]));
printf("cpYt[%0d]=%0.5f;\n",
(int)(i1),
(double)(cpyt.ptr.p_double[i1]));
printf(" TEST FAILED.\n");
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
sparsecopy(&s, &ss, _state);
for(i1=0; i1<=i-1; i1++)
{
for(j1=0; j1<=j-1; j1++)
{
a0 = sparseget(&s, i1, j1, _state);
a1 = sparseget(&ss, i1, j1, _state);
if( ae_fp_neq(a0,a1) )
{
if( !silent )
{
printf("CopyFuncTest::Report::SparseGet\n");
printf("S::[%0d,%0d]=%0.5f\n",
(int)(i1),
(int)(j1),
(double)(a0));
printf("SS::[%0d,%0d]=%0.5f\n",
(int)(i1),
(int)(j1),
(double)(a1));
printf(" TEST FAILED.\n");
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
else
{
/*
* Searching true result
*/
for(i1=0; i1<=i-1; i1++)
{
for(j1=0; j1<=j-1; j1++)
{
ty.ptr.p_double[i1] = ty.ptr.p_double[i1]+a.ptr.pp_double[i1][j1]*x0.ptr.p_double[j1];
tyt.ptr.p_double[j1] = tyt.ptr.p_double[j1]+a.ptr.pp_double[i1][j1]*x0.ptr.p_double[i1];
}
}
/*
* Multiplication
*/
sparsemv(&s, &x0, &y, _state);
sparsemtv(&s, &x0, &yt, _state);
sparsemv2(&s, &x0, &y0, &yt0, _state);
sparsemv(&ss, &x0, &cpy, _state);
sparsemtv(&ss, &x0, &cpyt, _state);
sparsemv2(&ss, &x0, &cpy0, &cpyt0, _state);
/*
* Check for MV2-result
*/
for(i1=0; i1<=i-1; i1++)
{
if( ((((ae_fp_greater_eq(ae_fabs(y0.ptr.p_double[i1]-ty.ptr.p_double[i1], _state),eps)||ae_fp_greater_eq(ae_fabs(yt0.ptr.p_double[i1]-tyt.ptr.p_double[i1], _state),eps))||ae_fp_greater_eq(ae_fabs(cpy0.ptr.p_double[i1]-ty.ptr.p_double[i1], _state),eps))||ae_fp_greater_eq(ae_fabs(cpyt0.ptr.p_double[i1]-tyt.ptr.p_double[i1], _state),eps))||ae_fp_neq(cpy0.ptr.p_double[i1]-y0.ptr.p_double[i1],(double)(0)))||ae_fp_neq(cpyt0.ptr.p_double[i1]-yt0.ptr.p_double[i1],(double)(0)) )
{
if( !silent )
{
printf("CopyFuncTest::Report::RES_MV2\n");
printf("Y0[%0d]=%0.5f; tY[%0d]=%0.5f\n",
(int)(i1),
(double)(y0.ptr.p_double[i1]),
(int)(i1),
(double)(ty.ptr.p_double[i1]));
printf("Yt0[%0d]=%0.5f; tYt[%0d]=%0.5f\n",
(int)(i1),
(double)(yt0.ptr.p_double[i1]),
(int)(i1),
(double)(tyt.ptr.p_double[i1]));
printf("cpY0[%0d]=%0.5f;\n",
(int)(i1),
(double)(cpy0.ptr.p_double[i1]));
printf("cpYt0[%0d]=%0.5f;\n",
(int)(i1),
(double)(cpyt0.ptr.p_double[i1]));
printf(" TEST FAILED.\n");
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
/*
* Check for MV- and MTV-result by help MV2
*/
for(i1=0; i1<=i-1; i1++)
{
if( ((ae_fp_greater(ae_fabs(y0.ptr.p_double[i1]-y.ptr.p_double[i1], _state),eps)||ae_fp_greater(ae_fabs(yt0.ptr.p_double[i1]-yt.ptr.p_double[i1], _state),eps))||ae_fp_greater(ae_fabs(cpy0.ptr.p_double[i1]-cpy.ptr.p_double[i1], _state),eps))||ae_fp_greater(ae_fabs(cpyt0.ptr.p_double[i1]-cpyt.ptr.p_double[i1], _state),eps) )
{
if( !silent )
{
printf("CopyFuncTest::Report::RES_MV_MVT\n");
printf("Y0[%0d]=%0.5f; Y[%0d]=%0.5f\n",
(int)(i1),
(double)(y0.ptr.p_double[i1]),
(int)(i1),
(double)(y.ptr.p_double[i1]));
printf("Yt0[%0d]=%0.5f; Yt[%0d]=%0.5f\n",
(int)(i1),
(double)(yt0.ptr.p_double[i1]),
(int)(i1),
(double)(yt.ptr.p_double[i1]));
printf("cpY0[%0d]=%0.5f; cpY[%0d]=%0.5f\n",
(int)(i1),
(double)(cpy0.ptr.p_double[i1]),
(int)(i1),
(double)(cpy.ptr.p_double[i1]));
printf("cpYt0[%0d]=%0.5f; cpYt[%0d]=%0.5f\n",
(int)(i1),
(double)(cpyt0.ptr.p_double[i1]),
(int)(i1),
(double)(cpyt.ptr.p_double[i1]));
printf(" TEST FAILED.\n");
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
sparsecopy(&s, &ss, _state);
for(i1=0; i1<=i-1; i1++)
{
for(j1=0; j1<=j-1; j1++)
{
a0 = sparseget(&s, i1, j1, _state);
a1 = sparseget(&ss, i1, j1, _state);
if( ae_fp_neq(a0,a1) )
{
if( !silent )
{
printf("CopyFuncTest::Report::SparseGet\n");
printf("S::[%0d,%0d]=%0.5f\n",
(int)(i1),
(int)(j1),
(double)(a0));
printf("SS::[%0d,%0d]=%0.5f\n",
(int)(i1),
(int)(j1),
(double)(a1));
printf(" TEST FAILED.\n");
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
}
}
}
if( !silent )
{
printf(" TEST IS PASSED.\n");
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function initializes sparse matrix generator, which is used to generate
a set of matrices with sequentially increasing sparsity.
PARAMETERS:
M, N - matrix size. If M=0, then matrix is square N*N.
N and M must be small enough to store N*M dense matrix.
MatKind - matrix properties:
* 0 - general sparse (no structure)
* 1 - general sparse, but diagonal is always present and non-zero
* 2 - diagonally dominant, SPD
Triangle - triangle being returned:
* +1 - upper triangle
* -1 - lower triangle
* 0 - full matrix is returned
OUTPUT PARAMETERS:
G - generator
A - matrix A in dense format
SA - matrix A in sparse format (hash-table storage)
*************************************************************************/
static void testsparseunit_initgenerator(ae_int_t m,
ae_int_t n,
ae_int_t matkind,
ae_int_t triangle,
sparsegenerator* g,
ae_state *_state)
{
_sparsegenerator_clear(g);
g->n = n;
g->m = m;
g->matkind = matkind;
g->triangle = triangle;
hqrndrandomize(&g->rs, _state);
ae_vector_set_length(&g->rcs.ia, 5+1, _state);
ae_vector_set_length(&g->rcs.ra, 1+1, _state);
g->rcs.stage = -1;
}
static ae_bool testsparseunit_generatenext(sparsegenerator* g,
/* Real */ ae_matrix* da,
sparsematrix* sa,
ae_state *_state)
{
ae_int_t n;
ae_int_t m;
ae_int_t nz;
ae_int_t nzd;
double pnz;
ae_int_t i;
ae_int_t j;
double v;
ae_bool result;
ae_matrix_clear(da);
_sparsematrix_clear(sa);
/*
* Reverse communication preparations
* I know it looks ugly, but it works the same way
* anywhere from C++ to Python.
*
* This code initializes locals by:
* * random values determined during code
* generation - on first subroutine call
* * values from previous call - on subsequent calls
*/
if( g->rcs.stage>=0 )
{
n = g->rcs.ia.ptr.p_int[0];
m = g->rcs.ia.ptr.p_int[1];
nz = g->rcs.ia.ptr.p_int[2];
nzd = g->rcs.ia.ptr.p_int[3];
i = g->rcs.ia.ptr.p_int[4];
j = g->rcs.ia.ptr.p_int[5];
pnz = g->rcs.ra.ptr.p_double[0];
v = g->rcs.ra.ptr.p_double[1];
}
else
{
n = 359;
m = -58;
nz = -919;
nzd = -909;
i = 81;
j = 255;
pnz = 74;
v = -788;
}
if( g->rcs.stage==0 )
{
goto lbl_0;
}
if( g->rcs.stage==1 )
{
goto lbl_1;
}
/*
* Routine body
*/
n = g->n;
if( g->m==0 )
{
m = n;
}
else
{
m = g->m;
}
ae_assert(m>0&&n>0, "GenerateNext: incorrect N/M", _state);
/*
* Generate general sparse matrix
*/
if( g->matkind!=0 )
{
goto lbl_2;
}
nz = n*m;
lbl_4:
if( ae_false )
{
goto lbl_5;
}
/*
* Generate dense N*N matrix where probability of element
* being non-zero is PNZ.
*/
pnz = (double)nz/(double)(n*m);
ae_matrix_set_length(&g->bufa, m, n, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_less_eq(hqrnduniformr(&g->rs, _state),pnz) )
{
g->bufa.ptr.pp_double[i][j] = hqrnduniformr(&g->rs, _state)-0.5;
}
else
{
g->bufa.ptr.pp_double[i][j] = 0.0;
}
}
}
/*
* Output matrix and RComm
*/
ae_matrix_set_length(da, m, n, _state);
sparsecreate(m, n, ae_round(pnz*m*n, _state), sa, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (j<=i&&g->triangle<=0)||(j>=i&&g->triangle>=0) )
{
da->ptr.pp_double[i][j] = g->bufa.ptr.pp_double[i][j];
sparseset(sa, i, j, g->bufa.ptr.pp_double[i][j], _state);
}
else
{
da->ptr.pp_double[i][j] = 0.0;
}
}
}
g->rcs.stage = 0;
goto lbl_rcomm;
lbl_0:
/*
* Increase problem sparcity and try one more time.
* Stop after testing NZ=0.
*/
if( nz==0 )
{
goto lbl_5;
}
nz = nz/2;
goto lbl_4;
lbl_5:
result = ae_false;
return result;
lbl_2:
/*
* Generate general sparse matrix with non-zero diagonal
*/
if( g->matkind!=1 )
{
goto lbl_6;
}
ae_assert(n==m, "GenerateNext: non-square matrix for MatKind=1", _state);
nz = n*n-n;
lbl_8:
if( ae_false )
{
goto lbl_9;
}
/*
* Generate dense N*N matrix where probability of non-diagonal element
* being non-zero is PNZ.
*/
if( n>1 )
{
pnz = (double)nz/(double)(n*n-n);
}
else
{
pnz = (double)(1);
}
ae_matrix_set_length(&g->bufa, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( i==j )
{
do
{
g->bufa.ptr.pp_double[i][i] = hqrnduniformr(&g->rs, _state)-0.5;
}
while(ae_fp_eq(g->bufa.ptr.pp_double[i][i],(double)(0)));
g->bufa.ptr.pp_double[i][i] = g->bufa.ptr.pp_double[i][i]+1.5*ae_sign(g->bufa.ptr.pp_double[i][i], _state);
continue;
}
if( ae_fp_less_eq(hqrnduniformr(&g->rs, _state),pnz) )
{
g->bufa.ptr.pp_double[i][j] = hqrnduniformr(&g->rs, _state)-0.5;
}
else
{
g->bufa.ptr.pp_double[i][j] = 0.0;
}
}
}
/*
* Output matrix and RComm
*/
ae_matrix_set_length(da, n, n, _state);
sparsecreate(n, n, ae_round(pnz*(n*n-n)+n, _state), sa, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (j<=i&&g->triangle<=0)||(j>=i&&g->triangle>=0) )
{
da->ptr.pp_double[i][j] = g->bufa.ptr.pp_double[i][j];
sparseset(sa, i, j, g->bufa.ptr.pp_double[i][j], _state);
}
else
{
da->ptr.pp_double[i][j] = 0.0;
}
}
}
g->rcs.stage = 1;
goto lbl_rcomm;
lbl_1:
/*
* Increase problem sparcity and try one more time.
* Stop after testing NZ=0.
*/
if( nz==0 )
{
goto lbl_9;
}
nz = nz/2;
goto lbl_8;
lbl_9:
result = ae_false;
return result;
lbl_6:
ae_assert(ae_false, "Assertion failed", _state);
result = ae_false;
return result;
/*
* Saving state
*/
lbl_rcomm:
result = ae_true;
g->rcs.ia.ptr.p_int[0] = n;
g->rcs.ia.ptr.p_int[1] = m;
g->rcs.ia.ptr.p_int[2] = nz;
g->rcs.ia.ptr.p_int[3] = nzd;
g->rcs.ia.ptr.p_int[4] = i;
g->rcs.ia.ptr.p_int[5] = j;
g->rcs.ra.ptr.p_double[0] = pnz;
g->rcs.ra.ptr.p_double[1] = v;
return result;
}
/*************************************************************************
This function creates random sparse matrix with some prescribed pattern.
INPUT PARAMETERS:
M - number of rows
N - number of columns
PKind - sparsity pattern:
*-1 = pattern is chosen at random as well as P0/P1
* 0 = matrix with up to P0 non-zero elements at random locations
(however, actual number of non-zero elements can be
less than P0, and in fact can be zero)
* 1 = band matrix with P0 non-zero elements below diagonal
and P1 non-zero element above diagonal
* 2 = matrix with random number of contiguous non-zero
elements in the each row
CKind - creation type:
*-1 = CKind is chosen at random
* 0 = matrix is created in Hash-Table format and converted
to CRS representation
* 1 = matrix is created in CRS format
OUTPUT PARAMETERS:
DA - dense representation of A, array[M,N]
SA - sparse representation of A, in CRS format
-- ALGLIB PROJECT --
Copyright 31.10.2011 by Bochkanov Sergey
*************************************************************************/
static void testsparseunit_createrandom(ae_int_t m,
ae_int_t n,
ae_int_t pkind,
ae_int_t ckind,
ae_int_t p0,
ae_int_t p1,
/* Real */ ae_matrix* da,
sparsematrix* sa,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t maxpkind;
ae_int_t maxckind;
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
ae_vector c0;
ae_vector c1;
ae_vector rowsizes;
ae_frame_make(_state, &_frame_block);
memset(&c0, 0, sizeof(c0));
memset(&c1, 0, sizeof(c1));
memset(&rowsizes, 0, sizeof(rowsizes));
ae_matrix_clear(da);
_sparsematrix_clear(sa);
ae_vector_init(&c0, 0, DT_INT, _state, ae_true);
ae_vector_init(&c1, 0, DT_INT, _state, ae_true);
ae_vector_init(&rowsizes, 0, DT_INT, _state, ae_true);
maxpkind = 2;
maxckind = 1;
ae_assert(m>=1, "CreateRandom: incorrect parameters", _state);
ae_assert(n>=1, "CreateRandom: incorrect parameters", _state);
ae_assert(pkind>=-1&&pkind<=maxpkind, "CreateRandom: incorrect parameters", _state);
ae_assert(ckind>=-1&&ckind<=maxckind, "CreateRandom: incorrect parameters", _state);
if( pkind==-1 )
{
pkind = ae_randominteger(maxpkind+1, _state);
if( pkind==0 )
{
p0 = ae_randominteger(m*n, _state);
}
if( pkind==1 )
{
p0 = ae_randominteger(ae_minint(m, n, _state), _state);
p1 = ae_randominteger(ae_minint(m, n, _state), _state);
}
}
if( ckind==-1 )
{
ckind = ae_randominteger(maxckind+1, _state);
}
if( pkind==0 )
{
/*
* Matrix with elements at random locations
*/
ae_matrix_set_length(da, m, n, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
da->ptr.pp_double[i][j] = (double)(0);
}
}
if( ckind==0 )
{
/*
* Create matrix in Hash format, convert to CRS
*/
sparsecreate(m, n, 1, sa, _state);
for(k=0; k<=p0-1; k++)
{
i = ae_randominteger(m, _state);
j = ae_randominteger(n, _state);
v = (double)(ae_randominteger(17, _state)-8)/(double)8;
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
da->ptr.pp_double[i][j] = v;
sparseset(sa, i, j, v, _state);
}
else
{
da->ptr.pp_double[i][j] = da->ptr.pp_double[i][j]+v;
sparseadd(sa, i, j, v, _state);
}
}
sparseconverttocrs(sa, _state);
ae_frame_leave(_state);
return;
}
if( ckind==1 )
{
/*
* Create matrix in CRS format
*/
for(k=0; k<=p0-1; k++)
{
i = ae_randominteger(m, _state);
j = ae_randominteger(n, _state);
v = (double)(ae_randominteger(17, _state)-8)/(double)8;
da->ptr.pp_double[i][j] = v;
}
ae_vector_set_length(&rowsizes, m, _state);
for(i=0; i<=m-1; i++)
{
rowsizes.ptr.p_int[i] = 0;
for(j=0; j<=n-1; j++)
{
if( ae_fp_neq(da->ptr.pp_double[i][j],(double)(0)) )
{
rowsizes.ptr.p_int[i] = rowsizes.ptr.p_int[i]+1;
}
}
}
sparsecreatecrs(m, n, &rowsizes, sa, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_neq(da->ptr.pp_double[i][j],(double)(0)) )
{
sparseset(sa, i, j, da->ptr.pp_double[i][j], _state);
}
}
}
ae_frame_leave(_state);
return;
}
ae_assert(ae_false, "CreateRandom: internal error", _state);
}
if( pkind==1 )
{
/*
* Band matrix
*/
ae_matrix_set_length(da, m, n, _state);
ae_vector_set_length(&rowsizes, m, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
da->ptr.pp_double[i][j] = (double)(0);
}
}
for(i=0; i<=m-1; i++)
{
for(j=ae_maxint(i-p0, 0, _state); j<=ae_minint(i+p1, n-1, _state); j++)
{
do
{
da->ptr.pp_double[i][j] = (double)(ae_randominteger(17, _state)-8)/(double)8;
}
while(ae_fp_eq(da->ptr.pp_double[i][j],(double)(0)));
}
rowsizes.ptr.p_int[i] = ae_maxint(ae_minint(i+p1, n-1, _state)-ae_maxint(i-p0, 0, _state)+1, 0, _state);
}
if( ckind==0 )
{
sparsecreate(m, n, 1, sa, _state);
}
if( ckind==1 )
{
sparsecreatecrs(m, n, &rowsizes, sa, _state);
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_neq(da->ptr.pp_double[i][j],(double)(0)) )
{
sparseset(sa, i, j, da->ptr.pp_double[i][j], _state);
}
}
}
sparseconverttocrs(sa, _state);
ae_frame_leave(_state);
return;
}
if( pkind==2 )
{
/*
* Matrix with one contiguous sequence of non-zero elements per row
*/
ae_matrix_set_length(da, m, n, _state);
ae_vector_set_length(&rowsizes, m, _state);
ae_vector_set_length(&c0, m, _state);
ae_vector_set_length(&c1, m, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
da->ptr.pp_double[i][j] = (double)(0);
}
}
for(i=0; i<=m-1; i++)
{
c0.ptr.p_int[i] = ae_randominteger(n, _state);
c1.ptr.p_int[i] = c0.ptr.p_int[i]+ae_randominteger(n-c0.ptr.p_int[i]+1, _state);
rowsizes.ptr.p_int[i] = c1.ptr.p_int[i]-c0.ptr.p_int[i];
}
for(i=0; i<=m-1; i++)
{
for(j=c0.ptr.p_int[i]; j<=c1.ptr.p_int[i]-1; j++)
{
do
{
da->ptr.pp_double[i][j] = (double)(ae_randominteger(17, _state)-8)/(double)8;
}
while(ae_fp_eq(da->ptr.pp_double[i][j],(double)(0)));
}
}
if( ckind==0 )
{
sparsecreate(m, n, 1, sa, _state);
}
if( ckind==1 )
{
sparsecreatecrs(m, n, &rowsizes, sa, _state);
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_neq(da->ptr.pp_double[i][j],(double)(0)) )
{
sparseset(sa, i, j, da->ptr.pp_double[i][j], _state);
}
}
}
sparseconverttocrs(sa, _state);
ae_frame_leave(_state);
return;
}
ae_frame_leave(_state);
}
/*************************************************************************
This function does test for SparseEnumerate function.
-- ALGLIB PROJECT --
Copyright 14.03.2012 by Bochkanov Sergey
*************************************************************************/
static ae_bool testsparseunit_enumeratetest(ae_state *_state)
{
ae_frame _frame_block;
sparsematrix spa;
ae_matrix a;
ae_matrix ta;
ae_int_t m;
ae_int_t n;
double r;
double v;
ae_int_t ne;
ae_int_t t0;
ae_int_t t1;
ae_int_t counter;
ae_int_t c;
ae_int_t hashcrs;
ae_int_t i;
ae_int_t j;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&spa, 0, sizeof(spa));
memset(&a, 0, sizeof(a));
memset(&ta, 0, sizeof(ta));
_sparsematrix_init(&spa, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ta, 0, 0, DT_BOOL, _state, ae_true);
r = 10.5;
for(m=1; m<=30; m++)
{
for(n=1; n<=30; n++)
{
ne = 0;
/*
* Create matrix with non-zero elements inside the region:
* 0<=In )
{
ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testsparseunit.ap:3121");
ae_frame_leave(_state);
return;
}
for(j=0; j<=n-1; j++)
{
wasreturned.ptr.p_bool[j] = ae_false;
}
for(j=0; j<=nz-1; j++)
{
if( colidx.ptr.p_int[j]<0||colidx.ptr.p_int[j]>n )
{
ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testsparseunit.ap:3130");
ae_frame_leave(_state);
return;
}
ae_set_error_flag(err, j>0&&colidx.ptr.p_int[j]<=colidx.ptr.p_int[j-1], __FILE__, __LINE__, "testsparseunit.ap:3133");
ae_set_error_flag(err, ae_fp_neq(vals.ptr.p_double[j],a.ptr.pp_double[i][colidx.ptr.p_int[j]])||ae_fp_neq(vals.ptr.p_double[j],sparseget(&s, i, colidx.ptr.p_int[j], _state)), __FILE__, __LINE__, "testsparseunit.ap:3134");
wasreturned.ptr.p_bool[colidx.ptr.p_int[j]] = ae_true;
}
for(j=0; j<=n-1; j++)
{
ae_set_error_flag(err, ae_fp_neq(a.ptr.pp_double[i][j],(double)(0))&&!wasreturned.ptr.p_bool[j], __FILE__, __LINE__, "testsparseunit.ap:3138");
}
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Test for SparseConvert functions(isn't tested ConvertToCRS function). The
function create random dense and sparse matrices in CRS format. Then
convert sparse matrix to some format by CONVERT_TO/COPY_TO functions,
then it does some modification in matrices and compares that marices are
identical.
NOTE:
Result of the function assigned to variable CopyErrors in unit test.
-- ALGLIB PROJECT --
Copyright 23.07.2012 by Bochkanov Sergey
*************************************************************************/
static ae_bool testsparseunit_testconvertsm(ae_state *_state)
{
ae_frame _frame_block;
sparsematrix s;
sparsematrix cs;
ae_matrix a;
ae_int_t m;
ae_int_t n;
ae_int_t msize;
ae_int_t nsize;
ae_vector ner;
double tmp;
ae_int_t i;
ae_int_t j;
ae_int_t vartf;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&cs, 0, sizeof(cs));
memset(&a, 0, sizeof(a));
memset(&ner, 0, sizeof(ner));
_sparsematrix_init(&s, _state, ae_true);
_sparsematrix_init(&cs, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ner, 0, DT_INT, _state, ae_true);
msize = 15;
nsize = 15;
for(m=1; m<=msize; m++)
{
for(n=1; n<=nsize; n++)
{
for(vartf=0; vartf<=2; vartf++)
{
ae_matrix_set_length(&a, m, n, _state);
ae_vector_set_length(&ner, m, _state);
for(i=0; i<=m-1; i++)
{
ner.ptr.p_int[i] = 0;
for(j=0; j<=n-1; j++)
{
if( ae_randominteger(5, _state)==3 )
{
ner.ptr.p_int[i] = ner.ptr.p_int[i]+1;
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
else
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
}
/*
* Create sparse matrix
*/
sparsecreatecrs(m, n, &ner, &s, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_neq(a.ptr.pp_double[i][j],(double)(0)) )
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
sparseset(&s, i, j, a.ptr.pp_double[i][j], _state);
}
}
}
/*
* Set matrix type(we have to be sure that all formats
* converted correctly)
*/
i = ae_randominteger(2, _state);
if( i==0 )
{
sparseconverttohash(&s, _state);
}
if( i==1 )
{
sparseconverttocrs(&s, _state);
}
/*
* Start test
*/
if( vartf==0 )
{
sparseconverttohash(&s, _state);
sparsecopy(&s, &cs, _state);
}
if( vartf==1 )
{
sparsecopytohash(&s, &cs, _state);
}
if( vartf==2 )
{
sparsecopytocrs(&s, &cs, _state);
}
/*
* Change some elements in row
*/
if( vartf!=2 )
{
for(i=0; i<=m-1; i++)
{
tmp = 2*ae_randomreal(_state)-1;
j = ae_randominteger(n, _state);
a.ptr.pp_double[i][j] = tmp;
sparseset(&cs, i, j, tmp, _state);
tmp = 2*ae_randomreal(_state)-1;
j = ae_randominteger(n, _state);
a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+tmp;
sparseadd(&cs, i, j, tmp, _state);
}
}
/*
* Check that A is identical to S
*/
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_neq(a.ptr.pp_double[i][j],sparseget(&cs, i, j, _state)) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Test for check/get type functions. The function create sparse matrix,
converts it to desired type then check this type.
NOTE:
Result of the function assigned to variable BasicErrors in unit test.
-- ALGLIB PROJECT --
Copyright 23.07.2012 by Bochkanov Sergey
*************************************************************************/
static ae_bool testsparseunit_testgcmatrixtype(ae_state *_state)
{
ae_frame _frame_block;
sparsematrix s;
sparsematrix cs;
ae_int_t m;
ae_int_t n;
ae_int_t msize;
ae_int_t nsize;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&cs, 0, sizeof(cs));
_sparsematrix_init(&s, _state, ae_true);
_sparsematrix_init(&cs, _state, ae_true);
msize = 5;
nsize = 5;
for(m=1; m<=msize; m++)
{
for(n=1; n<=nsize; n++)
{
sparsecreate(m, n, 1, &s, _state);
sparseconverttocrs(&s, _state);
if( (sparseishash(&s, _state)||!sparseiscrs(&s, _state))||sparsegetmatrixtype(&s, _state)!=1 )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
sparseconverttohash(&s, _state);
if( (!sparseishash(&s, _state)||sparseiscrs(&s, _state))||sparsegetmatrixtype(&s, _state)!=0 )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
sparsecopytocrs(&s, &cs, _state);
if( (sparseishash(&cs, _state)||!sparseiscrs(&cs, _state))||sparsegetmatrixtype(&cs, _state)!=1 )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
sparsecopytohash(&cs, &s, _state);
if( (!sparseishash(&s, _state)||sparseiscrs(&s, _state))||sparsegetmatrixtype(&s, _state)!=0 )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
void _sparsegenerator_init(void* _p, ae_state *_state, ae_bool make_automatic)
{
sparsegenerator *p = (sparsegenerator*)_p;
ae_touch_ptr((void*)p);
ae_matrix_init(&p->bufa, 0, 0, DT_REAL, _state, make_automatic);
_hqrndstate_init(&p->rs, _state, make_automatic);
_rcommstate_init(&p->rcs, _state, make_automatic);
}
void _sparsegenerator_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
{
sparsegenerator *dst = (sparsegenerator*)_dst;
sparsegenerator *src = (sparsegenerator*)_src;
dst->n = src->n;
dst->m = src->m;
dst->matkind = src->matkind;
dst->triangle = src->triangle;
ae_matrix_init_copy(&dst->bufa, &src->bufa, _state, make_automatic);
_hqrndstate_init_copy(&dst->rs, &src->rs, _state, make_automatic);
_rcommstate_init_copy(&dst->rcs, &src->rcs, _state, make_automatic);
}
void _sparsegenerator_clear(void* _p)
{
sparsegenerator *p = (sparsegenerator*)_p;
ae_touch_ptr((void*)p);
ae_matrix_clear(&p->bufa);
_hqrndstate_clear(&p->rs);
_rcommstate_clear(&p->rcs);
}
void _sparsegenerator_destroy(void* _p)
{
sparsegenerator *p = (sparsegenerator*)_p;
ae_touch_ptr((void*)p);
ae_matrix_destroy(&p->bufa);
_hqrndstate_destroy(&p->rs);
_rcommstate_destroy(&p->rcs);
}
static ae_bool testablasunit_testtrsm(ae_int_t minn,
ae_int_t maxn,
ae_state *_state);
static ae_bool testablasunit_testsyrk(ae_int_t minn,
ae_int_t maxn,
ae_state *_state);
static ae_bool testablasunit_testgemm(ae_int_t minn,
ae_int_t maxn,
ae_state *_state);
static ae_bool testablasunit_testtrans(ae_int_t minn,
ae_int_t maxn,
ae_state *_state);
static ae_bool testablasunit_testrank1(ae_int_t minn,
ae_int_t maxn,
ae_state *_state);
static ae_bool testablasunit_testgemv(ae_int_t minn,
ae_int_t maxn,
ae_state *_state);
static void testablasunit_testsymv(ae_int_t minn,
ae_int_t maxn,
ae_bool* errorflag,
ae_state *_state);
static void testablasunit_testtrsv(ae_int_t minn,
ae_int_t maxn,
ae_bool* errorflag,
ae_state *_state);
static void testablasunit_spectest(ae_bool* errorflag, ae_state *_state);
static ae_bool testablasunit_testcopy(ae_int_t minn,
ae_int_t maxn,
ae_state *_state);
static void testablasunit_testreflections(ae_bool* errorflag,
ae_state *_state);
static void testablasunit_refcmatrixrighttrsm(ae_int_t m,
ae_int_t n,
/* Complex */ ae_matrix* a,
ae_int_t i1,
ae_int_t j1,
ae_bool isupper,
ae_bool isunit,
ae_int_t optype,
/* Complex */ ae_matrix* x,
ae_int_t i2,
ae_int_t j2,
ae_state *_state);
static void testablasunit_refcmatrixlefttrsm(ae_int_t m,
ae_int_t n,
/* Complex */ ae_matrix* a,
ae_int_t i1,
ae_int_t j1,
ae_bool isupper,
ae_bool isunit,
ae_int_t optype,
/* Complex */ ae_matrix* x,
ae_int_t i2,
ae_int_t j2,
ae_state *_state);
static void testablasunit_refrmatrixrighttrsm(ae_int_t m,
ae_int_t n,
/* Real */ ae_matrix* a,
ae_int_t i1,
ae_int_t j1,
ae_bool isupper,
ae_bool isunit,
ae_int_t optype,
/* Real */ ae_matrix* x,
ae_int_t i2,
ae_int_t j2,
ae_state *_state);
static void testablasunit_refrmatrixlefttrsm(ae_int_t m,
ae_int_t n,
/* Real */ ae_matrix* a,
ae_int_t i1,
ae_int_t j1,
ae_bool isupper,
ae_bool isunit,
ae_int_t optype,
/* Real */ ae_matrix* x,
ae_int_t i2,
ae_int_t j2,
ae_state *_state);
static ae_bool testablasunit_internalcmatrixtrinverse(/* Complex */ ae_matrix* a,
ae_int_t n,
ae_bool isupper,
ae_bool isunittriangular,
ae_state *_state);
static ae_bool testablasunit_internalrmatrixtrinverse(/* Real */ ae_matrix* a,
ae_int_t n,
ae_bool isupper,
ae_bool isunittriangular,
ae_state *_state);
static void testablasunit_refcmatrixherk(ae_int_t n,
ae_int_t k,
double alpha,
/* Complex */ ae_matrix* a,
ae_int_t ia,
ae_int_t ja,
ae_int_t optypea,
double beta,
/* Complex */ ae_matrix* c,
ae_int_t ic,
ae_int_t jc,
ae_bool isupper,
ae_state *_state);
static void testablasunit_refrmatrixsyrk(ae_int_t n,
ae_int_t k,
double alpha,
/* Real */ ae_matrix* a,
ae_int_t ia,
ae_int_t ja,
ae_int_t optypea,
double beta,
/* Real */ ae_matrix* c,
ae_int_t ic,
ae_int_t jc,
ae_bool isupper,
ae_state *_state);
static void testablasunit_refcmatrixgemm(ae_int_t m,
ae_int_t n,
ae_int_t k,
ae_complex alpha,
/* Complex */ ae_matrix* a,
ae_int_t ia,
ae_int_t ja,
ae_int_t optypea,
/* Complex */ ae_matrix* b,
ae_int_t ib,
ae_int_t jb,
ae_int_t optypeb,
ae_complex beta,
/* Complex */ ae_matrix* c,
ae_int_t ic,
ae_int_t jc,
ae_state *_state);
static void testablasunit_refrmatrixgemm(ae_int_t m,
ae_int_t n,
ae_int_t k,
double alpha,
/* Real */ ae_matrix* a,
ae_int_t ia,
ae_int_t ja,
ae_int_t optypea,
/* Real */ ae_matrix* b,
ae_int_t ib,
ae_int_t jb,
ae_int_t optypeb,
double beta,
/* Real */ ae_matrix* c,
ae_int_t ic,
ae_int_t jc,
ae_state *_state);
static void testablasunit_refrmatrixsymv(ae_int_t n,
double alpha,
/* Real */ ae_matrix* a,
ae_int_t ia,
ae_int_t ja,
ae_bool isupper,
/* Real */ ae_vector* x,
ae_int_t ix,
double beta,
/* Real */ ae_vector* y,
ae_int_t iy,
ae_state *_state);
static double testablasunit_refrmatrixsyvmv(ae_int_t n,
/* Real */ ae_matrix* a,
ae_int_t ia,
ae_int_t ja,
ae_bool isupper,
/* Real */ ae_vector* x,
ae_int_t ix,
ae_state *_state);
ae_bool testablas(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n0;
ae_int_t n1;
ae_bool trsmerrors;
ae_bool syrkerrors;
ae_bool gemmerrors;
ae_bool transerrors;
ae_bool rank1errors;
ae_bool gemverrors;
ae_bool symverrors;
ae_bool trsverrors;
ae_bool reflerrors;
ae_bool copyerrors;
ae_bool specerrors;
ae_bool waserrors;
ae_matrix ra;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&ra, 0, sizeof(ra));
ae_matrix_init(&ra, 0, 0, DT_REAL, _state, ae_true);
trsmerrors = ae_false;
syrkerrors = ae_false;
gemmerrors = ae_false;
transerrors = ae_false;
rank1errors = ae_false;
gemverrors = ae_false;
symverrors = ae_false;
trsverrors = ae_false;
reflerrors = ae_false;
copyerrors = ae_false;
waserrors = ae_false;
specerrors = ae_false;
testablasunit_spectest(&specerrors, _state);
trsmerrors = trsmerrors||testablasunit_testtrsm(1, 3*matrixtilesizea(_state)+1, _state);
syrkerrors = syrkerrors||testablasunit_testsyrk(1, 3*matrixtilesizea(_state)+1, _state);
gemmerrors = gemmerrors||testablasunit_testgemm(1, 3*matrixtilesizea(_state)+1, _state);
transerrors = transerrors||testablasunit_testtrans(1, 3*matrixtilesizea(_state)+1, _state);
rank1errors = rank1errors||testablasunit_testrank1(1, 3*matrixtilesizea(_state)+1, _state);
gemverrors = gemverrors||testablasunit_testgemv(1, 3*matrixtilesizea(_state)+1, _state);
copyerrors = copyerrors||testablasunit_testcopy(1, 3*matrixtilesizea(_state)+1, _state);
testablasunit_testsymv(1, 3*matrixtilesizea(_state)+1, &symverrors, _state);
testablasunit_testtrsv(1, 3*matrixtilesizea(_state)+1, &trsverrors, _state);
testablasunit_testreflections(&reflerrors, _state);
n0 = 6*matrixtilesizeb(_state);
n1 = 6*matrixtilesizeb(_state);
gemmerrors = gemmerrors||testablasunit_testgemm(n0, n1, _state);
trsmerrors = trsmerrors||testablasunit_testtrsm(n0, n1, _state);
syrkerrors = syrkerrors||testablasunit_testsyrk(n0, n1, _state);
/*
* report
*/
waserrors = (((((((((trsmerrors||syrkerrors)||gemmerrors)||transerrors)||rank1errors)||gemverrors)||symverrors)||trsverrors)||reflerrors)||copyerrors)||specerrors;
if( !silent )
{
printf("TESTING ABLAS\n");
printf("LEVEL 3 FUNCTIONS:\n");
printf("* TRSM ");
if( trsmerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* SYRK ");
if( syrkerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* GEMM ");
if( gemmerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("LEVEL 2 FUNCTIONS:\n");
printf("* TRANS ");
if( transerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* RANK1 ");
if( rank1errors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* GEMV ");
if( gemverrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* SYMV/SYVMV ");
if( symverrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* TRSV ");
if( trsverrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* REFL ");
if( reflerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* COPY ");
if( copyerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("SPECIAL TESTS ");
if( specerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
?Matrix????TRSM tests
Returns False for passed test, True - for failed
*************************************************************************/
static ae_bool testablasunit_testtrsm(ae_int_t minn,
ae_int_t maxn,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t m;
ae_int_t mx;
ae_int_t i;
ae_int_t j;
ae_int_t optype;
ae_int_t uppertype;
ae_int_t unittype;
ae_int_t xoffsi;
ae_int_t xoffsj;
ae_int_t aoffsitype;
ae_int_t aoffsjtype;
ae_int_t aoffsi;
ae_int_t aoffsj;
ae_matrix refra;
ae_matrix refrxl;
ae_matrix refrxr;
ae_matrix refca;
ae_matrix refcxl;
ae_matrix refcxr;
ae_matrix ra;
ae_matrix ca;
ae_matrix rxr1;
ae_matrix rxl1;
ae_matrix cxr1;
ae_matrix cxl1;
ae_matrix rxr2;
ae_matrix rxl2;
ae_matrix cxr2;
ae_matrix cxl2;
double threshold;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&refra, 0, sizeof(refra));
memset(&refrxl, 0, sizeof(refrxl));
memset(&refrxr, 0, sizeof(refrxr));
memset(&refca, 0, sizeof(refca));
memset(&refcxl, 0, sizeof(refcxl));
memset(&refcxr, 0, sizeof(refcxr));
memset(&ra, 0, sizeof(ra));
memset(&ca, 0, sizeof(ca));
memset(&rxr1, 0, sizeof(rxr1));
memset(&rxl1, 0, sizeof(rxl1));
memset(&cxr1, 0, sizeof(cxr1));
memset(&cxl1, 0, sizeof(cxl1));
memset(&rxr2, 0, sizeof(rxr2));
memset(&rxl2, 0, sizeof(rxl2));
memset(&cxr2, 0, sizeof(cxr2));
memset(&cxl2, 0, sizeof(cxl2));
ae_matrix_init(&refra, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&refrxl, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&refrxr, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&refca, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&refcxl, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&refcxr, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&ra, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ca, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&rxr1, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&rxl1, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&cxr1, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&cxl1, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&rxr2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&rxl2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&cxr2, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&cxl2, 0, 0, DT_COMPLEX, _state, ae_true);
threshold = ae_sqr((double)(maxn), _state)*100*ae_machineepsilon;
result = ae_false;
for(mx=minn; mx<=maxn; mx++)
{
/*
* Select random M/N in [1,MX] such that max(M,N)=MX
*/
m = 1+ae_randominteger(mx, _state);
n = 1+ae_randominteger(mx, _state);
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
m = mx;
}
else
{
n = mx;
}
/*
* Initialize RefRA/RefCA by random matrices whose upper
* and lower triangle submatrices are non-degenerate
* well-conditioned matrices.
*
* Matrix size is 2Mx2M (four copies of same MxM matrix
* to test different offsets)
*/
ae_matrix_set_length(&refra, 2*m, 2*m, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=m-1; j++)
{
refra.ptr.pp_double[i][j] = 0.2*ae_randomreal(_state)-0.1;
}
}
for(i=0; i<=m-1; i++)
{
refra.ptr.pp_double[i][i] = (2*ae_randominteger(1, _state)-1)*(2*m+ae_randomreal(_state));
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=m-1; j++)
{
refra.ptr.pp_double[i+m][j] = refra.ptr.pp_double[i][j];
refra.ptr.pp_double[i][j+m] = refra.ptr.pp_double[i][j];
refra.ptr.pp_double[i+m][j+m] = refra.ptr.pp_double[i][j];
}
}
ae_matrix_set_length(&refca, 2*m, 2*m, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=m-1; j++)
{
refca.ptr.pp_complex[i][j].x = 0.2*ae_randomreal(_state)-0.1;
refca.ptr.pp_complex[i][j].y = 0.2*ae_randomreal(_state)-0.1;
}
}
for(i=0; i<=m-1; i++)
{
refca.ptr.pp_complex[i][i].x = (2*ae_randominteger(2, _state)-1)*(2*m+ae_randomreal(_state));
refca.ptr.pp_complex[i][i].y = (2*ae_randominteger(2, _state)-1)*(2*m+ae_randomreal(_state));
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=m-1; j++)
{
refca.ptr.pp_complex[i+m][j] = refca.ptr.pp_complex[i][j];
refca.ptr.pp_complex[i][j+m] = refca.ptr.pp_complex[i][j];
refca.ptr.pp_complex[i+m][j+m] = refca.ptr.pp_complex[i][j];
}
}
/*
* Generate random XL/XR.
*
* XR is NxM matrix (matrix for 'Right' subroutines)
* XL is MxN matrix (matrix for 'Left' subroutines)
*/
ae_matrix_set_length(&refrxr, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
refrxr.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
ae_matrix_set_length(&refrxl, m, n, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
refrxl.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
ae_matrix_set_length(&refcxr, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
refcxr.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
refcxr.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
ae_matrix_set_length(&refcxl, m, n, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
refcxl.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
refcxl.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
/*
* test different types of operations, offsets, and so on...
*
* to avoid unnecessary slowdown we don't test ALL possible
* combinations of operation types. We just generate one random
* set of parameters and test it.
*/
ae_matrix_set_length(&ra, 2*m, 2*m, _state);
ae_matrix_set_length(&rxr1, n, m, _state);
ae_matrix_set_length(&rxr2, n, m, _state);
ae_matrix_set_length(&rxl1, m, n, _state);
ae_matrix_set_length(&rxl2, m, n, _state);
ae_matrix_set_length(&ca, 2*m, 2*m, _state);
ae_matrix_set_length(&cxr1, n, m, _state);
ae_matrix_set_length(&cxr2, n, m, _state);
ae_matrix_set_length(&cxl1, m, n, _state);
ae_matrix_set_length(&cxl2, m, n, _state);
optype = ae_randominteger(3, _state);
uppertype = ae_randominteger(2, _state);
unittype = ae_randominteger(2, _state);
xoffsi = ae_randominteger(2, _state);
xoffsj = ae_randominteger(2, _state);
aoffsitype = ae_randominteger(2, _state);
aoffsjtype = ae_randominteger(2, _state);
aoffsi = m*aoffsitype;
aoffsj = m*aoffsjtype;
/*
* copy A, XR, XL (fill unused parts with random garbage)
*/
for(i=0; i<=2*m-1; i++)
{
for(j=0; j<=2*m-1; j++)
{
if( ((i>=aoffsi&&i=aoffsj)&&j=xoffsi&&j>=xoffsj )
{
cxr1.ptr.pp_complex[i][j] = refcxr.ptr.pp_complex[i][j];
cxr2.ptr.pp_complex[i][j] = refcxr.ptr.pp_complex[i][j];
rxr1.ptr.pp_double[i][j] = refrxr.ptr.pp_double[i][j];
rxr2.ptr.pp_double[i][j] = refrxr.ptr.pp_double[i][j];
}
else
{
cxr1.ptr.pp_complex[i][j] = ae_complex_from_d(ae_randomreal(_state));
cxr2.ptr.pp_complex[i][j] = cxr1.ptr.pp_complex[i][j];
rxr1.ptr.pp_double[i][j] = ae_randomreal(_state);
rxr2.ptr.pp_double[i][j] = rxr1.ptr.pp_double[i][j];
}
}
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( i>=xoffsi&&j>=xoffsj )
{
cxl1.ptr.pp_complex[i][j] = refcxl.ptr.pp_complex[i][j];
cxl2.ptr.pp_complex[i][j] = refcxl.ptr.pp_complex[i][j];
rxl1.ptr.pp_double[i][j] = refrxl.ptr.pp_double[i][j];
rxl2.ptr.pp_double[i][j] = refrxl.ptr.pp_double[i][j];
}
else
{
cxl1.ptr.pp_complex[i][j] = ae_complex_from_d(ae_randomreal(_state));
cxl2.ptr.pp_complex[i][j] = cxl1.ptr.pp_complex[i][j];
rxl1.ptr.pp_double[i][j] = ae_randomreal(_state);
rxl2.ptr.pp_double[i][j] = rxl1.ptr.pp_double[i][j];
}
}
}
/*
* Test CXR
*/
cmatrixrighttrsm(n-xoffsi, m-xoffsj, &ca, aoffsi, aoffsj, uppertype==0, unittype==0, optype, &cxr1, xoffsi, xoffsj, _state);
testablasunit_refcmatrixrighttrsm(n-xoffsi, m-xoffsj, &ca, aoffsi, aoffsj, uppertype==0, unittype==0, optype, &cxr2, xoffsi, xoffsj, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
result = result||ae_fp_greater(ae_c_abs(ae_c_sub(cxr1.ptr.pp_complex[i][j],cxr2.ptr.pp_complex[i][j]), _state),threshold);
}
}
/*
* Test CXL
*/
cmatrixlefttrsm(m-xoffsi, n-xoffsj, &ca, aoffsi, aoffsj, uppertype==0, unittype==0, optype, &cxl1, xoffsi, xoffsj, _state);
testablasunit_refcmatrixlefttrsm(m-xoffsi, n-xoffsj, &ca, aoffsi, aoffsj, uppertype==0, unittype==0, optype, &cxl2, xoffsi, xoffsj, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
result = result||ae_fp_greater(ae_c_abs(ae_c_sub(cxl1.ptr.pp_complex[i][j],cxl2.ptr.pp_complex[i][j]), _state),threshold);
}
}
if( optype<2 )
{
/*
* Test RXR
*/
rmatrixrighttrsm(n-xoffsi, m-xoffsj, &ra, aoffsi, aoffsj, uppertype==0, unittype==0, optype, &rxr1, xoffsi, xoffsj, _state);
testablasunit_refrmatrixrighttrsm(n-xoffsi, m-xoffsj, &ra, aoffsi, aoffsj, uppertype==0, unittype==0, optype, &rxr2, xoffsi, xoffsj, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
result = result||ae_fp_greater(ae_fabs(rxr1.ptr.pp_double[i][j]-rxr2.ptr.pp_double[i][j], _state),threshold);
}
}
/*
* Test RXL
*/
rmatrixlefttrsm(m-xoffsi, n-xoffsj, &ra, aoffsi, aoffsj, uppertype==0, unittype==0, optype, &rxl1, xoffsi, xoffsj, _state);
testablasunit_refrmatrixlefttrsm(m-xoffsi, n-xoffsj, &ra, aoffsi, aoffsj, uppertype==0, unittype==0, optype, &rxl2, xoffsi, xoffsj, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
result = result||ae_fp_greater(ae_fabs(rxl1.ptr.pp_double[i][j]-rxl2.ptr.pp_double[i][j], _state),threshold);
}
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
SYRK tests
Returns False for passed test, True - for failed
*************************************************************************/
static ae_bool testablasunit_testsyrk(ae_int_t minn,
ae_int_t maxn,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t k;
ae_int_t mx;
ae_int_t i;
ae_int_t j;
ae_int_t uppertype;
ae_int_t xoffsi;
ae_int_t xoffsj;
ae_int_t aoffsitype;
ae_int_t aoffsjtype;
ae_int_t aoffsi;
ae_int_t aoffsj;
ae_int_t alphatype;
ae_int_t betatype;
ae_matrix refra;
ae_matrix refrc;
ae_matrix refca;
ae_matrix refcc;
double alpha;
double beta;
ae_matrix ra1;
ae_matrix ra2;
ae_matrix ca1;
ae_matrix ca2;
ae_matrix rc;
ae_matrix rct;
ae_matrix cc;
ae_matrix cct;
double threshold;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&refra, 0, sizeof(refra));
memset(&refrc, 0, sizeof(refrc));
memset(&refca, 0, sizeof(refca));
memset(&refcc, 0, sizeof(refcc));
memset(&ra1, 0, sizeof(ra1));
memset(&ra2, 0, sizeof(ra2));
memset(&ca1, 0, sizeof(ca1));
memset(&ca2, 0, sizeof(ca2));
memset(&rc, 0, sizeof(rc));
memset(&rct, 0, sizeof(rct));
memset(&cc, 0, sizeof(cc));
memset(&cct, 0, sizeof(cct));
ae_matrix_init(&refra, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&refrc, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&refca, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&refcc, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&ra1, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ra2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ca1, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&ca2, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&rc, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&rct, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&cc, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&cct, 0, 0, DT_COMPLEX, _state, ae_true);
threshold = maxn*100*ae_machineepsilon;
result = ae_false;
for(mx=minn; mx<=maxn; mx++)
{
/*
* Select random M/N in [1,MX] such that max(M,N)=MX
*/
k = 1+ae_randominteger(mx, _state);
n = 1+ae_randominteger(mx, _state);
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
k = mx;
}
else
{
n = mx;
}
/*
* Initialize RefRA/RefCA by random Hermitian matrices,
* RefRC/RefCC by random matrices
*
* RA/CA size is 2Nx2N (four copies of same NxN matrix
* to test different offsets)
*/
ae_matrix_set_length(&refra, 2*n, 2*n, _state);
ae_matrix_set_length(&refca, 2*n, 2*n, _state);
for(i=0; i<=n-1; i++)
{
refra.ptr.pp_double[i][i] = 2*ae_randomreal(_state)-1;
refca.ptr.pp_complex[i][i] = ae_complex_from_d(2*ae_randomreal(_state)-1);
for(j=i+1; j<=n-1; j++)
{
refra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
refca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
refca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
refra.ptr.pp_double[j][i] = refra.ptr.pp_double[i][j];
refca.ptr.pp_complex[j][i] = ae_c_conj(refca.ptr.pp_complex[i][j], _state);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
refra.ptr.pp_double[i+n][j] = refra.ptr.pp_double[i][j];
refra.ptr.pp_double[i][j+n] = refra.ptr.pp_double[i][j];
refra.ptr.pp_double[i+n][j+n] = refra.ptr.pp_double[i][j];
refca.ptr.pp_complex[i+n][j] = refca.ptr.pp_complex[i][j];
refca.ptr.pp_complex[i][j+n] = refca.ptr.pp_complex[i][j];
refca.ptr.pp_complex[i+n][j+n] = refca.ptr.pp_complex[i][j];
}
}
ae_matrix_set_length(&refrc, n, k, _state);
ae_matrix_set_length(&refcc, n, k, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=k-1; j++)
{
refrc.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
refcc.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
refcc.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
/*
* test different types of operations, offsets, and so on...
*
* to avoid unnecessary slowdown we don't test ALL possible
* combinations of operation types. We just generate one random
* set of parameters and test it.
*/
ae_matrix_set_length(&ra1, 2*n, 2*n, _state);
ae_matrix_set_length(&ra2, 2*n, 2*n, _state);
ae_matrix_set_length(&ca1, 2*n, 2*n, _state);
ae_matrix_set_length(&ca2, 2*n, 2*n, _state);
ae_matrix_set_length(&rc, n, k, _state);
ae_matrix_set_length(&rct, k, n, _state);
ae_matrix_set_length(&cc, n, k, _state);
ae_matrix_set_length(&cct, k, n, _state);
uppertype = ae_randominteger(2, _state);
xoffsi = ae_randominteger(2, _state);
xoffsj = ae_randominteger(2, _state);
aoffsitype = ae_randominteger(2, _state);
aoffsjtype = ae_randominteger(2, _state);
alphatype = ae_randominteger(2, _state);
betatype = ae_randominteger(2, _state);
aoffsi = n*aoffsitype;
aoffsj = n*aoffsjtype;
alpha = alphatype*(2*ae_randomreal(_state)-1);
beta = betatype*(2*ae_randomreal(_state)-1);
/*
* copy A, C (fill unused parts with random garbage)
*/
for(i=0; i<=2*n-1; i++)
{
for(j=0; j<=2*n-1; j++)
{
if( ((i>=aoffsi&&i=aoffsj)&&j=xoffsi&&j>=xoffsj )
{
rc.ptr.pp_double[i][j] = refrc.ptr.pp_double[i][j];
rct.ptr.pp_double[j][i] = refrc.ptr.pp_double[i][j];
cc.ptr.pp_complex[i][j] = refcc.ptr.pp_complex[i][j];
cct.ptr.pp_complex[j][i] = refcc.ptr.pp_complex[i][j];
}
else
{
rc.ptr.pp_double[i][j] = ae_randomreal(_state);
rct.ptr.pp_double[j][i] = rc.ptr.pp_double[i][j];
cc.ptr.pp_complex[i][j] = ae_complex_from_d(ae_randomreal(_state));
cct.ptr.pp_complex[j][i] = cct.ptr.pp_complex[j][i];
}
}
}
/*
* Test complex
* Only one of transform types is selected and tested
*/
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
cmatrixherk(n-xoffsi, k-xoffsj, alpha, &cc, xoffsi, xoffsj, 0, beta, &ca1, aoffsi, aoffsj, uppertype==0, _state);
testablasunit_refcmatrixherk(n-xoffsi, k-xoffsj, alpha, &cc, xoffsi, xoffsj, 0, beta, &ca2, aoffsi, aoffsj, uppertype==0, _state);
}
else
{
cmatrixherk(n-xoffsi, k-xoffsj, alpha, &cct, xoffsj, xoffsi, 2, beta, &ca1, aoffsi, aoffsj, uppertype==0, _state);
testablasunit_refcmatrixherk(n-xoffsi, k-xoffsj, alpha, &cct, xoffsj, xoffsi, 2, beta, &ca2, aoffsi, aoffsj, uppertype==0, _state);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
result = result||ae_fp_greater(ae_c_abs(ae_c_sub(ca1.ptr.pp_complex[i][j],ca2.ptr.pp_complex[i][j]), _state),threshold);
}
}
/*
* Test old version of HERK (named SYRK)
* Only one of transform types is selected and tested
*/
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
cmatrixsyrk(n-xoffsi, k-xoffsj, alpha, &cc, xoffsi, xoffsj, 0, beta, &ca1, aoffsi, aoffsj, uppertype==0, _state);
testablasunit_refcmatrixherk(n-xoffsi, k-xoffsj, alpha, &cc, xoffsi, xoffsj, 0, beta, &ca2, aoffsi, aoffsj, uppertype==0, _state);
}
else
{
cmatrixsyrk(n-xoffsi, k-xoffsj, alpha, &cct, xoffsj, xoffsi, 2, beta, &ca1, aoffsi, aoffsj, uppertype==0, _state);
testablasunit_refcmatrixherk(n-xoffsi, k-xoffsj, alpha, &cct, xoffsj, xoffsi, 2, beta, &ca2, aoffsi, aoffsj, uppertype==0, _state);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
result = result||ae_fp_greater(ae_c_abs(ae_c_sub(ca1.ptr.pp_complex[i][j],ca2.ptr.pp_complex[i][j]), _state),threshold);
}
}
/*
* Test real
* Only one of transform types is selected and tested
*/
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
rmatrixsyrk(n-xoffsi, k-xoffsj, alpha, &rc, xoffsi, xoffsj, 0, beta, &ra1, aoffsi, aoffsj, uppertype==0, _state);
testablasunit_refrmatrixsyrk(n-xoffsi, k-xoffsj, alpha, &rc, xoffsi, xoffsj, 0, beta, &ra2, aoffsi, aoffsj, uppertype==0, _state);
}
else
{
rmatrixsyrk(n-xoffsi, k-xoffsj, alpha, &rct, xoffsj, xoffsi, 1, beta, &ra1, aoffsi, aoffsj, uppertype==0, _state);
testablasunit_refrmatrixsyrk(n-xoffsi, k-xoffsj, alpha, &rct, xoffsj, xoffsi, 1, beta, &ra2, aoffsi, aoffsj, uppertype==0, _state);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
result = result||ae_fp_greater(ae_fabs(ra1.ptr.pp_double[i][j]-ra2.ptr.pp_double[i][j], _state),threshold);
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
GEMM tests
Returns False for passed test, True - for failed
*************************************************************************/
static ae_bool testablasunit_testgemm(ae_int_t minn,
ae_int_t maxn,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t m;
ae_int_t n;
ae_int_t k;
ae_int_t mx;
ae_int_t i;
ae_int_t j;
ae_int_t aoffsi;
ae_int_t aoffsj;
ae_int_t aoptype;
ae_int_t aoptyper;
ae_int_t boffsi;
ae_int_t boffsj;
ae_int_t boptype;
ae_int_t boptyper;
ae_int_t coffsi;
ae_int_t coffsj;
ae_matrix refra;
ae_matrix refrb;
ae_matrix refrc;
ae_matrix refca;
ae_matrix refcb;
ae_matrix refcc;
double alphar;
double betar;
ae_complex alphac;
ae_complex betac;
ae_matrix rc1;
ae_matrix rc2;
ae_matrix cc1;
ae_matrix cc2;
double threshold;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&refra, 0, sizeof(refra));
memset(&refrb, 0, sizeof(refrb));
memset(&refrc, 0, sizeof(refrc));
memset(&refca, 0, sizeof(refca));
memset(&refcb, 0, sizeof(refcb));
memset(&refcc, 0, sizeof(refcc));
memset(&rc1, 0, sizeof(rc1));
memset(&rc2, 0, sizeof(rc2));
memset(&cc1, 0, sizeof(cc1));
memset(&cc2, 0, sizeof(cc2));
ae_matrix_init(&refra, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&refrb, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&refrc, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&refca, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&refcb, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&refcc, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&rc1, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&rc2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&cc1, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&cc2, 0, 0, DT_COMPLEX, _state, ae_true);
threshold = maxn*100*ae_machineepsilon;
result = ae_false;
for(mx=minn; mx<=maxn; mx++)
{
/*
* Select random M/N/K in [1,MX] such that max(M,N,K)=MX
*/
m = 1+ae_randominteger(mx, _state);
n = 1+ae_randominteger(mx, _state);
k = 1+ae_randominteger(mx, _state);
i = ae_randominteger(3, _state);
if( i==0 )
{
m = mx;
}
if( i==1 )
{
n = mx;
}
if( i==2 )
{
k = mx;
}
/*
* Initialize A/B/C by random matrices with size (MaxN+1)*(MaxN+1)
*/
ae_matrix_set_length(&refra, maxn+1, maxn+1, _state);
ae_matrix_set_length(&refrb, maxn+1, maxn+1, _state);
ae_matrix_set_length(&refrc, maxn+1, maxn+1, _state);
ae_matrix_set_length(&refca, maxn+1, maxn+1, _state);
ae_matrix_set_length(&refcb, maxn+1, maxn+1, _state);
ae_matrix_set_length(&refcc, maxn+1, maxn+1, _state);
for(i=0; i<=maxn; i++)
{
for(j=0; j<=maxn; j++)
{
refra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
refrb.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
refrc.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
refca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
refca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
refcb.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
refcb.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
refcc.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
refcc.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
/*
* test different types of operations, offsets, and so on...
*
* to avoid unnecessary slowdown we don't test ALL possible
* combinations of operation types. We just generate one random
* set of parameters and test it.
*/
ae_matrix_set_length(&rc1, maxn+1, maxn+1, _state);
ae_matrix_set_length(&rc2, maxn+1, maxn+1, _state);
ae_matrix_set_length(&cc1, maxn+1, maxn+1, _state);
ae_matrix_set_length(&cc2, maxn+1, maxn+1, _state);
aoffsi = ae_randominteger(2, _state);
aoffsj = ae_randominteger(2, _state);
aoptype = ae_randominteger(3, _state);
aoptyper = ae_randominteger(2, _state);
boffsi = ae_randominteger(2, _state);
boffsj = ae_randominteger(2, _state);
boptype = ae_randominteger(3, _state);
boptyper = ae_randominteger(2, _state);
coffsi = ae_randominteger(2, _state);
coffsj = ae_randominteger(2, _state);
alphar = ae_randominteger(2, _state)*(2*ae_randomreal(_state)-1);
betar = ae_randominteger(2, _state)*(2*ae_randomreal(_state)-1);
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
alphac.x = 2*ae_randomreal(_state)-1;
alphac.y = 2*ae_randomreal(_state)-1;
}
else
{
alphac = ae_complex_from_i(0);
}
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
betac.x = 2*ae_randomreal(_state)-1;
betac.y = 2*ae_randomreal(_state)-1;
}
else
{
betac = ae_complex_from_i(0);
}
/*
* copy C
*/
for(i=0; i<=maxn; i++)
{
for(j=0; j<=maxn; j++)
{
rc1.ptr.pp_double[i][j] = refrc.ptr.pp_double[i][j];
rc2.ptr.pp_double[i][j] = refrc.ptr.pp_double[i][j];
cc1.ptr.pp_complex[i][j] = refcc.ptr.pp_complex[i][j];
cc2.ptr.pp_complex[i][j] = refcc.ptr.pp_complex[i][j];
}
}
/*
* Test complex
*/
cmatrixgemm(m, n, k, alphac, &refca, aoffsi, aoffsj, aoptype, &refcb, boffsi, boffsj, boptype, betac, &cc1, coffsi, coffsj, _state);
testablasunit_refcmatrixgemm(m, n, k, alphac, &refca, aoffsi, aoffsj, aoptype, &refcb, boffsi, boffsj, boptype, betac, &cc2, coffsi, coffsj, _state);
for(i=0; i<=maxn; i++)
{
for(j=0; j<=maxn; j++)
{
result = result||ae_fp_greater(ae_c_abs(ae_c_sub(cc1.ptr.pp_complex[i][j],cc2.ptr.pp_complex[i][j]), _state),threshold);
}
}
/*
* Test real
*/
rmatrixgemm(m, n, k, alphar, &refra, aoffsi, aoffsj, aoptyper, &refrb, boffsi, boffsj, boptyper, betar, &rc1, coffsi, coffsj, _state);
testablasunit_refrmatrixgemm(m, n, k, alphar, &refra, aoffsi, aoffsj, aoptyper, &refrb, boffsi, boffsj, boptyper, betar, &rc2, coffsi, coffsj, _state);
for(i=0; i<=maxn; i++)
{
for(j=0; j<=maxn; j++)
{
result = result||ae_fp_greater(ae_fabs(rc1.ptr.pp_double[i][j]-rc2.ptr.pp_double[i][j], _state),threshold);
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
transpose tests
Returns False for passed test, True - for failed
*************************************************************************/
static ae_bool testablasunit_testtrans(ae_int_t minn,
ae_int_t maxn,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t m;
ae_int_t n;
ae_int_t mx;
ae_int_t i;
ae_int_t j;
ae_int_t aoffsi;
ae_int_t aoffsj;
ae_int_t boffsi;
ae_int_t boffsj;
double v1;
double v2;
double threshold;
ae_matrix refra;
ae_matrix refrb;
ae_matrix refca;
ae_matrix refcb;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&refra, 0, sizeof(refra));
memset(&refrb, 0, sizeof(refrb));
memset(&refca, 0, sizeof(refca));
memset(&refcb, 0, sizeof(refcb));
ae_matrix_init(&refra, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&refrb, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&refca, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&refcb, 0, 0, DT_COMPLEX, _state, ae_true);
result = ae_false;
threshold = 1000*ae_machineepsilon;
for(mx=minn; mx<=maxn; mx++)
{
/*
* Select random M/N in [1,MX] such that max(M,N)=MX
* Generate random V1 and V2 which are used to fill
* RefRB/RefCB with control values.
*/
m = 1+ae_randominteger(mx, _state);
n = 1+ae_randominteger(mx, _state);
if( ae_randominteger(2, _state)==0 )
{
m = mx;
}
else
{
n = mx;
}
v1 = ae_randomreal(_state);
v2 = ae_randomreal(_state);
/*
* Initialize A by random matrix with size (MaxN+1)*(MaxN+1)
* Fill B with control values
*/
ae_matrix_set_length(&refra, maxn+1, maxn+1, _state);
ae_matrix_set_length(&refrb, maxn+1, maxn+1, _state);
ae_matrix_set_length(&refca, maxn+1, maxn+1, _state);
ae_matrix_set_length(&refcb, maxn+1, maxn+1, _state);
for(i=0; i<=maxn; i++)
{
for(j=0; j<=maxn; j++)
{
refra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
refca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
refca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
refrb.ptr.pp_double[i][j] = i*v1+j*v2;
refcb.ptr.pp_complex[i][j] = ae_complex_from_d(i*v1+j*v2);
}
}
/*
* test different offsets (zero or one)
*
* to avoid unnecessary slowdown we don't test ALL possible
* combinations of operation types. We just generate one random
* set of parameters and test it.
*/
aoffsi = ae_randominteger(2, _state);
aoffsj = ae_randominteger(2, _state);
boffsi = ae_randominteger(2, _state);
boffsj = ae_randominteger(2, _state);
rmatrixtranspose(m, n, &refra, aoffsi, aoffsj, &refrb, boffsi, boffsj, _state);
for(i=0; i<=maxn; i++)
{
for(j=0; j<=maxn; j++)
{
if( ((i=boffsi+n)||j=boffsj+m )
{
result = result||ae_fp_greater(ae_fabs(refrb.ptr.pp_double[i][j]-(v1*i+v2*j), _state),threshold);
}
else
{
result = result||ae_fp_greater(ae_fabs(refrb.ptr.pp_double[i][j]-refra.ptr.pp_double[aoffsi+j-boffsj][aoffsj+i-boffsi], _state),threshold);
}
}
}
cmatrixtranspose(m, n, &refca, aoffsi, aoffsj, &refcb, boffsi, boffsj, _state);
for(i=0; i<=maxn; i++)
{
for(j=0; j<=maxn; j++)
{
if( ((i=boffsi+n)||j=boffsj+m )
{
result = result||ae_fp_greater(ae_c_abs(ae_c_sub_d(refcb.ptr.pp_complex[i][j],v1*i+v2*j), _state),threshold);
}
else
{
result = result||ae_fp_greater(ae_c_abs(ae_c_sub(refcb.ptr.pp_complex[i][j],refca.ptr.pp_complex[aoffsi+j-boffsj][aoffsj+i-boffsi]), _state),threshold);
}
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
rank-1tests
Returns False for passed test, True - for failed
*************************************************************************/
static ae_bool testablasunit_testrank1(ae_int_t minn,
ae_int_t maxn,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t m;
ae_int_t n;
ae_int_t mx;
ae_int_t i;
ae_int_t j;
ae_int_t aoffsi;
ae_int_t aoffsj;
ae_int_t uoffs;
ae_int_t voffs;
double threshold;
double ralpha;
ae_matrix refra;
ae_matrix refrb;
ae_matrix refca;
ae_matrix refcb;
ae_vector ru;
ae_vector rv;
ae_vector cu;
ae_vector cv;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&refra, 0, sizeof(refra));
memset(&refrb, 0, sizeof(refrb));
memset(&refca, 0, sizeof(refca));
memset(&refcb, 0, sizeof(refcb));
memset(&ru, 0, sizeof(ru));
memset(&rv, 0, sizeof(rv));
memset(&cu, 0, sizeof(cu));
memset(&cv, 0, sizeof(cv));
ae_matrix_init(&refra, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&refrb, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&refca, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&refcb, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&ru, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rv, 0, DT_REAL, _state, ae_true);
ae_vector_init(&cu, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&cv, 0, DT_COMPLEX, _state, ae_true);
result = ae_false;
threshold = 1000*ae_machineepsilon;
for(mx=minn; mx<=maxn; mx++)
{
/*
* Select random M/N in [1,MX] such that max(M,N)=MX
*/
m = 1+ae_randominteger(mx, _state);
n = 1+ae_randominteger(mx, _state);
if( ae_randominteger(2, _state)==0 )
{
m = mx;
}
else
{
n = mx;
}
/*
* Initialize A by random matrix with size (MaxN+1)*(MaxN+1)
* Fill B with control values
*/
ae_matrix_set_length(&refra, maxn+maxn, maxn+maxn, _state);
ae_matrix_set_length(&refrb, maxn+maxn, maxn+maxn, _state);
ae_matrix_set_length(&refca, maxn+maxn, maxn+maxn, _state);
ae_matrix_set_length(&refcb, maxn+maxn, maxn+maxn, _state);
for(i=0; i<=2*maxn-1; i++)
{
for(j=0; j<=2*maxn-1; j++)
{
refrb.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
refcb.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
refcb.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
ae_vector_set_length(&ru, 2*m, _state);
ae_vector_set_length(&cu, 2*m, _state);
for(i=0; i<=2*m-1; i++)
{
ru.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
cu.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1;
cu.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1;
}
ae_vector_set_length(&rv, 2*n, _state);
ae_vector_set_length(&cv, 2*n, _state);
for(i=0; i<=2*n-1; i++)
{
rv.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
cv.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1;
cv.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1;
}
/*
* Generate random offsets of all operands and random coefficients.
*/
aoffsi = ae_randominteger(maxn, _state);
aoffsj = ae_randominteger(maxn, _state);
uoffs = ae_randominteger(m, _state);
voffs = ae_randominteger(n, _state);
ralpha = ae_randomreal(_state)-0.5;
/*
* Test CMatrixRank1() and deprecated RMatrixRank1()
*/
for(i=0; i<=2*maxn-1; i++)
{
for(j=0; j<=2*maxn-1; j++)
{
refca.ptr.pp_complex[i][j] = refcb.ptr.pp_complex[i][j];
}
}
cmatrixrank1(m, n, &refca, aoffsi, aoffsj, &cu, uoffs, &cv, voffs, _state);
for(i=0; i<=2*maxn-1; i++)
{
for(j=0; j<=2*maxn-1; j++)
{
if( ((i=aoffsi+m)||j=aoffsj+n )
{
result = result||ae_fp_greater(ae_c_abs(ae_c_sub(refca.ptr.pp_complex[i][j],refcb.ptr.pp_complex[i][j]), _state),threshold);
}
else
{
result = result||ae_fp_greater(ae_c_abs(ae_c_sub(refca.ptr.pp_complex[i][j],ae_c_add(refcb.ptr.pp_complex[i][j],ae_c_mul(cu.ptr.p_complex[i-aoffsi+uoffs],cv.ptr.p_complex[j-aoffsj+voffs]))), _state),threshold);
}
}
}
for(i=0; i<=2*maxn-1; i++)
{
for(j=0; j<=2*maxn-1; j++)
{
refra.ptr.pp_double[i][j] = refrb.ptr.pp_double[i][j];
}
}
rmatrixrank1(m, n, &refra, aoffsi, aoffsj, &ru, uoffs, &rv, voffs, _state);
for(i=0; i<=2*maxn-1; i++)
{
for(j=0; j<=2*maxn-1; j++)
{
if( ((i=aoffsi+m)||j=aoffsj+n )
{
result = result||ae_fp_greater(ae_fabs(refra.ptr.pp_double[i][j]-refrb.ptr.pp_double[i][j], _state),threshold);
}
else
{
result = result||ae_fp_greater(ae_fabs(refra.ptr.pp_double[i][j]-(refrb.ptr.pp_double[i][j]+ru.ptr.p_double[i-aoffsi+uoffs]*rv.ptr.p_double[j-aoffsj+voffs]), _state),threshold);
}
}
}
/*
* Test modern RMatrixGER()
*/
for(i=0; i<=2*maxn-1; i++)
{
for(j=0; j<=2*maxn-1; j++)
{
refra.ptr.pp_double[i][j] = refrb.ptr.pp_double[i][j];
}
}
rmatrixger(m, n, &refra, aoffsi, aoffsj, ralpha, &ru, uoffs, &rv, voffs, _state);
for(i=0; i<=2*maxn-1; i++)
{
for(j=0; j<=2*maxn-1; j++)
{
if( ((i=aoffsi+m)||j=aoffsj+n )
{
ae_set_error_flag(&result, ae_fp_neq(ae_fabs(refra.ptr.pp_double[i][j]-refrb.ptr.pp_double[i][j], _state),0.0), __FILE__, __LINE__, "testablasunit.ap:1132");
}
else
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(refra.ptr.pp_double[i][j]-(refrb.ptr.pp_double[i][j]+ralpha*ru.ptr.p_double[i-aoffsi+uoffs]*rv.ptr.p_double[j-aoffsj+voffs]), _state),threshold), __FILE__, __LINE__, "testablasunit.ap:1134");
}
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
MV tests
Returns False for passed test, True - for failed
*************************************************************************/
static ae_bool testablasunit_testgemv(ae_int_t minn,
ae_int_t maxn,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t m;
ae_int_t n;
ae_int_t mx;
ae_int_t i;
ae_int_t j;
ae_int_t aoffsi;
ae_int_t aoffsj;
ae_int_t xoffs;
ae_int_t yoffs;
ae_int_t opca;
ae_int_t opra;
double threshold;
double ralpha;
double rbeta;
double rv1;
double rv2;
ae_complex cv1;
ae_complex cv2;
ae_matrix refra;
ae_matrix refca;
ae_vector rx;
ae_vector ry;
ae_vector cx;
ae_vector cy;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&refra, 0, sizeof(refra));
memset(&refca, 0, sizeof(refca));
memset(&rx, 0, sizeof(rx));
memset(&ry, 0, sizeof(ry));
memset(&cx, 0, sizeof(cx));
memset(&cy, 0, sizeof(cy));
ae_matrix_init(&refra, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&refca, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&rx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ry, 0, DT_REAL, _state, ae_true);
ae_vector_init(&cx, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&cy, 0, DT_COMPLEX, _state, ae_true);
result = ae_false;
threshold = 1000*ae_machineepsilon;
for(mx=minn; mx<=maxn; mx++)
{
/*
* Select random M/N in [1,MX] such that max(M,N)=MX
*/
m = 1+ae_randominteger(mx, _state);
n = 1+ae_randominteger(mx, _state);
if( ae_randominteger(2, _state)==0 )
{
m = mx;
}
else
{
n = mx;
}
/*
* Initialize A by random matrix with size (MaxN+MaxN)*(MaxN+MaxN)
* Initialize X by random vector with size (MaxN+MaxN)
* Fill Y by control values
*/
ae_matrix_set_length(&refra, maxn+maxn, maxn+maxn, _state);
ae_matrix_set_length(&refca, maxn+maxn, maxn+maxn, _state);
for(i=0; i<=2*maxn-1; i++)
{
for(j=0; j<=2*maxn-1; j++)
{
refra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
refca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
refca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
ae_vector_set_length(&rx, 2*maxn, _state);
ae_vector_set_length(&cx, 2*maxn, _state);
ae_vector_set_length(&ry, 2*maxn, _state);
ae_vector_set_length(&cy, 2*maxn, _state);
for(i=0; i<=2*maxn-1; i++)
{
rx.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
cx.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1;
cx.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1;
}
/*
* Select random offsets and operations.
*
* To avoid unnecessary slowdown we don't test ALL possible
* combinations of operation types. We just generate one random
* set of parameters and test it.
*/
aoffsi = ae_randominteger(maxn, _state);
aoffsj = ae_randominteger(maxn, _state);
xoffs = ae_randominteger(maxn, _state);
yoffs = ae_randominteger(maxn, _state);
opca = ae_randominteger(3, _state);
opra = ae_randominteger(2, _state);
ralpha = (ae_randomreal(_state)-0.5)*ae_randominteger(2, _state);
rbeta = (ae_randomreal(_state)-0.5)*ae_randominteger(2, _state);
/*
* Test CMatrixMV and deprecated RMatrixMV
*/
for(i=0; i<=2*maxn-1; i++)
{
cy.ptr.p_complex[i] = ae_complex_from_i(i);
}
cmatrixmv(m, n, &refca, aoffsi, aoffsj, opca, &cx, xoffs, &cy, yoffs, _state);
for(i=0; i<=2*maxn-1; i++)
{
if( i=yoffs+m )
{
result = result||ae_c_neq_d(cy.ptr.p_complex[i],(double)(i));
}
else
{
cv1 = cy.ptr.p_complex[i];
cv2 = ae_complex_from_d(0.0);
if( opca==0 )
{
cv2 = ae_v_cdotproduct(&refca.ptr.pp_complex[aoffsi+i-yoffs][aoffsj], 1, "N", &cx.ptr.p_complex[xoffs], 1, "N", ae_v_len(aoffsj,aoffsj+n-1));
}
if( opca==1 )
{
cv2 = ae_v_cdotproduct(&refca.ptr.pp_complex[aoffsi][aoffsj+i-yoffs], refca.stride, "N", &cx.ptr.p_complex[xoffs], 1, "N", ae_v_len(aoffsi,aoffsi+n-1));
}
if( opca==2 )
{
cv2 = ae_v_cdotproduct(&refca.ptr.pp_complex[aoffsi][aoffsj+i-yoffs], refca.stride, "Conj", &cx.ptr.p_complex[xoffs], 1, "N", ae_v_len(aoffsi,aoffsi+n-1));
}
result = result||ae_fp_greater(ae_c_abs(ae_c_sub(cv1,cv2), _state),threshold);
}
}
for(i=0; i<=2*maxn-1; i++)
{
ry.ptr.p_double[i] = (double)(i);
}
rmatrixmv(m, n, &refra, aoffsi, aoffsj, opra, &rx, xoffs, &ry, yoffs, _state);
for(i=0; i<=2*maxn-1; i++)
{
if( i=yoffs+m )
{
result = result||ae_fp_neq(ry.ptr.p_double[i],(double)(i));
}
else
{
rv1 = ry.ptr.p_double[i];
rv2 = (double)(0);
if( opra==0 )
{
rv2 = ae_v_dotproduct(&refra.ptr.pp_double[aoffsi+i-yoffs][aoffsj], 1, &rx.ptr.p_double[xoffs], 1, ae_v_len(aoffsj,aoffsj+n-1));
}
if( opra==1 )
{
rv2 = ae_v_dotproduct(&refra.ptr.pp_double[aoffsi][aoffsj+i-yoffs], refra.stride, &rx.ptr.p_double[xoffs], 1, ae_v_len(aoffsi,aoffsi+n-1));
}
result = result||ae_fp_greater(ae_fabs(rv1-rv2, _state),threshold);
}
}
/*
* Test modern RMatrixGEMV()
*/
for(i=0; i<=2*maxn-1; i++)
{
ry.ptr.p_double[i] = (double)(i);
}
rmatrixgemv(m, n, ralpha, &refra, aoffsi, aoffsj, opra, &rx, xoffs, rbeta, &ry, yoffs, _state);
for(i=0; i<=2*maxn-1; i++)
{
if( i=yoffs+m )
{
ae_set_error_flag(&result, ae_fp_neq(ry.ptr.p_double[i],(double)(i)), __FILE__, __LINE__, "testablasunit.ap:1282");
}
else
{
rv1 = ry.ptr.p_double[i];
rv2 = (double)(0);
if( opra==0 )
{
rv2 = ae_v_dotproduct(&refra.ptr.pp_double[aoffsi+i-yoffs][aoffsj], 1, &rx.ptr.p_double[xoffs], 1, ae_v_len(aoffsj,aoffsj+n-1));
}
if( opra==1 )
{
rv2 = ae_v_dotproduct(&refra.ptr.pp_double[aoffsi][aoffsj+i-yoffs], refra.stride, &rx.ptr.p_double[xoffs], 1, ae_v_len(aoffsi,aoffsi+n-1));
}
rv2 = rbeta*i+ralpha*rv2;
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(rv1-rv2, _state),threshold), __FILE__, __LINE__, "testablasunit.ap:1292");
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
SYMV/SYVMV tests
Sets error flag on failure, ignores on success.
*************************************************************************/
static void testablasunit_testsymv(ae_int_t minn,
ae_int_t maxn,
ae_bool* errorflag,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_int_t aoffsi;
ae_int_t aoffsj;
ae_int_t xoffs;
ae_int_t yoffs;
ae_bool isuppera;
double threshold;
double ralpha;
double rbeta;
double rv1;
double rv2;
ae_matrix refra;
ae_vector rx;
ae_vector ry;
ae_vector rz;
ae_frame_make(_state, &_frame_block);
memset(&refra, 0, sizeof(refra));
memset(&rx, 0, sizeof(rx));
memset(&ry, 0, sizeof(ry));
memset(&rz, 0, sizeof(rz));
ae_matrix_init(&refra, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ry, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rz, 0, DT_REAL, _state, ae_true);
threshold = 1000*ae_machineepsilon;
for(n=minn; n<=maxn; n++)
{
/*
* Initialize A by random matrix with size (MaxN+MaxN)*(MaxN+MaxN)
* Initialize X by random vector with size (MaxN+MaxN)
* Fill Y by control values
*/
ae_matrix_set_length(&refra, maxn+maxn, maxn+maxn, _state);
for(i=0; i<=2*maxn-1; i++)
{
for(j=0; j<=2*maxn-1; j++)
{
refra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
ae_vector_set_length(&rx, 2*maxn, _state);
ae_vector_set_length(&ry, 2*maxn, _state);
ae_vector_set_length(&rz, 2*maxn, _state);
for(i=0; i<=2*maxn-1; i++)
{
rx.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
/*
* Select random offsets and operations.
*
* To avoid unnecessary slowdown we don't test ALL possible
* combinations of operation types. We just generate one random
* set of parameters and test it.
*/
aoffsi = ae_randominteger(maxn, _state);
aoffsj = ae_randominteger(maxn, _state);
xoffs = ae_randominteger(maxn, _state);
yoffs = ae_randominteger(maxn, _state);
isuppera = ae_fp_greater(ae_randomreal(_state),0.5);
ralpha = (ae_randomreal(_state)-0.5)*ae_randominteger(2, _state);
rbeta = (ae_randomreal(_state)-0.5)*ae_randominteger(2, _state);
/*
* Test RMatrixSYMV()
*/
for(i=0; i<=2*maxn-1; i++)
{
ry.ptr.p_double[i] = (double)(i);
rz.ptr.p_double[i] = (double)(i);
}
rmatrixsymv(n, ralpha, &refra, aoffsi, aoffsj, isuppera, &rx, xoffs, rbeta, &ry, yoffs, _state);
testablasunit_refrmatrixsymv(n, ralpha, &refra, aoffsi, aoffsj, isuppera, &rx, xoffs, rbeta, &rz, yoffs, _state);
for(i=0; i<=2*maxn-1; i++)
{
if( i=yoffs+n )
{
ae_set_error_flag(errorflag, ae_fp_neq(ry.ptr.p_double[i],(double)(i)), __FILE__, __LINE__, "testablasunit.ap:1380");
}
else
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(ry.ptr.p_double[i]-rz.ptr.p_double[i], _state),threshold*maxreal3(ae_fabs(ry.ptr.p_double[i], _state), ae_fabs(rz.ptr.p_double[i], _state), 1.0, _state)), __FILE__, __LINE__, "testablasunit.ap:1382");
}
}
/*
* Test RMatrixSYVMV()
*/
rv1 = rmatrixsyvmv(n, &refra, aoffsi, aoffsj, isuppera, &rx, xoffs, &ry, _state);
rv2 = testablasunit_refrmatrixsyvmv(n, &refra, aoffsi, aoffsj, isuppera, &rx, xoffs, _state);
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(rv1-rv2, _state),threshold*maxreal3(ae_fabs(rv1, _state), ae_fabs(rv2, _state), 1.0, _state)), __FILE__, __LINE__, "testablasunit.ap:1396");
}
ae_frame_leave(_state);
}
/*************************************************************************
TRSV tests
Sets error flag on failure, ignores on success.
*************************************************************************/
static void testablasunit_testtrsv(ae_int_t minn,
ae_int_t maxn,
ae_bool* errorflag,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_int_t aoffsi;
ae_int_t aoffsj;
ae_int_t xoffs;
ae_bool isuppera;
ae_bool isunita;
ae_int_t opa;
double threshold;
ae_matrix refra;
ae_matrix ea;
ae_vector rx;
ae_vector ry;
double v;
ae_frame_make(_state, &_frame_block);
memset(&refra, 0, sizeof(refra));
memset(&ea, 0, sizeof(ea));
memset(&rx, 0, sizeof(rx));
memset(&ry, 0, sizeof(ry));
ae_matrix_init(&refra, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ea, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ry, 0, DT_REAL, _state, ae_true);
for(n=minn; n<=maxn; n++)
{
/*
* Decreased threshold because of ill-conditioning of randomly generated matrices
*/
threshold = 1.0E-6*(1+n);
/*
* Initialize A by random matrix with size (MaxN+MaxN)*(MaxN+MaxN)
* Initialize X by sparse random vector with size (MaxN+MaxN) (sparsity is important to test some branches of algorithm)
* Fill Y by control values
*/
ae_matrix_set_length(&refra, maxn+maxn, maxn+maxn, _state);
for(i=0; i<=2*maxn-1; i++)
{
for(j=0; j<=2*maxn-1; j++)
{
refra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
ae_vector_set_length(&rx, 2*maxn, _state);
ae_vector_set_length(&ry, 2*maxn, _state);
for(i=0; i<=2*maxn-1; i++)
{
rx.ptr.p_double[i] = (2*ae_randomreal(_state)-1)*ae_randominteger(3, _state);
}
/*
* Select random offsets and operations.
*
* To avoid unnecessary slowdown we don't test ALL possible
* combinations of operation types. We just generate one random
* set of parameters and test it.
*
* NOTE: in order to improve conditioning properties we add 10*Identity
* to purported diagonal of A
*/
aoffsi = ae_randominteger(maxn, _state);
aoffsj = ae_randominteger(maxn, _state);
xoffs = ae_randominteger(maxn, _state);
isuppera = ae_fp_greater(ae_randomreal(_state),0.5);
isunita = ae_fp_greater(ae_randomreal(_state),0.5);
opa = ae_randominteger(2, _state);
for(i=0; i<=n-1; i++)
{
refra.ptr.pp_double[aoffsi+i][aoffsj+i] = refra.ptr.pp_double[aoffsi+i][aoffsj+i]+10;
}
/*
* Test RMatrixTRSV():
* * check that elements of RX beyond [XOffs,XOffs+N-1] are unchanged
* * calculate RX:=TRSV(RX)
* * extract effective A from RefRA to EA=array[N,N]
* * compare product EA*RX, compare with copy of RX stored in RY
*/
for(i=0; i<=2*maxn-1; i++)
{
ry.ptr.p_double[i] = rx.ptr.p_double[i];
}
rmatrixtrsv(n, &refra, aoffsi, aoffsj, isuppera, isunita, opa, &rx, xoffs, _state);
for(i=0; i<=2*maxn-1; i++)
{
if( ixoffs+n-1 )
{
ae_set_error_flag(errorflag, ae_fp_neq(rx.ptr.p_double[i],ry.ptr.p_double[i]), __FILE__, __LINE__, "testablasunit.ap:1480");
}
}
ae_matrix_set_length(&ea, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = refra.ptr.pp_double[aoffsi+i][aoffsj+j];
if( (ji&&!isuppera) )
{
v = (double)(0);
}
if( isunita&&i==j )
{
v = (double)(1);
}
if( opa==0 )
{
ea.ptr.pp_double[i][j] = v;
}
else
{
ea.ptr.pp_double[j][i] = v;
}
}
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&ea.ptr.pp_double[i][0], 1, &rx.ptr.p_double[xoffs], 1, ae_v_len(0,n-1));
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v-ry.ptr.p_double[xoffs+i], _state),threshold), __FILE__, __LINE__, "testablasunit.ap:1503");
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Special test.
On failure sets error flag, on success does not change it.
*************************************************************************/
static void testablasunit_spectest(ae_bool* errorflag, ae_state *_state)
{
ae_frame _frame_block;
ae_matrix emptyr2;
ae_matrix emptyc2;
ae_matrix outputr2;
ae_matrix outputc2;
ae_int_t i;
ae_int_t j;
ae_int_t n;
ae_int_t pass;
ae_frame_make(_state, &_frame_block);
memset(&emptyr2, 0, sizeof(emptyr2));
memset(&emptyc2, 0, sizeof(emptyc2));
memset(&outputr2, 0, sizeof(outputr2));
memset(&outputc2, 0, sizeof(outputc2));
ae_matrix_init(&emptyr2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&emptyc2, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&outputr2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&outputc2, 0, 0, DT_COMPLEX, _state, ae_true);
/*
* Test that SYRK, GEMM and TRSM does not reference empty argument at all.
*
* In order to perform this test we pass empty (unallocated) matrix
* with large offset; incorrect implementation will crash on such data.
*/
n = 128+ae_randominteger(65, _state)-32;
ae_matrix_set_length(&outputr2, n, n, _state);
ae_matrix_set_length(&outputc2, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
outputr2.ptr.pp_double[i][j] = (double)(0);
outputc2.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
for(pass=0; pass<=10; pass++)
{
rmatrixgemm(n, n, 0, 1.0, &emptyr2, 35345, 23453, ae_randominteger(2, _state), &emptyr2, 74764, 26845, ae_randominteger(2, _state), 1.0+ae_randominteger(2, _state), &outputr2, 0, 0, _state);
rmatrixgemm(n, n, n, 0.0, &emptyr2, 35345, 23453, ae_randominteger(2, _state), &emptyr2, 74764, 26845, ae_randominteger(2, _state), 1.0+ae_randominteger(2, _state), &outputr2, 0, 0, _state);
cmatrixgemm(n, n, 0, ae_complex_from_d(1.0), &emptyc2, 35345, 23453, ae_randominteger(3, _state), &emptyc2, 74764, 26845, ae_randominteger(3, _state), ae_complex_from_d(1.0+ae_randominteger(2, _state)), &outputc2, 0, 0, _state);
cmatrixgemm(n, n, n, ae_complex_from_d(0.0), &emptyc2, 35345, 23453, ae_randominteger(3, _state), &emptyc2, 74764, 26845, ae_randominteger(3, _state), ae_complex_from_d(1.0+ae_randominteger(2, _state)), &outputc2, 0, 0, _state);
rmatrixsyrk(n, 0, 1.0, &emptyr2, 54674, 34657, 2*ae_randominteger(2, _state), 1.0+ae_randominteger(2, _state), &outputr2, 0, 0, ae_fp_greater(ae_randomreal(_state),0.5), _state);
rmatrixsyrk(n, n, 0.0, &emptyr2, 54674, 34657, 2*ae_randominteger(2, _state), 1.0+ae_randominteger(2, _state), &outputr2, 0, 0, ae_fp_greater(ae_randomreal(_state),0.5), _state);
cmatrixherk(n, 0, 1.0, &emptyc2, 54674, 34657, 2*ae_randominteger(2, _state), 1.0+ae_randominteger(2, _state), &outputc2, 0, 0, ae_fp_greater(ae_randomreal(_state),0.5), _state);
cmatrixherk(n, n, 0.0, &emptyc2, 54674, 34657, 2*ae_randominteger(2, _state), 1.0+ae_randominteger(2, _state), &outputc2, 0, 0, ae_fp_greater(ae_randomreal(_state),0.5), _state);
rmatrixrighttrsm(0, 0, &emptyr2, 63463, 36345, ae_fp_greater(ae_randomreal(_state),0.5), ae_fp_greater(ae_randomreal(_state),0.5), ae_randominteger(2, _state), &outputr2, 0, 0, _state);
rmatrixlefttrsm(0, 0, &emptyr2, 63463, 36345, ae_fp_greater(ae_randomreal(_state),0.5), ae_fp_greater(ae_randomreal(_state),0.5), ae_randominteger(2, _state), &outputr2, 0, 0, _state);
cmatrixrighttrsm(0, 0, &emptyc2, 63463, 36345, ae_fp_greater(ae_randomreal(_state),0.5), ae_fp_greater(ae_randomreal(_state),0.5), ae_randominteger(3, _state), &outputc2, 0, 0, _state);
cmatrixlefttrsm(0, 0, &emptyc2, 63463, 36345, ae_fp_greater(ae_randomreal(_state),0.5), ae_fp_greater(ae_randomreal(_state),0.5), ae_randominteger(3, _state), &outputc2, 0, 0, _state);
}
ae_frame_leave(_state);
}
/*************************************************************************
COPY tests
Returns False for passed test, True - for failed
*************************************************************************/
static ae_bool testablasunit_testcopy(ae_int_t minn,
ae_int_t maxn,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t m;
ae_int_t n;
ae_int_t mx;
ae_int_t i;
ae_int_t j;
ae_int_t aoffsi;
ae_int_t aoffsj;
ae_int_t boffsi;
ae_int_t boffsj;
double threshold;
ae_matrix ra;
ae_matrix rb;
ae_matrix ca;
ae_matrix cb;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&ra, 0, sizeof(ra));
memset(&rb, 0, sizeof(rb));
memset(&ca, 0, sizeof(ca));
memset(&cb, 0, sizeof(cb));
ae_matrix_init(&ra, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&rb, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ca, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&cb, 0, 0, DT_COMPLEX, _state, ae_true);
result = ae_false;
threshold = 1000*ae_machineepsilon;
for(mx=minn; mx<=maxn; mx++)
{
/*
* Select random M/N in [1,MX] such that max(M,N)=MX
*/
m = 1+ae_randominteger(mx, _state);
n = 1+ae_randominteger(mx, _state);
if( ae_randominteger(2, _state)==0 )
{
m = mx;
}
else
{
n = mx;
}
/*
* Initialize A by random matrix with size (MaxN+MaxN)*(MaxN+MaxN)
* Initialize X by random vector with size (MaxN+MaxN)
* Fill Y by control values
*/
ae_matrix_set_length(&ra, maxn+maxn, maxn+maxn, _state);
ae_matrix_set_length(&ca, maxn+maxn, maxn+maxn, _state);
ae_matrix_set_length(&rb, maxn+maxn, maxn+maxn, _state);
ae_matrix_set_length(&cb, maxn+maxn, maxn+maxn, _state);
for(i=0; i<=2*maxn-1; i++)
{
for(j=0; j<=2*maxn-1; j++)
{
ra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
ca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
ca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
rb.ptr.pp_double[i][j] = (double)(1+2*i+3*j);
cb.ptr.pp_complex[i][j] = ae_complex_from_i(1+2*i+3*j);
}
}
/*
* test different offsets (zero or one)
*
* to avoid unnecessary slowdown we don't test ALL possible
* combinations of operation types. We just generate one random
* set of parameters and test it.
*/
aoffsi = ae_randominteger(maxn, _state);
aoffsj = ae_randominteger(maxn, _state);
boffsi = ae_randominteger(maxn, _state);
boffsj = ae_randominteger(maxn, _state);
cmatrixcopy(m, n, &ca, aoffsi, aoffsj, &cb, boffsi, boffsj, _state);
for(i=0; i<=2*maxn-1; i++)
{
for(j=0; j<=2*maxn-1; j++)
{
if( ((i=boffsi+m)||j=boffsj+n )
{
result = result||ae_c_neq_d(cb.ptr.pp_complex[i][j],(double)(1+2*i+3*j));
}
else
{
result = result||ae_fp_greater(ae_c_abs(ae_c_sub(ca.ptr.pp_complex[aoffsi+i-boffsi][aoffsj+j-boffsj],cb.ptr.pp_complex[i][j]), _state),threshold);
}
}
}
rmatrixcopy(m, n, &ra, aoffsi, aoffsj, &rb, boffsi, boffsj, _state);
for(i=0; i<=2*maxn-1; i++)
{
for(j=0; j<=2*maxn-1; j++)
{
if( ((i=boffsi+m)||j=boffsj+n )
{
result = result||ae_fp_neq(rb.ptr.pp_double[i][j],(double)(1+2*i+3*j));
}
else
{
result = result||ae_fp_greater(ae_fabs(ra.ptr.pp_double[aoffsi+i-boffsi][aoffsj+j-boffsj]-rb.ptr.pp_double[i][j], _state),threshold);
}
}
}
}
ae_frame_leave(_state);
return result;
}
static void testablasunit_testreflections(ae_bool* errorflag,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_int_t n;
ae_int_t m;
ae_int_t maxmn;
ae_vector x;
ae_vector v;
ae_vector work;
ae_matrix h;
ae_matrix a;
ae_matrix b;
ae_matrix c;
double tmp;
double beta;
double tau;
double err;
double mer;
double mel;
double meg;
ae_int_t pass;
ae_int_t passcount;
double threshold;
ae_int_t tasktype;
double xscale;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&v, 0, sizeof(v));
memset(&work, 0, sizeof(work));
memset(&h, 0, sizeof(h));
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
memset(&c, 0, sizeof(c));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&v, 0, DT_REAL, _state, ae_true);
ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&h, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
passcount = 10;
threshold = 100*ae_machineepsilon;
mer = (double)(0);
mel = (double)(0);
meg = (double)(0);
for(pass=1; pass<=passcount; pass++)
{
for(n=1; n<=10; n++)
{
for(m=1; m<=10; m++)
{
/*
* Task
*/
n = 1+ae_randominteger(10, _state);
m = 1+ae_randominteger(10, _state);
maxmn = ae_maxint(m, n, _state);
/*
* Initialize
*/
ae_vector_set_length(&x, maxmn+1, _state);
ae_vector_set_length(&v, maxmn+1, _state);
ae_vector_set_length(&work, maxmn+1, _state);
ae_matrix_set_length(&h, maxmn+1, maxmn+1, _state);
ae_matrix_set_length(&a, maxmn+1, maxmn+1, _state);
ae_matrix_set_length(&b, maxmn+1, maxmn+1, _state);
ae_matrix_set_length(&c, maxmn+1, maxmn+1, _state);
/*
* GenerateReflection, three tasks are possible:
* * random X
* * zero X
* * non-zero X[1], all other are zeros
* * random X, near underflow scale
* * random X, near overflow scale
*/
for(tasktype=0; tasktype<=4; tasktype++)
{
xscale = (double)(1);
if( tasktype==0 )
{
for(i=1; i<=n; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
}
if( tasktype==1 )
{
for(i=1; i<=n; i++)
{
x.ptr.p_double[i] = (double)(0);
}
}
if( tasktype==2 )
{
x.ptr.p_double[1] = 2*ae_randomreal(_state)-1;
for(i=2; i<=n; i++)
{
x.ptr.p_double[i] = (double)(0);
}
}
if( tasktype==3 )
{
for(i=1; i<=n; i++)
{
x.ptr.p_double[i] = (ae_randominteger(21, _state)-10)*ae_minrealnumber;
}
xscale = 10*ae_minrealnumber;
}
if( tasktype==4 )
{
for(i=1; i<=n; i++)
{
x.ptr.p_double[i] = (2*ae_randomreal(_state)-1)*ae_maxrealnumber;
}
xscale = ae_maxrealnumber;
}
ae_v_move(&v.ptr.p_double[1], 1, &x.ptr.p_double[1], 1, ae_v_len(1,n));
generatereflection(&v, n, &tau, _state);
beta = v.ptr.p_double[1];
v.ptr.p_double[1] = (double)(1);
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
if( i==j )
{
h.ptr.pp_double[i][j] = 1-tau*v.ptr.p_double[i]*v.ptr.p_double[j];
}
else
{
h.ptr.pp_double[i][j] = -tau*v.ptr.p_double[i]*v.ptr.p_double[j];
}
}
}
err = (double)(0);
for(i=1; i<=n; i++)
{
tmp = ae_v_dotproduct(&h.ptr.pp_double[i][1], 1, &x.ptr.p_double[1], 1, ae_v_len(1,n));
if( i==1 )
{
err = ae_maxreal(err, ae_fabs(tmp-beta, _state), _state);
}
else
{
err = ae_maxreal(err, ae_fabs(tmp, _state), _state);
}
}
meg = ae_maxreal(meg, err/xscale, _state);
}
/*
* ApplyReflectionFromTheLeft
*/
for(i=1; i<=m; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
v.ptr.p_double[i] = x.ptr.p_double[i];
}
for(i=1; i<=m; i++)
{
for(j=1; j<=n; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
b.ptr.pp_double[i][j] = a.ptr.pp_double[i][j];
}
}
generatereflection(&v, m, &tau, _state);
beta = v.ptr.p_double[1];
v.ptr.p_double[1] = (double)(1);
applyreflectionfromtheleft(&b, tau, &v, 1, m, 1, n, &work, _state);
for(i=1; i<=m; i++)
{
for(j=1; j<=m; j++)
{
if( i==j )
{
h.ptr.pp_double[i][j] = 1-tau*v.ptr.p_double[i]*v.ptr.p_double[j];
}
else
{
h.ptr.pp_double[i][j] = -tau*v.ptr.p_double[i]*v.ptr.p_double[j];
}
}
}
for(i=1; i<=m; i++)
{
for(j=1; j<=n; j++)
{
tmp = ae_v_dotproduct(&h.ptr.pp_double[i][1], 1, &a.ptr.pp_double[1][j], a.stride, ae_v_len(1,m));
c.ptr.pp_double[i][j] = tmp;
}
}
err = (double)(0);
for(i=1; i<=m; i++)
{
for(j=1; j<=n; j++)
{
err = ae_maxreal(err, ae_fabs(b.ptr.pp_double[i][j]-c.ptr.pp_double[i][j], _state), _state);
}
}
mel = ae_maxreal(mel, err, _state);
/*
* ApplyReflectionFromTheRight
*/
for(i=1; i<=n; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
v.ptr.p_double[i] = x.ptr.p_double[i];
}
for(i=1; i<=m; i++)
{
for(j=1; j<=n; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
b.ptr.pp_double[i][j] = a.ptr.pp_double[i][j];
}
}
generatereflection(&v, n, &tau, _state);
beta = v.ptr.p_double[1];
v.ptr.p_double[1] = (double)(1);
applyreflectionfromtheright(&b, tau, &v, 1, m, 1, n, &work, _state);
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
if( i==j )
{
h.ptr.pp_double[i][j] = 1-tau*v.ptr.p_double[i]*v.ptr.p_double[j];
}
else
{
h.ptr.pp_double[i][j] = -tau*v.ptr.p_double[i]*v.ptr.p_double[j];
}
}
}
for(i=1; i<=m; i++)
{
for(j=1; j<=n; j++)
{
tmp = ae_v_dotproduct(&a.ptr.pp_double[i][1], 1, &h.ptr.pp_double[1][j], h.stride, ae_v_len(1,n));
c.ptr.pp_double[i][j] = tmp;
}
}
err = (double)(0);
for(i=1; i<=m; i++)
{
for(j=1; j<=n; j++)
{
err = ae_maxreal(err, ae_fabs(b.ptr.pp_double[i][j]-c.ptr.pp_double[i][j], _state), _state);
}
}
mer = ae_maxreal(mer, err, _state);
}
}
}
/*
* Overflow crash test
*/
ae_vector_set_length(&x, 10+1, _state);
ae_vector_set_length(&v, 10+1, _state);
for(i=1; i<=10; i++)
{
v.ptr.p_double[i] = ae_maxrealnumber*0.01*(2*ae_randomreal(_state)-1);
}
generatereflection(&v, 10, &tau, _state);
/*
* Result
*/
ae_set_error_flag(errorflag, (ae_fp_greater(meg,threshold)||ae_fp_greater(mel,threshold))||ae_fp_greater(mer,threshold), __FILE__, __LINE__, "testablasunit.ap:1888");
ae_frame_leave(_state);
}
/*************************************************************************
Reference implementation
-- ALGLIB routine --
15.12.2009
Bochkanov Sergey
*************************************************************************/
static void testablasunit_refcmatrixrighttrsm(ae_int_t m,
ae_int_t n,
/* Complex */ ae_matrix* a,
ae_int_t i1,
ae_int_t j1,
ae_bool isupper,
ae_bool isunit,
ae_int_t optype,
/* Complex */ ae_matrix* x,
ae_int_t i2,
ae_int_t j2,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a1;
ae_matrix a2;
ae_vector tx;
ae_int_t i;
ae_int_t j;
ae_complex vc;
ae_bool rupper;
ae_frame_make(_state, &_frame_block);
memset(&a1, 0, sizeof(a1));
memset(&a2, 0, sizeof(a2));
memset(&tx, 0, sizeof(tx));
ae_matrix_init(&a1, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&a2, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&tx, 0, DT_COMPLEX, _state, ae_true);
if( n*m==0 )
{
ae_frame_leave(_state);
return;
}
ae_matrix_set_length(&a1, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a1.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
if( isupper )
{
for(i=0; i<=n-1; i++)
{
for(j=i; j<=n-1; j++)
{
a1.ptr.pp_complex[i][j] = a->ptr.pp_complex[i1+i][j1+j];
}
}
}
else
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=i; j++)
{
a1.ptr.pp_complex[i][j] = a->ptr.pp_complex[i1+i][j1+j];
}
}
}
rupper = isupper;
if( isunit )
{
for(i=0; i<=n-1; i++)
{
a1.ptr.pp_complex[i][i] = ae_complex_from_i(1);
}
}
ae_matrix_set_length(&a2, n, n, _state);
if( optype==0 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a2.ptr.pp_complex[i][j] = a1.ptr.pp_complex[i][j];
}
}
}
if( optype==1 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a2.ptr.pp_complex[i][j] = a1.ptr.pp_complex[j][i];
}
}
rupper = !rupper;
}
if( optype==2 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a2.ptr.pp_complex[i][j] = ae_c_conj(a1.ptr.pp_complex[j][i], _state);
}
}
rupper = !rupper;
}
testablasunit_internalcmatrixtrinverse(&a2, n, rupper, ae_false, _state);
ae_vector_set_length(&tx, n, _state);
for(i=0; i<=m-1; i++)
{
ae_v_cmove(&tx.ptr.p_complex[0], 1, &x->ptr.pp_complex[i2+i][j2], 1, "N", ae_v_len(0,n-1));
for(j=0; j<=n-1; j++)
{
vc = ae_v_cdotproduct(&tx.ptr.p_complex[0], 1, "N", &a2.ptr.pp_complex[0][j], a2.stride, "N", ae_v_len(0,n-1));
x->ptr.pp_complex[i2+i][j2+j] = vc;
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Reference implementation
-- ALGLIB routine --
15.12.2009
Bochkanov Sergey
*************************************************************************/
static void testablasunit_refcmatrixlefttrsm(ae_int_t m,
ae_int_t n,
/* Complex */ ae_matrix* a,
ae_int_t i1,
ae_int_t j1,
ae_bool isupper,
ae_bool isunit,
ae_int_t optype,
/* Complex */ ae_matrix* x,
ae_int_t i2,
ae_int_t j2,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a1;
ae_matrix a2;
ae_vector tx;
ae_int_t i;
ae_int_t j;
ae_complex vc;
ae_bool rupper;
ae_frame_make(_state, &_frame_block);
memset(&a1, 0, sizeof(a1));
memset(&a2, 0, sizeof(a2));
memset(&tx, 0, sizeof(tx));
ae_matrix_init(&a1, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&a2, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&tx, 0, DT_COMPLEX, _state, ae_true);
if( n*m==0 )
{
ae_frame_leave(_state);
return;
}
ae_matrix_set_length(&a1, m, m, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=m-1; j++)
{
a1.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
if( isupper )
{
for(i=0; i<=m-1; i++)
{
for(j=i; j<=m-1; j++)
{
a1.ptr.pp_complex[i][j] = a->ptr.pp_complex[i1+i][j1+j];
}
}
}
else
{
for(i=0; i<=m-1; i++)
{
for(j=0; j<=i; j++)
{
a1.ptr.pp_complex[i][j] = a->ptr.pp_complex[i1+i][j1+j];
}
}
}
rupper = isupper;
if( isunit )
{
for(i=0; i<=m-1; i++)
{
a1.ptr.pp_complex[i][i] = ae_complex_from_i(1);
}
}
ae_matrix_set_length(&a2, m, m, _state);
if( optype==0 )
{
for(i=0; i<=m-1; i++)
{
for(j=0; j<=m-1; j++)
{
a2.ptr.pp_complex[i][j] = a1.ptr.pp_complex[i][j];
}
}
}
if( optype==1 )
{
for(i=0; i<=m-1; i++)
{
for(j=0; j<=m-1; j++)
{
a2.ptr.pp_complex[i][j] = a1.ptr.pp_complex[j][i];
}
}
rupper = !rupper;
}
if( optype==2 )
{
for(i=0; i<=m-1; i++)
{
for(j=0; j<=m-1; j++)
{
a2.ptr.pp_complex[i][j] = ae_c_conj(a1.ptr.pp_complex[j][i], _state);
}
}
rupper = !rupper;
}
testablasunit_internalcmatrixtrinverse(&a2, m, rupper, ae_false, _state);
ae_vector_set_length(&tx, m, _state);
for(j=0; j<=n-1; j++)
{
ae_v_cmove(&tx.ptr.p_complex[0], 1, &x->ptr.pp_complex[i2][j2+j], x->stride, "N", ae_v_len(0,m-1));
for(i=0; i<=m-1; i++)
{
vc = ae_v_cdotproduct(&a2.ptr.pp_complex[i][0], 1, "N", &tx.ptr.p_complex[0], 1, "N", ae_v_len(0,m-1));
x->ptr.pp_complex[i2+i][j2+j] = vc;
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Reference implementation
-- ALGLIB routine --
15.12.2009
Bochkanov Sergey
*************************************************************************/
static void testablasunit_refrmatrixrighttrsm(ae_int_t m,
ae_int_t n,
/* Real */ ae_matrix* a,
ae_int_t i1,
ae_int_t j1,
ae_bool isupper,
ae_bool isunit,
ae_int_t optype,
/* Real */ ae_matrix* x,
ae_int_t i2,
ae_int_t j2,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a1;
ae_matrix a2;
ae_vector tx;
ae_int_t i;
ae_int_t j;
double vr;
ae_bool rupper;
ae_frame_make(_state, &_frame_block);
memset(&a1, 0, sizeof(a1));
memset(&a2, 0, sizeof(a2));
memset(&tx, 0, sizeof(tx));
ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a2, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tx, 0, DT_REAL, _state, ae_true);
if( n*m==0 )
{
ae_frame_leave(_state);
return;
}
ae_matrix_set_length(&a1, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a1.ptr.pp_double[i][j] = (double)(0);
}
}
if( isupper )
{
for(i=0; i<=n-1; i++)
{
for(j=i; j<=n-1; j++)
{
a1.ptr.pp_double[i][j] = a->ptr.pp_double[i1+i][j1+j];
}
}
}
else
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=i; j++)
{
a1.ptr.pp_double[i][j] = a->ptr.pp_double[i1+i][j1+j];
}
}
}
rupper = isupper;
if( isunit )
{
for(i=0; i<=n-1; i++)
{
a1.ptr.pp_double[i][i] = (double)(1);
}
}
ae_matrix_set_length(&a2, n, n, _state);
if( optype==0 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a2.ptr.pp_double[i][j] = a1.ptr.pp_double[i][j];
}
}
}
if( optype==1 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a2.ptr.pp_double[i][j] = a1.ptr.pp_double[j][i];
}
}
rupper = !rupper;
}
testablasunit_internalrmatrixtrinverse(&a2, n, rupper, ae_false, _state);
ae_vector_set_length(&tx, n, _state);
for(i=0; i<=m-1; i++)
{
ae_v_move(&tx.ptr.p_double[0], 1, &x->ptr.pp_double[i2+i][j2], 1, ae_v_len(0,n-1));
for(j=0; j<=n-1; j++)
{
vr = ae_v_dotproduct(&tx.ptr.p_double[0], 1, &a2.ptr.pp_double[0][j], a2.stride, ae_v_len(0,n-1));
x->ptr.pp_double[i2+i][j2+j] = vr;
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Reference implementation
-- ALGLIB routine --
15.12.2009
Bochkanov Sergey
*************************************************************************/
static void testablasunit_refrmatrixlefttrsm(ae_int_t m,
ae_int_t n,
/* Real */ ae_matrix* a,
ae_int_t i1,
ae_int_t j1,
ae_bool isupper,
ae_bool isunit,
ae_int_t optype,
/* Real */ ae_matrix* x,
ae_int_t i2,
ae_int_t j2,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a1;
ae_matrix a2;
ae_vector tx;
ae_int_t i;
ae_int_t j;
double vr;
ae_bool rupper;
ae_frame_make(_state, &_frame_block);
memset(&a1, 0, sizeof(a1));
memset(&a2, 0, sizeof(a2));
memset(&tx, 0, sizeof(tx));
ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a2, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tx, 0, DT_REAL, _state, ae_true);
if( n*m==0 )
{
ae_frame_leave(_state);
return;
}
ae_matrix_set_length(&a1, m, m, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=m-1; j++)
{
a1.ptr.pp_double[i][j] = (double)(0);
}
}
if( isupper )
{
for(i=0; i<=m-1; i++)
{
for(j=i; j<=m-1; j++)
{
a1.ptr.pp_double[i][j] = a->ptr.pp_double[i1+i][j1+j];
}
}
}
else
{
for(i=0; i<=m-1; i++)
{
for(j=0; j<=i; j++)
{
a1.ptr.pp_double[i][j] = a->ptr.pp_double[i1+i][j1+j];
}
}
}
rupper = isupper;
if( isunit )
{
for(i=0; i<=m-1; i++)
{
a1.ptr.pp_double[i][i] = (double)(1);
}
}
ae_matrix_set_length(&a2, m, m, _state);
if( optype==0 )
{
for(i=0; i<=m-1; i++)
{
for(j=0; j<=m-1; j++)
{
a2.ptr.pp_double[i][j] = a1.ptr.pp_double[i][j];
}
}
}
if( optype==1 )
{
for(i=0; i<=m-1; i++)
{
for(j=0; j<=m-1; j++)
{
a2.ptr.pp_double[i][j] = a1.ptr.pp_double[j][i];
}
}
rupper = !rupper;
}
testablasunit_internalrmatrixtrinverse(&a2, m, rupper, ae_false, _state);
ae_vector_set_length(&tx, m, _state);
for(j=0; j<=n-1; j++)
{
ae_v_move(&tx.ptr.p_double[0], 1, &x->ptr.pp_double[i2][j2+j], x->stride, ae_v_len(0,m-1));
for(i=0; i<=m-1; i++)
{
vr = ae_v_dotproduct(&a2.ptr.pp_double[i][0], 1, &tx.ptr.p_double[0], 1, ae_v_len(0,m-1));
x->ptr.pp_double[i2+i][j2+j] = vr;
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Internal subroutine.
Triangular matrix inversion
-- LAPACK routine (version 3.0) --
Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
Courant Institute, Argonne National Lab, and Rice University
February 29, 1992
*************************************************************************/
static ae_bool testablasunit_internalcmatrixtrinverse(/* Complex */ ae_matrix* a,
ae_int_t n,
ae_bool isupper,
ae_bool isunittriangular,
ae_state *_state)
{
ae_frame _frame_block;
ae_bool nounit;
ae_int_t i;
ae_int_t j;
ae_complex v;
ae_complex ajj;
ae_vector t;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&t, 0, sizeof(t));
ae_vector_init(&t, 0, DT_COMPLEX, _state, ae_true);
result = ae_true;
ae_vector_set_length(&t, n-1+1, _state);
/*
* Test the input parameters.
*/
nounit = !isunittriangular;
if( isupper )
{
/*
* Compute inverse of upper triangular matrix.
*/
for(j=0; j<=n-1; j++)
{
if( nounit )
{
if( ae_c_eq_d(a->ptr.pp_complex[j][j],(double)(0)) )
{
result = ae_false;
ae_frame_leave(_state);
return result;
}
a->ptr.pp_complex[j][j] = ae_c_d_div(1,a->ptr.pp_complex[j][j]);
ajj = ae_c_neg(a->ptr.pp_complex[j][j]);
}
else
{
ajj = ae_complex_from_i(-1);
}
/*
* Compute elements 1:j-1 of j-th column.
*/
if( j>0 )
{
ae_v_cmove(&t.ptr.p_complex[0], 1, &a->ptr.pp_complex[0][j], a->stride, "N", ae_v_len(0,j-1));
for(i=0; i<=j-1; i++)
{
if( i+1ptr.pp_complex[i][i+1], 1, "N", &t.ptr.p_complex[i+1], 1, "N", ae_v_len(i+1,j-1));
}
else
{
v = ae_complex_from_i(0);
}
if( nounit )
{
a->ptr.pp_complex[i][j] = ae_c_add(v,ae_c_mul(a->ptr.pp_complex[i][i],t.ptr.p_complex[i]));
}
else
{
a->ptr.pp_complex[i][j] = ae_c_add(v,t.ptr.p_complex[i]);
}
}
ae_v_cmulc(&a->ptr.pp_complex[0][j], a->stride, ae_v_len(0,j-1), ajj);
}
}
}
else
{
/*
* Compute inverse of lower triangular matrix.
*/
for(j=n-1; j>=0; j--)
{
if( nounit )
{
if( ae_c_eq_d(a->ptr.pp_complex[j][j],(double)(0)) )
{
result = ae_false;
ae_frame_leave(_state);
return result;
}
a->ptr.pp_complex[j][j] = ae_c_d_div(1,a->ptr.pp_complex[j][j]);
ajj = ae_c_neg(a->ptr.pp_complex[j][j]);
}
else
{
ajj = ae_complex_from_i(-1);
}
if( j+1ptr.pp_complex[j+1][j], a->stride, "N", ae_v_len(j+1,n-1));
for(i=j+1; i<=n-1; i++)
{
if( i>j+1 )
{
v = ae_v_cdotproduct(&a->ptr.pp_complex[i][j+1], 1, "N", &t.ptr.p_complex[j+1], 1, "N", ae_v_len(j+1,i-1));
}
else
{
v = ae_complex_from_i(0);
}
if( nounit )
{
a->ptr.pp_complex[i][j] = ae_c_add(v,ae_c_mul(a->ptr.pp_complex[i][i],t.ptr.p_complex[i]));
}
else
{
a->ptr.pp_complex[i][j] = ae_c_add(v,t.ptr.p_complex[i]);
}
}
ae_v_cmulc(&a->ptr.pp_complex[j+1][j], a->stride, ae_v_len(j+1,n-1), ajj);
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Internal subroutine.
Triangular matrix inversion
-- LAPACK routine (version 3.0) --
Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,
Courant Institute, Argonne National Lab, and Rice University
February 29, 1992
*************************************************************************/
static ae_bool testablasunit_internalrmatrixtrinverse(/* Real */ ae_matrix* a,
ae_int_t n,
ae_bool isupper,
ae_bool isunittriangular,
ae_state *_state)
{
ae_frame _frame_block;
ae_bool nounit;
ae_int_t i;
ae_int_t j;
double v;
double ajj;
ae_vector t;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&t, 0, sizeof(t));
ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
result = ae_true;
ae_vector_set_length(&t, n-1+1, _state);
/*
* Test the input parameters.
*/
nounit = !isunittriangular;
if( isupper )
{
/*
* Compute inverse of upper triangular matrix.
*/
for(j=0; j<=n-1; j++)
{
if( nounit )
{
if( ae_fp_eq(a->ptr.pp_double[j][j],(double)(0)) )
{
result = ae_false;
ae_frame_leave(_state);
return result;
}
a->ptr.pp_double[j][j] = 1/a->ptr.pp_double[j][j];
ajj = -a->ptr.pp_double[j][j];
}
else
{
ajj = (double)(-1);
}
/*
* Compute elements 1:j-1 of j-th column.
*/
if( j>0 )
{
ae_v_move(&t.ptr.p_double[0], 1, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,j-1));
for(i=0; i<=j-1; i++)
{
if( iptr.pp_double[i][i+1], 1, &t.ptr.p_double[i+1], 1, ae_v_len(i+1,j-1));
}
else
{
v = (double)(0);
}
if( nounit )
{
a->ptr.pp_double[i][j] = v+a->ptr.pp_double[i][i]*t.ptr.p_double[i];
}
else
{
a->ptr.pp_double[i][j] = v+t.ptr.p_double[i];
}
}
ae_v_muld(&a->ptr.pp_double[0][j], a->stride, ae_v_len(0,j-1), ajj);
}
}
}
else
{
/*
* Compute inverse of lower triangular matrix.
*/
for(j=n-1; j>=0; j--)
{
if( nounit )
{
if( ae_fp_eq(a->ptr.pp_double[j][j],(double)(0)) )
{
result = ae_false;
ae_frame_leave(_state);
return result;
}
a->ptr.pp_double[j][j] = 1/a->ptr.pp_double[j][j];
ajj = -a->ptr.pp_double[j][j];
}
else
{
ajj = (double)(-1);
}
if( jptr.pp_double[j+1][j], a->stride, ae_v_len(j+1,n-1));
for(i=j+1; i<=n-1; i++)
{
if( i>j+1 )
{
v = ae_v_dotproduct(&a->ptr.pp_double[i][j+1], 1, &t.ptr.p_double[j+1], 1, ae_v_len(j+1,i-1));
}
else
{
v = (double)(0);
}
if( nounit )
{
a->ptr.pp_double[i][j] = v+a->ptr.pp_double[i][i]*t.ptr.p_double[i];
}
else
{
a->ptr.pp_double[i][j] = v+t.ptr.p_double[i];
}
}
ae_v_muld(&a->ptr.pp_double[j+1][j], a->stride, ae_v_len(j+1,n-1), ajj);
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Reference SYRK subroutine.
-- ALGLIB routine --
16.12.2009
Bochkanov Sergey
*************************************************************************/
static void testablasunit_refcmatrixherk(ae_int_t n,
ae_int_t k,
double alpha,
/* Complex */ ae_matrix* a,
ae_int_t ia,
ae_int_t ja,
ae_int_t optypea,
double beta,
/* Complex */ ae_matrix* c,
ae_int_t ic,
ae_int_t jc,
ae_bool isupper,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix ae;
ae_int_t i;
ae_int_t j;
ae_complex vc;
ae_frame_make(_state, &_frame_block);
memset(&ae, 0, sizeof(ae));
ae_matrix_init(&ae, 0, 0, DT_COMPLEX, _state, ae_true);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (isupper&&j>=i)||(!isupper&&j<=i) )
{
if( ae_fp_eq(beta,(double)(0)) )
{
c->ptr.pp_complex[i+ic][j+jc] = ae_complex_from_i(0);
}
else
{
c->ptr.pp_complex[i+ic][j+jc] = ae_c_mul_d(c->ptr.pp_complex[i+ic][j+jc],beta);
}
}
}
}
if( ae_fp_eq(alpha,(double)(0)) )
{
ae_frame_leave(_state);
return;
}
if( n*k>0 )
{
ae_matrix_set_length(&ae, n, k, _state);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=k-1; j++)
{
if( optypea==0 )
{
ae.ptr.pp_complex[i][j] = a->ptr.pp_complex[ia+i][ja+j];
}
if( optypea==2 )
{
ae.ptr.pp_complex[i][j] = ae_c_conj(a->ptr.pp_complex[ia+j][ja+i], _state);
}
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
vc = ae_complex_from_i(0);
if( k>0 )
{
vc = ae_v_cdotproduct(&ae.ptr.pp_complex[i][0], 1, "N", &ae.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,k-1));
}
vc = ae_c_mul_d(vc,alpha);
if( isupper&&j>=i )
{
c->ptr.pp_complex[ic+i][jc+j] = ae_c_add(vc,c->ptr.pp_complex[ic+i][jc+j]);
}
if( !isupper&&j<=i )
{
c->ptr.pp_complex[ic+i][jc+j] = ae_c_add(vc,c->ptr.pp_complex[ic+i][jc+j]);
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Reference SYRK subroutine.
-- ALGLIB routine --
16.12.2009
Bochkanov Sergey
*************************************************************************/
static void testablasunit_refrmatrixsyrk(ae_int_t n,
ae_int_t k,
double alpha,
/* Real */ ae_matrix* a,
ae_int_t ia,
ae_int_t ja,
ae_int_t optypea,
double beta,
/* Real */ ae_matrix* c,
ae_int_t ic,
ae_int_t jc,
ae_bool isupper,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix ae;
ae_int_t i;
ae_int_t j;
double vr;
ae_frame_make(_state, &_frame_block);
memset(&ae, 0, sizeof(ae));
ae_matrix_init(&ae, 0, 0, DT_REAL, _state, ae_true);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (isupper&&j>=i)||(!isupper&&j<=i) )
{
if( ae_fp_eq(beta,(double)(0)) )
{
c->ptr.pp_double[i+ic][j+jc] = (double)(0);
}
else
{
c->ptr.pp_double[i+ic][j+jc] = c->ptr.pp_double[i+ic][j+jc]*beta;
}
}
}
}
if( ae_fp_eq(alpha,(double)(0)) )
{
ae_frame_leave(_state);
return;
}
if( n*k>0 )
{
ae_matrix_set_length(&ae, n, k, _state);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=k-1; j++)
{
if( optypea==0 )
{
ae.ptr.pp_double[i][j] = a->ptr.pp_double[ia+i][ja+j];
}
if( optypea==1 )
{
ae.ptr.pp_double[i][j] = a->ptr.pp_double[ia+j][ja+i];
}
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
vr = (double)(0);
if( k>0 )
{
vr = ae_v_dotproduct(&ae.ptr.pp_double[i][0], 1, &ae.ptr.pp_double[j][0], 1, ae_v_len(0,k-1));
}
vr = alpha*vr;
if( isupper&&j>=i )
{
c->ptr.pp_double[ic+i][jc+j] = vr+c->ptr.pp_double[ic+i][jc+j];
}
if( !isupper&&j<=i )
{
c->ptr.pp_double[ic+i][jc+j] = vr+c->ptr.pp_double[ic+i][jc+j];
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Reference GEMM,
ALGLIB subroutine
*************************************************************************/
static void testablasunit_refcmatrixgemm(ae_int_t m,
ae_int_t n,
ae_int_t k,
ae_complex alpha,
/* Complex */ ae_matrix* a,
ae_int_t ia,
ae_int_t ja,
ae_int_t optypea,
/* Complex */ ae_matrix* b,
ae_int_t ib,
ae_int_t jb,
ae_int_t optypeb,
ae_complex beta,
/* Complex */ ae_matrix* c,
ae_int_t ic,
ae_int_t jc,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix ae;
ae_matrix be;
ae_int_t i;
ae_int_t j;
ae_complex vc;
ae_frame_make(_state, &_frame_block);
memset(&ae, 0, sizeof(ae));
memset(&be, 0, sizeof(be));
ae_matrix_init(&ae, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&be, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_set_length(&ae, m, k, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=k-1; j++)
{
if( optypea==0 )
{
ae.ptr.pp_complex[i][j] = a->ptr.pp_complex[ia+i][ja+j];
}
if( optypea==1 )
{
ae.ptr.pp_complex[i][j] = a->ptr.pp_complex[ia+j][ja+i];
}
if( optypea==2 )
{
ae.ptr.pp_complex[i][j] = ae_c_conj(a->ptr.pp_complex[ia+j][ja+i], _state);
}
}
}
ae_matrix_set_length(&be, k, n, _state);
for(i=0; i<=k-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( optypeb==0 )
{
be.ptr.pp_complex[i][j] = b->ptr.pp_complex[ib+i][jb+j];
}
if( optypeb==1 )
{
be.ptr.pp_complex[i][j] = b->ptr.pp_complex[ib+j][jb+i];
}
if( optypeb==2 )
{
be.ptr.pp_complex[i][j] = ae_c_conj(b->ptr.pp_complex[ib+j][jb+i], _state);
}
}
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
vc = ae_v_cdotproduct(&ae.ptr.pp_complex[i][0], 1, "N", &be.ptr.pp_complex[0][j], be.stride, "N", ae_v_len(0,k-1));
vc = ae_c_mul(alpha,vc);
if( ae_c_neq_d(beta,(double)(0)) )
{
vc = ae_c_add(vc,ae_c_mul(beta,c->ptr.pp_complex[ic+i][jc+j]));
}
c->ptr.pp_complex[ic+i][jc+j] = vc;
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Reference GEMM,
ALGLIB subroutine
*************************************************************************/
static void testablasunit_refrmatrixgemm(ae_int_t m,
ae_int_t n,
ae_int_t k,
double alpha,
/* Real */ ae_matrix* a,
ae_int_t ia,
ae_int_t ja,
ae_int_t optypea,
/* Real */ ae_matrix* b,
ae_int_t ib,
ae_int_t jb,
ae_int_t optypeb,
double beta,
/* Real */ ae_matrix* c,
ae_int_t ic,
ae_int_t jc,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix ae;
ae_matrix be;
ae_int_t i;
ae_int_t j;
double vc;
ae_frame_make(_state, &_frame_block);
memset(&ae, 0, sizeof(ae));
memset(&be, 0, sizeof(be));
ae_matrix_init(&ae, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&be, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_set_length(&ae, m, k, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=k-1; j++)
{
if( optypea==0 )
{
ae.ptr.pp_double[i][j] = a->ptr.pp_double[ia+i][ja+j];
}
if( optypea==1 )
{
ae.ptr.pp_double[i][j] = a->ptr.pp_double[ia+j][ja+i];
}
}
}
ae_matrix_set_length(&be, k, n, _state);
for(i=0; i<=k-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( optypeb==0 )
{
be.ptr.pp_double[i][j] = b->ptr.pp_double[ib+i][jb+j];
}
if( optypeb==1 )
{
be.ptr.pp_double[i][j] = b->ptr.pp_double[ib+j][jb+i];
}
}
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
vc = ae_v_dotproduct(&ae.ptr.pp_double[i][0], 1, &be.ptr.pp_double[0][j], be.stride, ae_v_len(0,k-1));
vc = alpha*vc;
if( ae_fp_neq(beta,(double)(0)) )
{
vc = vc+beta*c->ptr.pp_double[ic+i][jc+j];
}
c->ptr.pp_double[ic+i][jc+j] = vc;
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Reference SYMV,
ALGLIB subroutine
*************************************************************************/
static void testablasunit_refrmatrixsymv(ae_int_t n,
double alpha,
/* Real */ ae_matrix* a,
ae_int_t ia,
ae_int_t ja,
ae_bool isupper,
/* Real */ ae_vector* x,
ae_int_t ix,
double beta,
/* Real */ ae_vector* y,
ae_int_t iy,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
double v;
ae_matrix b;
ae_frame_make(_state, &_frame_block);
memset(&b, 0, sizeof(b));
ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true);
/*
* Convert problem to traditional dense GEMV
*/
ae_matrix_set_length(&b, n, n, _state);
if( isupper )
{
for(i=0; i<=n-1; i++)
{
for(j=i; j<=n-1; j++)
{
b.ptr.pp_double[i][j] = a->ptr.pp_double[ia+i][ja+j];
b.ptr.pp_double[j][i] = a->ptr.pp_double[ia+i][ja+j];
}
}
}
else
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=i; j++)
{
b.ptr.pp_double[i][j] = a->ptr.pp_double[ia+i][ja+j];
b.ptr.pp_double[j][i] = a->ptr.pp_double[ia+i][ja+j];
}
}
}
/*
* Calculate result
*/
for(i=0; i<=n-1; i++)
{
v = beta*y->ptr.p_double[iy+i];
for(j=0; j<=n-1; j++)
{
v = v+alpha*b.ptr.pp_double[i][j]*x->ptr.p_double[ix+j];
}
y->ptr.p_double[iy+i] = v;
}
ae_frame_leave(_state);
}
/*************************************************************************
Reference SYVMV,
ALGLIB subroutine
*************************************************************************/
static double testablasunit_refrmatrixsyvmv(ae_int_t n,
/* Real */ ae_matrix* a,
ae_int_t ia,
ae_int_t ja,
ae_bool isupper,
/* Real */ ae_vector* x,
ae_int_t ix,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_matrix b;
double result;
ae_frame_make(_state, &_frame_block);
memset(&b, 0, sizeof(b));
ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true);
/*
* Convert problem to traditional dense GEMV
*/
ae_matrix_set_length(&b, n, n, _state);
if( isupper )
{
for(i=0; i<=n-1; i++)
{
for(j=i; j<=n-1; j++)
{
b.ptr.pp_double[i][j] = a->ptr.pp_double[ia+i][ja+j];
b.ptr.pp_double[j][i] = a->ptr.pp_double[ia+i][ja+j];
}
}
}
else
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=i; j++)
{
b.ptr.pp_double[i][j] = a->ptr.pp_double[ia+i][ja+j];
b.ptr.pp_double[j][i] = a->ptr.pp_double[ia+i][ja+j];
}
}
}
/*
* Calculate result
*/
result = (double)(0);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
result = result+x->ptr.p_double[ix+i]*b.ptr.pp_double[i][j]*x->ptr.p_double[ix+j];
}
}
ae_frame_leave(_state);
return result;
}
ae_bool testcreflections(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_int_t n;
ae_int_t m;
ae_int_t maxmn;
ae_vector x;
ae_vector v;
ae_vector work;
ae_matrix h;
ae_matrix a;
ae_matrix b;
ae_matrix c;
ae_complex tmp;
ae_complex beta;
ae_complex tau;
double err;
double mer;
double mel;
double meg;
ae_int_t pass;
ae_int_t passcount;
ae_bool waserrors;
double threshold;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&v, 0, sizeof(v));
memset(&work, 0, sizeof(work));
memset(&h, 0, sizeof(h));
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
memset(&c, 0, sizeof(c));
ae_vector_init(&x, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&v, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&work, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&h, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&b, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_COMPLEX, _state, ae_true);
threshold = 1000*ae_machineepsilon;
passcount = 1000;
mer = (double)(0);
mel = (double)(0);
meg = (double)(0);
for(pass=1; pass<=passcount; pass++)
{
/*
* Task
*/
n = 1+ae_randominteger(10, _state);
m = 1+ae_randominteger(10, _state);
maxmn = ae_maxint(m, n, _state);
/*
* Initialize
*/
ae_vector_set_length(&x, maxmn+1, _state);
ae_vector_set_length(&v, maxmn+1, _state);
ae_vector_set_length(&work, maxmn+1, _state);
ae_matrix_set_length(&h, maxmn+1, maxmn+1, _state);
ae_matrix_set_length(&a, maxmn+1, maxmn+1, _state);
ae_matrix_set_length(&b, maxmn+1, maxmn+1, _state);
ae_matrix_set_length(&c, maxmn+1, maxmn+1, _state);
/*
* GenerateReflection
*/
for(i=1; i<=n; i++)
{
x.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1;
x.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1;
v.ptr.p_complex[i] = x.ptr.p_complex[i];
}
complexgeneratereflection(&v, n, &tau, _state);
beta = v.ptr.p_complex[1];
v.ptr.p_complex[1] = ae_complex_from_i(1);
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
if( i==j )
{
h.ptr.pp_complex[i][j] = ae_c_d_sub(1,ae_c_mul(ae_c_mul(tau,v.ptr.p_complex[i]),ae_c_conj(v.ptr.p_complex[j], _state)));
}
else
{
h.ptr.pp_complex[i][j] = ae_c_neg(ae_c_mul(ae_c_mul(tau,v.ptr.p_complex[i]),ae_c_conj(v.ptr.p_complex[j], _state)));
}
}
}
err = (double)(0);
for(i=1; i<=n; i++)
{
tmp = ae_v_cdotproduct(&h.ptr.pp_complex[1][i], h.stride, "Conj", &x.ptr.p_complex[1], 1, "N", ae_v_len(1,n));
if( i==1 )
{
err = ae_maxreal(err, ae_c_abs(ae_c_sub(tmp,beta), _state), _state);
}
else
{
err = ae_maxreal(err, ae_c_abs(tmp, _state), _state);
}
}
err = ae_maxreal(err, ae_fabs(beta.y, _state), _state);
meg = ae_maxreal(meg, err, _state);
/*
* ApplyReflectionFromTheLeft
*/
for(i=1; i<=m; i++)
{
x.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1;
x.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1;
v.ptr.p_complex[i] = x.ptr.p_complex[i];
}
for(i=1; i<=m; i++)
{
for(j=1; j<=n; j++)
{
a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
b.ptr.pp_complex[i][j] = a.ptr.pp_complex[i][j];
}
}
complexgeneratereflection(&v, m, &tau, _state);
beta = v.ptr.p_complex[1];
v.ptr.p_complex[1] = ae_complex_from_i(1);
complexapplyreflectionfromtheleft(&b, tau, &v, 1, m, 1, n, &work, _state);
for(i=1; i<=m; i++)
{
for(j=1; j<=m; j++)
{
if( i==j )
{
h.ptr.pp_complex[i][j] = ae_c_d_sub(1,ae_c_mul(ae_c_mul(tau,v.ptr.p_complex[i]),ae_c_conj(v.ptr.p_complex[j], _state)));
}
else
{
h.ptr.pp_complex[i][j] = ae_c_neg(ae_c_mul(ae_c_mul(tau,v.ptr.p_complex[i]),ae_c_conj(v.ptr.p_complex[j], _state)));
}
}
}
for(i=1; i<=m; i++)
{
for(j=1; j<=n; j++)
{
tmp = ae_v_cdotproduct(&h.ptr.pp_complex[i][1], 1, "N", &a.ptr.pp_complex[1][j], a.stride, "N", ae_v_len(1,m));
c.ptr.pp_complex[i][j] = tmp;
}
}
err = (double)(0);
for(i=1; i<=m; i++)
{
for(j=1; j<=n; j++)
{
err = ae_maxreal(err, ae_c_abs(ae_c_sub(b.ptr.pp_complex[i][j],c.ptr.pp_complex[i][j]), _state), _state);
}
}
mel = ae_maxreal(mel, err, _state);
/*
* ApplyReflectionFromTheRight
*/
for(i=1; i<=n; i++)
{
x.ptr.p_complex[i] = ae_complex_from_d(2*ae_randomreal(_state)-1);
v.ptr.p_complex[i] = x.ptr.p_complex[i];
}
for(i=1; i<=m; i++)
{
for(j=1; j<=n; j++)
{
a.ptr.pp_complex[i][j] = ae_complex_from_d(2*ae_randomreal(_state)-1);
b.ptr.pp_complex[i][j] = a.ptr.pp_complex[i][j];
}
}
complexgeneratereflection(&v, n, &tau, _state);
beta = v.ptr.p_complex[1];
v.ptr.p_complex[1] = ae_complex_from_i(1);
complexapplyreflectionfromtheright(&b, tau, &v, 1, m, 1, n, &work, _state);
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
if( i==j )
{
h.ptr.pp_complex[i][j] = ae_c_d_sub(1,ae_c_mul(ae_c_mul(tau,v.ptr.p_complex[i]),ae_c_conj(v.ptr.p_complex[j], _state)));
}
else
{
h.ptr.pp_complex[i][j] = ae_c_neg(ae_c_mul(ae_c_mul(tau,v.ptr.p_complex[i]),ae_c_conj(v.ptr.p_complex[j], _state)));
}
}
}
for(i=1; i<=m; i++)
{
for(j=1; j<=n; j++)
{
tmp = ae_v_cdotproduct(&a.ptr.pp_complex[i][1], 1, "N", &h.ptr.pp_complex[1][j], h.stride, "N", ae_v_len(1,n));
c.ptr.pp_complex[i][j] = tmp;
}
}
err = (double)(0);
for(i=1; i<=m; i++)
{
for(j=1; j<=n; j++)
{
err = ae_maxreal(err, ae_c_abs(ae_c_sub(b.ptr.pp_complex[i][j],c.ptr.pp_complex[i][j]), _state), _state);
}
}
mer = ae_maxreal(mer, err, _state);
}
/*
* Overflow crash test
*/
ae_vector_set_length(&x, 10+1, _state);
ae_vector_set_length(&v, 10+1, _state);
for(i=1; i<=10; i++)
{
v.ptr.p_complex[i] = ae_complex_from_d(ae_maxrealnumber*0.01*(2*ae_randomreal(_state)-1));
}
complexgeneratereflection(&v, 10, &tau, _state);
/*
* report
*/
waserrors = (ae_fp_greater(meg,threshold)||ae_fp_greater(mel,threshold))||ae_fp_greater(mer,threshold);
if( !silent )
{
printf("TESTING COMPLEX REFLECTIONS\n");
printf("Generate error: %5.3e\n",
(double)(meg));
printf("Apply(L) error: %5.3e\n",
(double)(mel));
printf("Apply(R) error: %5.3e\n",
(double)(mer));
printf("Threshold: %5.3e\n",
(double)(threshold));
printf("Overflow crash test: PASSED\n");
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
static ae_int_t testmatgenunit_maxsvditerations = 60;
static void testmatgenunit_unset2d(/* Real */ ae_matrix* a,
ae_state *_state);
static void testmatgenunit_unset2dc(/* Complex */ ae_matrix* a,
ae_state *_state);
static ae_bool testmatgenunit_isspd(/* Real */ ae_matrix* a,
ae_int_t n,
ae_bool isupper,
ae_state *_state);
static ae_bool testmatgenunit_ishpd(/* Complex */ ae_matrix* a,
ae_int_t n,
ae_state *_state);
static ae_bool testmatgenunit_testeult(ae_state *_state);
static double testmatgenunit_svdcond(/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state);
static ae_bool testmatgenunit_obsoletesvddecomposition(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Real */ ae_vector* w,
/* Real */ ae_matrix* v,
ae_state *_state);
static double testmatgenunit_extsign(double a, double b, ae_state *_state);
static double testmatgenunit_mymax(double a, double b, ae_state *_state);
static double testmatgenunit_pythag(double a, double b, ae_state *_state);
ae_bool testmatgen(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix b;
ae_matrix u;
ae_matrix v;
ae_matrix ca;
ae_matrix cb;
ae_matrix r1;
ae_matrix r2;
ae_matrix c1;
ae_matrix c2;
ae_vector w;
ae_int_t n;
ae_int_t maxn;
ae_int_t i;
ae_int_t j;
ae_int_t pass;
ae_int_t passcount;
ae_bool waserrors;
double cond;
double threshold;
double vt;
ae_complex ct;
double minw;
double maxw;
ae_bool serr;
ae_bool herr;
ae_bool spderr;
ae_bool hpderr;
ae_bool rerr;
ae_bool cerr;
ae_bool eulerr;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
memset(&u, 0, sizeof(u));
memset(&v, 0, sizeof(v));
memset(&ca, 0, sizeof(ca));
memset(&cb, 0, sizeof(cb));
memset(&r1, 0, sizeof(r1));
memset(&r2, 0, sizeof(r2));
memset(&c1, 0, sizeof(c1));
memset(&c2, 0, sizeof(c2));
memset(&w, 0, sizeof(w));
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ca, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&cb, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&r1, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&r2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c1, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&c2, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
rerr = ae_false;
cerr = ae_false;
serr = ae_false;
herr = ae_false;
spderr = ae_false;
hpderr = ae_false;
eulerr = ae_false;
waserrors = ae_false;
maxn = 20;
passcount = 15;
threshold = 1000*ae_machineepsilon;
/*
* Testing orthogonal
*/
for(n=1; n<=maxn; n++)
{
for(pass=1; pass<=passcount; pass++)
{
ae_matrix_set_length(&r1, n-1+1, 2*n-1+1, _state);
ae_matrix_set_length(&r2, 2*n-1+1, n-1+1, _state);
ae_matrix_set_length(&c1, n-1+1, 2*n-1+1, _state);
ae_matrix_set_length(&c2, 2*n-1+1, n-1+1, _state);
/*
* Random orthogonal, real
*/
testmatgenunit_unset2d(&a, _state);
testmatgenunit_unset2d(&b, _state);
rmatrixrndorthogonal(n, &a, _state);
rmatrixrndorthogonal(n, &b, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
/*
* orthogonality test
*/
vt = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &a.ptr.pp_double[j][0], 1, ae_v_len(0,n-1));
if( i==j )
{
rerr = rerr||ae_fp_greater(ae_fabs(vt-1, _state),threshold);
}
else
{
rerr = rerr||ae_fp_greater(ae_fabs(vt, _state),threshold);
}
vt = ae_v_dotproduct(&b.ptr.pp_double[i][0], 1, &b.ptr.pp_double[j][0], 1, ae_v_len(0,n-1));
if( i==j )
{
rerr = rerr||ae_fp_greater(ae_fabs(vt-1, _state),threshold);
}
else
{
rerr = rerr||ae_fp_greater(ae_fabs(vt, _state),threshold);
}
/*
* test for difference in A and B
*/
if( n>=2 )
{
rerr = rerr||ae_fp_eq(a.ptr.pp_double[i][j],b.ptr.pp_double[i][j]);
}
}
}
/*
* Random orthogonal, complex
*/
testmatgenunit_unset2dc(&ca, _state);
testmatgenunit_unset2dc(&cb, _state);
cmatrixrndorthogonal(n, &ca, _state);
cmatrixrndorthogonal(n, &cb, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
/*
* orthogonality test
*/
ct = ae_v_cdotproduct(&ca.ptr.pp_complex[i][0], 1, "N", &ca.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,n-1));
if( i==j )
{
cerr = cerr||ae_fp_greater(ae_c_abs(ae_c_sub_d(ct,1), _state),threshold);
}
else
{
cerr = cerr||ae_fp_greater(ae_c_abs(ct, _state),threshold);
}
ct = ae_v_cdotproduct(&cb.ptr.pp_complex[i][0], 1, "N", &cb.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,n-1));
if( i==j )
{
cerr = cerr||ae_fp_greater(ae_c_abs(ae_c_sub_d(ct,1), _state),threshold);
}
else
{
cerr = cerr||ae_fp_greater(ae_c_abs(ct, _state),threshold);
}
/*
* test for difference in A and B
*/
if( n>=2 )
{
cerr = cerr||ae_c_eq(ca.ptr.pp_complex[i][j],cb.ptr.pp_complex[i][j]);
}
}
}
/*
* From the right real tests:
* 1. E*Q is orthogonal
* 2. Q1<>Q2 (routine result is changing)
* 3. (E E)'*Q = (Q' Q')' (correct handling of non-square matrices)
*/
testmatgenunit_unset2d(&a, _state);
testmatgenunit_unset2d(&b, _state);
ae_matrix_set_length(&a, n-1+1, n-1+1, _state);
ae_matrix_set_length(&b, n-1+1, n-1+1, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
b.ptr.pp_double[i][j] = (double)(0);
}
a.ptr.pp_double[i][i] = (double)(1);
b.ptr.pp_double[i][i] = (double)(1);
}
rmatrixrndorthogonalfromtheright(&a, n, n, _state);
rmatrixrndorthogonalfromtheright(&b, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
/*
* orthogonality test
*/
vt = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &a.ptr.pp_double[j][0], 1, ae_v_len(0,n-1));
if( i==j )
{
rerr = rerr||ae_fp_greater(ae_fabs(vt-1, _state),threshold);
}
else
{
rerr = rerr||ae_fp_greater(ae_fabs(vt, _state),threshold);
}
vt = ae_v_dotproduct(&b.ptr.pp_double[i][0], 1, &b.ptr.pp_double[j][0], 1, ae_v_len(0,n-1));
if( i==j )
{
rerr = rerr||ae_fp_greater(ae_fabs(vt-1, _state),threshold);
}
else
{
rerr = rerr||ae_fp_greater(ae_fabs(vt, _state),threshold);
}
/*
* test for difference in A and B
*/
if( n>=2 )
{
rerr = rerr||ae_fp_eq(a.ptr.pp_double[i][j],b.ptr.pp_double[i][j]);
}
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
r2.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
r2.ptr.pp_double[i+n][j] = r2.ptr.pp_double[i][j];
}
}
rmatrixrndorthogonalfromtheright(&r2, 2*n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
rerr = rerr||ae_fp_greater(ae_fabs(r2.ptr.pp_double[i+n][j]-r2.ptr.pp_double[i][j], _state),threshold);
}
}
/*
* From the left real tests:
* 1. Q*E is orthogonal
* 2. Q1<>Q2 (routine result is changing)
* 3. Q*(E E) = (Q Q) (correct handling of non-square matrices)
*/
testmatgenunit_unset2d(&a, _state);
testmatgenunit_unset2d(&b, _state);
ae_matrix_set_length(&a, n-1+1, n-1+1, _state);
ae_matrix_set_length(&b, n-1+1, n-1+1, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
b.ptr.pp_double[i][j] = (double)(0);
}
a.ptr.pp_double[i][i] = (double)(1);
b.ptr.pp_double[i][i] = (double)(1);
}
rmatrixrndorthogonalfromtheleft(&a, n, n, _state);
rmatrixrndorthogonalfromtheleft(&b, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
/*
* orthogonality test
*/
vt = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &a.ptr.pp_double[j][0], 1, ae_v_len(0,n-1));
if( i==j )
{
rerr = rerr||ae_fp_greater(ae_fabs(vt-1, _state),threshold);
}
else
{
rerr = rerr||ae_fp_greater(ae_fabs(vt, _state),threshold);
}
vt = ae_v_dotproduct(&b.ptr.pp_double[i][0], 1, &b.ptr.pp_double[j][0], 1, ae_v_len(0,n-1));
if( i==j )
{
rerr = rerr||ae_fp_greater(ae_fabs(vt-1, _state),threshold);
}
else
{
rerr = rerr||ae_fp_greater(ae_fabs(vt, _state),threshold);
}
/*
* test for difference in A and B
*/
if( n>=2 )
{
rerr = rerr||ae_fp_eq(a.ptr.pp_double[i][j],b.ptr.pp_double[i][j]);
}
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
r1.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
r1.ptr.pp_double[i][j+n] = r1.ptr.pp_double[i][j];
}
}
rmatrixrndorthogonalfromtheleft(&r1, n, 2*n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
rerr = rerr||ae_fp_greater(ae_fabs(r1.ptr.pp_double[i][j]-r1.ptr.pp_double[i][j+n], _state),threshold);
}
}
/*
* From the right complex tests:
* 1. E*Q is orthogonal
* 2. Q1<>Q2 (routine result is changing)
* 3. (E E)'*Q = (Q' Q')' (correct handling of non-square matrices)
*/
testmatgenunit_unset2dc(&ca, _state);
testmatgenunit_unset2dc(&cb, _state);
ae_matrix_set_length(&ca, n-1+1, n-1+1, _state);
ae_matrix_set_length(&cb, n-1+1, n-1+1, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
ca.ptr.pp_complex[i][j] = ae_complex_from_i(0);
cb.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
ca.ptr.pp_complex[i][i] = ae_complex_from_i(1);
cb.ptr.pp_complex[i][i] = ae_complex_from_i(1);
}
cmatrixrndorthogonalfromtheright(&ca, n, n, _state);
cmatrixrndorthogonalfromtheright(&cb, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
/*
* orthogonality test
*/
ct = ae_v_cdotproduct(&ca.ptr.pp_complex[i][0], 1, "N", &ca.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,n-1));
if( i==j )
{
cerr = cerr||ae_fp_greater(ae_c_abs(ae_c_sub_d(ct,1), _state),threshold);
}
else
{
cerr = cerr||ae_fp_greater(ae_c_abs(ct, _state),threshold);
}
ct = ae_v_cdotproduct(&cb.ptr.pp_complex[i][0], 1, "N", &cb.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,n-1));
if( i==j )
{
cerr = cerr||ae_fp_greater(ae_c_abs(ae_c_sub_d(ct,1), _state),threshold);
}
else
{
cerr = cerr||ae_fp_greater(ae_c_abs(ct, _state),threshold);
}
/*
* test for difference in A and B
*/
cerr = cerr||ae_c_eq(ca.ptr.pp_complex[i][j],cb.ptr.pp_complex[i][j]);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
c2.ptr.pp_complex[i][j] = ae_complex_from_d(2*ae_randomreal(_state)-1);
c2.ptr.pp_complex[i+n][j] = c2.ptr.pp_complex[i][j];
}
}
cmatrixrndorthogonalfromtheright(&c2, 2*n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
cerr = cerr||ae_fp_greater(ae_c_abs(ae_c_sub(c2.ptr.pp_complex[i+n][j],c2.ptr.pp_complex[i][j]), _state),threshold);
}
}
/*
* From the left complex tests:
* 1. Q*E is orthogonal
* 2. Q1<>Q2 (routine result is changing)
* 3. Q*(E E) = (Q Q) (correct handling of non-square matrices)
*/
testmatgenunit_unset2dc(&ca, _state);
testmatgenunit_unset2dc(&cb, _state);
ae_matrix_set_length(&ca, n-1+1, n-1+1, _state);
ae_matrix_set_length(&cb, n-1+1, n-1+1, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
ca.ptr.pp_complex[i][j] = ae_complex_from_i(0);
cb.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
ca.ptr.pp_complex[i][i] = ae_complex_from_i(1);
cb.ptr.pp_complex[i][i] = ae_complex_from_i(1);
}
cmatrixrndorthogonalfromtheleft(&ca, n, n, _state);
cmatrixrndorthogonalfromtheleft(&cb, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
/*
* orthogonality test
*/
ct = ae_v_cdotproduct(&ca.ptr.pp_complex[i][0], 1, "N", &ca.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,n-1));
if( i==j )
{
cerr = cerr||ae_fp_greater(ae_c_abs(ae_c_sub_d(ct,1), _state),threshold);
}
else
{
cerr = cerr||ae_fp_greater(ae_c_abs(ct, _state),threshold);
}
ct = ae_v_cdotproduct(&cb.ptr.pp_complex[i][0], 1, "N", &cb.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,n-1));
if( i==j )
{
cerr = cerr||ae_fp_greater(ae_c_abs(ae_c_sub_d(ct,1), _state),threshold);
}
else
{
cerr = cerr||ae_fp_greater(ae_c_abs(ct, _state),threshold);
}
/*
* test for difference in A and B
*/
cerr = cerr||ae_c_eq(ca.ptr.pp_complex[i][j],cb.ptr.pp_complex[i][j]);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
c1.ptr.pp_complex[i][j] = ae_complex_from_d(2*ae_randomreal(_state)-1);
c1.ptr.pp_complex[i][j+n] = c1.ptr.pp_complex[i][j];
}
}
cmatrixrndorthogonalfromtheleft(&c1, n, 2*n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
cerr = cerr||ae_fp_greater(ae_c_abs(ae_c_sub(c1.ptr.pp_complex[i][j],c1.ptr.pp_complex[i][j+n]), _state),threshold);
}
}
}
}
/*
* Testing GCond
*/
for(n=2; n<=maxn; n++)
{
for(pass=1; pass<=passcount; pass++)
{
/*
* real test
*/
testmatgenunit_unset2d(&a, _state);
cond = ae_exp(ae_log((double)(1000), _state)*ae_randomreal(_state), _state);
rmatrixrndcond(n, cond, &a, _state);
ae_matrix_set_length(&b, n+1, n+1, _state);
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
b.ptr.pp_double[i][j] = a.ptr.pp_double[i-1][j-1];
}
}
if( testmatgenunit_obsoletesvddecomposition(&b, n, n, &w, &v, _state) )
{
maxw = w.ptr.p_double[1];
minw = w.ptr.p_double[1];
for(i=2; i<=n; i++)
{
if( ae_fp_greater(w.ptr.p_double[i],maxw) )
{
maxw = w.ptr.p_double[i];
}
if( ae_fp_less(w.ptr.p_double[i],minw) )
{
minw = w.ptr.p_double[i];
}
}
vt = maxw/minw/cond;
if( ae_fp_greater(ae_fabs(ae_log(vt, _state), _state),ae_log(1+threshold, _state)) )
{
rerr = ae_true;
}
}
}
}
/*
* Symmetric/SPD
* N = 2 .. 30
*/
for(n=2; n<=maxn; n++)
{
/*
* SPD matrices
*/
for(pass=1; pass<=passcount; pass++)
{
/*
* Generate A
*/
testmatgenunit_unset2d(&a, _state);
cond = ae_exp(ae_log((double)(1000), _state)*ae_randomreal(_state), _state);
spdmatrixrndcond(n, cond, &a, _state);
/*
* test condition number
*/
spderr = spderr||ae_fp_greater(testmatgenunit_svdcond(&a, n, _state)/cond-1,threshold);
/*
* test SPD
*/
spderr = spderr||!testmatgenunit_isspd(&a, n, ae_true, _state);
/*
* test that A is symmetic
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
spderr = spderr||ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-a.ptr.pp_double[j][i], _state),threshold);
}
}
/*
* test for difference between A and B (subsequent matrix)
*/
testmatgenunit_unset2d(&b, _state);
spdmatrixrndcond(n, cond, &b, _state);
if( n>=2 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
spderr = spderr||ae_fp_eq(a.ptr.pp_double[i][j],b.ptr.pp_double[i][j]);
}
}
}
}
/*
* HPD matrices
*/
for(pass=1; pass<=passcount; pass++)
{
/*
* Generate A
*/
testmatgenunit_unset2dc(&ca, _state);
cond = ae_exp(ae_log((double)(1000), _state)*ae_randomreal(_state), _state);
hpdmatrixrndcond(n, cond, &ca, _state);
/*
* test HPD
*/
hpderr = hpderr||!testmatgenunit_ishpd(&ca, n, _state);
/*
* test that A is Hermitian
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
hpderr = hpderr||ae_fp_greater(ae_c_abs(ae_c_sub(ca.ptr.pp_complex[i][j],ae_c_conj(ca.ptr.pp_complex[j][i], _state)), _state),threshold);
}
}
/*
* test for difference between A and B (subsequent matrix)
*/
testmatgenunit_unset2dc(&cb, _state);
hpdmatrixrndcond(n, cond, &cb, _state);
if( n>=2 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
hpderr = hpderr||ae_c_eq(ca.ptr.pp_complex[i][j],cb.ptr.pp_complex[i][j]);
}
}
}
}
/*
* Symmetric matrices
*/
for(pass=1; pass<=passcount; pass++)
{
/*
* test condition number
*/
testmatgenunit_unset2d(&a, _state);
cond = ae_exp(ae_log((double)(1000), _state)*ae_randomreal(_state), _state);
smatrixrndcond(n, cond, &a, _state);
serr = serr||ae_fp_greater(testmatgenunit_svdcond(&a, n, _state)/cond-1,threshold);
/*
* test for difference between A and B
*/
testmatgenunit_unset2d(&b, _state);
smatrixrndcond(n, cond, &b, _state);
if( n>=2 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
serr = serr||ae_fp_eq(a.ptr.pp_double[i][j],b.ptr.pp_double[i][j]);
}
}
}
}
/*
* Hermitian matrices
*/
for(pass=1; pass<=passcount; pass++)
{
/*
* Generate A
*/
testmatgenunit_unset2dc(&ca, _state);
cond = ae_exp(ae_log((double)(1000), _state)*ae_randomreal(_state), _state);
hmatrixrndcond(n, cond, &ca, _state);
/*
* test that A is Hermitian
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
herr = herr||ae_fp_greater(ae_c_abs(ae_c_sub(ca.ptr.pp_complex[i][j],ae_c_conj(ca.ptr.pp_complex[j][i], _state)), _state),threshold);
}
}
/*
* test for difference between A and B (subsequent matrix)
*/
testmatgenunit_unset2dc(&cb, _state);
hmatrixrndcond(n, cond, &cb, _state);
if( n>=2 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
herr = herr||ae_c_eq(ca.ptr.pp_complex[i][j],cb.ptr.pp_complex[i][j]);
}
}
}
}
}
/*
* Test for symmetric matrices
*/
eulerr = testmatgenunit_testeult(_state);
/*
* report
*/
waserrors = (((((rerr||cerr)||serr)||spderr)||herr)||hpderr)||eulerr;
if( !silent )
{
printf("TESTING MATRIX GENERATOR\n");
printf("REAL TEST: ");
if( !rerr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("COMPLEX TEST: ");
if( !cerr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("SYMMETRIC TEST: ");
if( !serr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("HERMITIAN TEST: ");
if( !herr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("SPD TEST: ");
if( !spderr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("HPD TEST: ");
if( !hpderr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("TEST FOR SYMMETRIC MATRICES: ");
if( !eulerr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Unsets 2D array.
*************************************************************************/
static void testmatgenunit_unset2d(/* Real */ ae_matrix* a,
ae_state *_state)
{
ae_matrix_set_length(a, 0+1, 0+1, _state);
a->ptr.pp_double[0][0] = 2*ae_randomreal(_state)-1;
}
/*************************************************************************
Unsets 2D array.
*************************************************************************/
static void testmatgenunit_unset2dc(/* Complex */ ae_matrix* a,
ae_state *_state)
{
ae_matrix_set_length(a, 0+1, 0+1, _state);
a->ptr.pp_complex[0][0] = ae_complex_from_d(2*ae_randomreal(_state)-1);
}
/*************************************************************************
Test whether matrix is SPD
*************************************************************************/
static ae_bool testmatgenunit_isspd(/* Real */ ae_matrix* a,
ae_int_t n,
ae_bool isupper,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix _a;
ae_int_t i;
ae_int_t j;
double ajj;
double v;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&_a, 0, sizeof(_a));
ae_matrix_init_copy(&_a, a, _state, ae_true);
a = &_a;
/*
* Test the input parameters.
*/
ae_assert(n>=0, "Error in SMatrixCholesky: incorrect function arguments", _state);
/*
* Quick return if possible
*/
result = ae_true;
if( n<=0 )
{
ae_frame_leave(_state);
return result;
}
if( isupper )
{
/*
* Compute the Cholesky factorization A = U'*U.
*/
for(j=0; j<=n-1; j++)
{
/*
* Compute U(J,J) and test for non-positive-definiteness.
*/
v = ae_v_dotproduct(&a->ptr.pp_double[0][j], a->stride, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,j-1));
ajj = a->ptr.pp_double[j][j]-v;
if( ae_fp_less_eq(ajj,(double)(0)) )
{
result = ae_false;
ae_frame_leave(_state);
return result;
}
ajj = ae_sqrt(ajj, _state);
a->ptr.pp_double[j][j] = ajj;
/*
* Compute elements J+1:N of row J.
*/
if( jptr.pp_double[0][i], a->stride, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,j-1));
a->ptr.pp_double[j][i] = a->ptr.pp_double[j][i]-v;
}
v = 1/ajj;
ae_v_muld(&a->ptr.pp_double[j][j+1], 1, ae_v_len(j+1,n-1), v);
}
}
}
else
{
/*
* Compute the Cholesky factorization A = L*L'.
*/
for(j=0; j<=n-1; j++)
{
/*
* Compute L(J,J) and test for non-positive-definiteness.
*/
v = ae_v_dotproduct(&a->ptr.pp_double[j][0], 1, &a->ptr.pp_double[j][0], 1, ae_v_len(0,j-1));
ajj = a->ptr.pp_double[j][j]-v;
if( ae_fp_less_eq(ajj,(double)(0)) )
{
result = ae_false;
ae_frame_leave(_state);
return result;
}
ajj = ae_sqrt(ajj, _state);
a->ptr.pp_double[j][j] = ajj;
/*
* Compute elements J+1:N of column J.
*/
if( jptr.pp_double[i][0], 1, &a->ptr.pp_double[j][0], 1, ae_v_len(0,j-1));
a->ptr.pp_double[i][j] = a->ptr.pp_double[i][j]-v;
}
v = 1/ajj;
ae_v_muld(&a->ptr.pp_double[j+1][j], a->stride, ae_v_len(j+1,n-1), v);
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Tests whether A is HPD
*************************************************************************/
static ae_bool testmatgenunit_ishpd(/* Complex */ ae_matrix* a,
ae_int_t n,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix _a;
ae_int_t j;
double ajj;
ae_complex v;
double r;
ae_vector t;
ae_vector t2;
ae_vector t3;
ae_int_t i;
ae_matrix a1;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&_a, 0, sizeof(_a));
memset(&t, 0, sizeof(t));
memset(&t2, 0, sizeof(t2));
memset(&t3, 0, sizeof(t3));
memset(&a1, 0, sizeof(a1));
ae_matrix_init_copy(&_a, a, _state, ae_true);
a = &_a;
ae_vector_init(&t, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&t2, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&t3, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&a1, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_set_length(&t, n-1+1, _state);
ae_vector_set_length(&t2, n-1+1, _state);
ae_vector_set_length(&t3, n-1+1, _state);
result = ae_true;
/*
* Compute the Cholesky factorization A = U'*U.
*/
for(j=0; j<=n-1; j++)
{
/*
* Compute U(J,J) and test for non-positive-definiteness.
*/
v = ae_v_cdotproduct(&a->ptr.pp_complex[0][j], a->stride, "Conj", &a->ptr.pp_complex[0][j], a->stride, "N", ae_v_len(0,j-1));
ajj = ae_c_sub(a->ptr.pp_complex[j][j],v).x;
if( ae_fp_less_eq(ajj,(double)(0)) )
{
a->ptr.pp_complex[j][j] = ae_complex_from_d(ajj);
result = ae_false;
ae_frame_leave(_state);
return result;
}
ajj = ae_sqrt(ajj, _state);
a->ptr.pp_complex[j][j] = ae_complex_from_d(ajj);
/*
* Compute elements J+1:N-1 of row J.
*/
if( jptr.pp_complex[0][j], a->stride, "Conj", ae_v_len(0,j-1));
ae_v_cmove(&t3.ptr.p_complex[j+1], 1, &a->ptr.pp_complex[j][j+1], 1, "N", ae_v_len(j+1,n-1));
for(i=j+1; i<=n-1; i++)
{
v = ae_v_cdotproduct(&a->ptr.pp_complex[0][i], a->stride, "N", &t2.ptr.p_complex[0], 1, "N", ae_v_len(0,j-1));
t3.ptr.p_complex[i] = ae_c_sub(t3.ptr.p_complex[i],v);
}
ae_v_cmove(&a->ptr.pp_complex[j][j+1], 1, &t3.ptr.p_complex[j+1], 1, "N", ae_v_len(j+1,n-1));
r = 1/ajj;
ae_v_cmuld(&a->ptr.pp_complex[j][j+1], 1, ae_v_len(j+1,n-1), r);
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
The function check, that upper triangle from symmetric matrix is equal to
lower triangle.
*************************************************************************/
static ae_bool testmatgenunit_testeult(ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix b;
double c;
double range;
double eps;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&b, 0, 0, DT_COMPLEX, _state, ae_true);
eps = 2*ae_machineepsilon;
range = 100*(2*ae_randomreal(_state)-1);
for(n=1; n<=15; n++)
{
c = 900*ae_randomreal(_state)+100;
/*
* Generate symmetric matrix and check it
*/
smatrixrndcond(n, c, &a, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-a.ptr.pp_double[j][i], _state),eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
spdmatrixrndcond(n, c, &a, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-a.ptr.pp_double[j][i], _state),eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
hmatrixrndcond(n, c, &b, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_greater(ae_fabs(b.ptr.pp_complex[i][j].x-b.ptr.pp_complex[j][i].x, _state),eps)||ae_fp_greater(ae_fabs(b.ptr.pp_complex[i][j].y+b.ptr.pp_complex[j][i].y, _state),eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
hpdmatrixrndcond(n, c, &b, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_greater(ae_fabs(b.ptr.pp_complex[i][j].x-b.ptr.pp_complex[j][i].x, _state),eps)||ae_fp_greater(ae_fabs(b.ptr.pp_complex[i][j].y+b.ptr.pp_complex[j][i].y, _state),eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
/*
* Prepare symmetric matrix with real values
*/
for(i=0; i<=n-1; i++)
{
for(j=i; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = range*(2*ae_randomreal(_state)-1);
}
}
for(i=0; i<=n-2; i++)
{
for(j=i+1; j<=n-1; j++)
{
a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j];
}
}
smatrixrndmultiply(&a, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-a.ptr.pp_double[j][i], _state),eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
/*
* Prepare symmetric matrix with complex values
*/
for(i=0; i<=n-1; i++)
{
for(j=i; j<=n-1; j++)
{
b.ptr.pp_complex[i][j].x = range*(2*ae_randomreal(_state)-1);
if( i!=j )
{
b.ptr.pp_complex[i][j].y = range*(2*ae_randomreal(_state)-1);
}
else
{
b.ptr.pp_complex[i][j].y = (double)(0);
}
}
}
for(i=0; i<=n-1; i++)
{
for(j=i+1; j<=n-1; j++)
{
b.ptr.pp_complex[i][j].x = b.ptr.pp_complex[j][i].x;
b.ptr.pp_complex[i][j].y = -b.ptr.pp_complex[j][i].y;
}
}
hmatrixrndmultiply(&b, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.pp_complex[i][i].y = (double)(0);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_greater(ae_fabs(b.ptr.pp_complex[i][j].x-b.ptr.pp_complex[j][i].x, _state),eps)||ae_fp_greater(ae_fabs(b.ptr.pp_complex[i][j].y+b.ptr.pp_complex[j][i].y, _state),eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
SVD condition number
*************************************************************************/
static double testmatgenunit_svdcond(/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a1;
ae_matrix v;
ae_vector w;
ae_int_t i;
ae_int_t j;
double minw;
double maxw;
double result;
ae_frame_make(_state, &_frame_block);
memset(&a1, 0, sizeof(a1));
memset(&v, 0, sizeof(v));
memset(&w, 0, sizeof(w));
ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
ae_matrix_set_length(&a1, n+1, n+1, _state);
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
a1.ptr.pp_double[i][j] = a->ptr.pp_double[i-1][j-1];
}
}
if( !testmatgenunit_obsoletesvddecomposition(&a1, n, n, &w, &v, _state) )
{
result = (double)(0);
ae_frame_leave(_state);
return result;
}
minw = w.ptr.p_double[1];
maxw = w.ptr.p_double[1];
for(i=2; i<=n; i++)
{
if( ae_fp_less(w.ptr.p_double[i],minw) )
{
minw = w.ptr.p_double[i];
}
if( ae_fp_greater(w.ptr.p_double[i],maxw) )
{
maxw = w.ptr.p_double[i];
}
}
result = maxw/minw;
ae_frame_leave(_state);
return result;
}
static ae_bool testmatgenunit_obsoletesvddecomposition(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Real */ ae_vector* w,
/* Real */ ae_matrix* v,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t nm;
ae_int_t minmn;
ae_int_t l;
ae_int_t k;
ae_int_t j;
ae_int_t jj;
ae_int_t its;
ae_int_t i;
double z;
double y;
double x;
double vscale;
double s;
double h;
double g;
double f;
double c;
double anorm;
ae_vector rv1;
ae_bool flag;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&rv1, 0, sizeof(rv1));
ae_vector_clear(w);
ae_matrix_clear(v);
ae_vector_init(&rv1, 0, DT_REAL, _state, ae_true);
ae_vector_set_length(&rv1, n+1, _state);
ae_vector_set_length(w, n+1, _state);
ae_matrix_set_length(v, n+1, n+1, _state);
result = ae_true;
if( mptr.pp_double[k][i], _state);
}
if( ae_fp_neq(vscale,0.0) )
{
for(k=i; k<=m; k++)
{
a->ptr.pp_double[k][i] = a->ptr.pp_double[k][i]/vscale;
s = s+a->ptr.pp_double[k][i]*a->ptr.pp_double[k][i];
}
f = a->ptr.pp_double[i][i];
g = -testmatgenunit_extsign(ae_sqrt(s, _state), f, _state);
h = f*g-s;
a->ptr.pp_double[i][i] = f-g;
if( i!=n )
{
for(j=l; j<=n; j++)
{
s = 0.0;
for(k=i; k<=m; k++)
{
s = s+a->ptr.pp_double[k][i]*a->ptr.pp_double[k][j];
}
f = s/h;
for(k=i; k<=m; k++)
{
a->ptr.pp_double[k][j] = a->ptr.pp_double[k][j]+f*a->ptr.pp_double[k][i];
}
}
}
for(k=i; k<=m; k++)
{
a->ptr.pp_double[k][i] = vscale*a->ptr.pp_double[k][i];
}
}
}
w->ptr.p_double[i] = vscale*g;
g = 0.0;
s = 0.0;
vscale = 0.0;
if( i<=m&&i!=n )
{
for(k=l; k<=n; k++)
{
vscale = vscale+ae_fabs(a->ptr.pp_double[i][k], _state);
}
if( ae_fp_neq(vscale,0.0) )
{
for(k=l; k<=n; k++)
{
a->ptr.pp_double[i][k] = a->ptr.pp_double[i][k]/vscale;
s = s+a->ptr.pp_double[i][k]*a->ptr.pp_double[i][k];
}
f = a->ptr.pp_double[i][l];
g = -testmatgenunit_extsign(ae_sqrt(s, _state), f, _state);
h = f*g-s;
a->ptr.pp_double[i][l] = f-g;
for(k=l; k<=n; k++)
{
rv1.ptr.p_double[k] = a->ptr.pp_double[i][k]/h;
}
if( i!=m )
{
for(j=l; j<=m; j++)
{
s = 0.0;
for(k=l; k<=n; k++)
{
s = s+a->ptr.pp_double[j][k]*a->ptr.pp_double[i][k];
}
for(k=l; k<=n; k++)
{
a->ptr.pp_double[j][k] = a->ptr.pp_double[j][k]+s*rv1.ptr.p_double[k];
}
}
}
for(k=l; k<=n; k++)
{
a->ptr.pp_double[i][k] = vscale*a->ptr.pp_double[i][k];
}
}
}
anorm = testmatgenunit_mymax(anorm, ae_fabs(w->ptr.p_double[i], _state)+ae_fabs(rv1.ptr.p_double[i], _state), _state);
}
for(i=n; i>=1; i--)
{
if( iptr.pp_double[j][i] = a->ptr.pp_double[i][j]/a->ptr.pp_double[i][l]/g;
}
for(j=l; j<=n; j++)
{
s = 0.0;
for(k=l; k<=n; k++)
{
s = s+a->ptr.pp_double[i][k]*v->ptr.pp_double[k][j];
}
for(k=l; k<=n; k++)
{
v->ptr.pp_double[k][j] = v->ptr.pp_double[k][j]+s*v->ptr.pp_double[k][i];
}
}
}
for(j=l; j<=n; j++)
{
v->ptr.pp_double[i][j] = 0.0;
v->ptr.pp_double[j][i] = 0.0;
}
}
v->ptr.pp_double[i][i] = 1.0;
g = rv1.ptr.p_double[i];
l = i;
}
for(i=minmn; i>=1; i--)
{
l = i+1;
g = w->ptr.p_double[i];
if( iptr.pp_double[i][j] = 0.0;
}
}
if( ae_fp_neq(g,0.0) )
{
g = 1.0/g;
if( i!=n )
{
for(j=l; j<=n; j++)
{
s = 0.0;
for(k=l; k<=m; k++)
{
s = s+a->ptr.pp_double[k][i]*a->ptr.pp_double[k][j];
}
f = s/a->ptr.pp_double[i][i]*g;
for(k=i; k<=m; k++)
{
a->ptr.pp_double[k][j] = a->ptr.pp_double[k][j]+f*a->ptr.pp_double[k][i];
}
}
}
for(j=i; j<=m; j++)
{
a->ptr.pp_double[j][i] = a->ptr.pp_double[j][i]*g;
}
}
else
{
for(j=i; j<=m; j++)
{
a->ptr.pp_double[j][i] = 0.0;
}
}
a->ptr.pp_double[i][i] = a->ptr.pp_double[i][i]+1.0;
}
nm = 0;
for(k=n; k>=1; k--)
{
for(its=1; its<=testmatgenunit_maxsvditerations; its++)
{
flag = ae_true;
for(l=k; l>=1; l--)
{
nm = l-1;
if( ae_fp_eq(ae_fabs(rv1.ptr.p_double[l], _state)+anorm,anorm) )
{
flag = ae_false;
break;
}
if( ae_fp_eq(ae_fabs(w->ptr.p_double[nm], _state)+anorm,anorm) )
{
break;
}
}
if( flag )
{
c = 0.0;
s = 1.0;
for(i=l; i<=k; i++)
{
f = s*rv1.ptr.p_double[i];
if( ae_fp_neq(ae_fabs(f, _state)+anorm,anorm) )
{
g = w->ptr.p_double[i];
h = testmatgenunit_pythag(f, g, _state);
w->ptr.p_double[i] = h;
h = 1.0/h;
c = g*h;
s = -f*h;
for(j=1; j<=m; j++)
{
y = a->ptr.pp_double[j][nm];
z = a->ptr.pp_double[j][i];
a->ptr.pp_double[j][nm] = y*c+z*s;
a->ptr.pp_double[j][i] = -y*s+z*c;
}
}
}
}
z = w->ptr.p_double[k];
if( l==k )
{
if( ae_fp_less(z,0.0) )
{
w->ptr.p_double[k] = -z;
for(j=1; j<=n; j++)
{
v->ptr.pp_double[j][k] = -v->ptr.pp_double[j][k];
}
}
break;
}
if( its==testmatgenunit_maxsvditerations )
{
result = ae_false;
ae_frame_leave(_state);
return result;
}
x = w->ptr.p_double[l];
nm = k-1;
y = w->ptr.p_double[nm];
g = rv1.ptr.p_double[nm];
h = rv1.ptr.p_double[k];
f = ((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
g = testmatgenunit_pythag(f, (double)(1), _state);
f = ((x-z)*(x+z)+h*(y/(f+testmatgenunit_extsign(g, f, _state))-h))/x;
c = 1.0;
s = 1.0;
for(j=l; j<=nm; j++)
{
i = j+1;
g = rv1.ptr.p_double[i];
y = w->ptr.p_double[i];
h = s*g;
g = c*g;
z = testmatgenunit_pythag(f, h, _state);
rv1.ptr.p_double[j] = z;
c = f/z;
s = h/z;
f = x*c+g*s;
g = -x*s+g*c;
h = y*s;
y = y*c;
for(jj=1; jj<=n; jj++)
{
x = v->ptr.pp_double[jj][j];
z = v->ptr.pp_double[jj][i];
v->ptr.pp_double[jj][j] = x*c+z*s;
v->ptr.pp_double[jj][i] = -x*s+z*c;
}
z = testmatgenunit_pythag(f, h, _state);
w->ptr.p_double[j] = z;
if( ae_fp_neq(z,0.0) )
{
z = 1.0/z;
c = f*z;
s = h*z;
}
f = c*g+s*y;
x = -s*g+c*y;
for(jj=1; jj<=m; jj++)
{
y = a->ptr.pp_double[jj][j];
z = a->ptr.pp_double[jj][i];
a->ptr.pp_double[jj][j] = y*c+z*s;
a->ptr.pp_double[jj][i] = -y*s+z*c;
}
}
rv1.ptr.p_double[l] = 0.0;
rv1.ptr.p_double[k] = f;
w->ptr.p_double[k] = x;
}
}
ae_frame_leave(_state);
return result;
}
static double testmatgenunit_extsign(double a, double b, ae_state *_state)
{
double result;
if( ae_fp_greater_eq(b,(double)(0)) )
{
result = ae_fabs(a, _state);
}
else
{
result = -ae_fabs(a, _state);
}
return result;
}
static double testmatgenunit_mymax(double a, double b, ae_state *_state)
{
double result;
if( ae_fp_greater(a,b) )
{
result = a;
}
else
{
result = b;
}
return result;
}
static double testmatgenunit_pythag(double a, double b, ae_state *_state)
{
double result;
if( ae_fp_less(ae_fabs(a, _state),ae_fabs(b, _state)) )
{
result = ae_fabs(b, _state)*ae_sqrt(1+ae_sqr(a/b, _state), _state);
}
else
{
result = ae_fabs(a, _state)*ae_sqrt(1+ae_sqr(b/a, _state), _state);
}
return result;
}
static void testtrfacunit_testcluproblem(/* Complex */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double threshold,
ae_bool* err,
ae_bool* properr,
ae_state *_state);
static void testtrfacunit_testrluproblem(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double threshold,
ae_bool* err,
ae_bool* properr,
ae_state *_state);
static void testtrfacunit_testdensecholeskyupdates(ae_bool* spdupderrorflag,
ae_state *_state);
ae_bool testtrfac(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_matrix ra;
ae_matrix ral;
ae_matrix rau;
ae_matrix ca;
ae_matrix cal;
ae_matrix cau;
ae_int_t m;
ae_int_t n;
ae_int_t mx;
ae_int_t maxmn;
ae_int_t largemn;
ae_int_t i;
ae_int_t j;
ae_complex vc;
double vr;
ae_bool waserrors;
ae_bool dspderr;
ae_bool sspderr;
ae_bool srerr;
ae_bool hpderr;
ae_bool rerr;
ae_bool cerr;
ae_bool properr;
ae_bool dspdupderr;
double threshold;
ae_int_t pass;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&ra, 0, sizeof(ra));
memset(&ral, 0, sizeof(ral));
memset(&rau, 0, sizeof(rau));
memset(&ca, 0, sizeof(ca));
memset(&cal, 0, sizeof(cal));
memset(&cau, 0, sizeof(cau));
ae_matrix_init(&ra, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ral, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&rau, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ca, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&cal, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&cau, 0, 0, DT_COMPLEX, _state, ae_true);
rerr = ae_false;
dspderr = ae_false;
sspderr = ae_false;
cerr = ae_false;
hpderr = ae_false;
properr = ae_false;
dspdupderr = ae_false;
srerr = ae_false;
waserrors = ae_false;
maxmn = 4*matrixtilesizea(_state)+1;
largemn = 256;
threshold = 1000*ae_machineepsilon*maxmn;
/*
* Sparse Cholesky
*/
sspderr = sparserealcholeskytest(_state);
/*
* Sparse LU
*/
sparsereallutest(&srerr, _state);
/*
* Cholesky updates
*/
testtrfacunit_testdensecholeskyupdates(&dspdupderr, _state);
/*
* test LU:
* * first, test on small-scale matrices
* * then, perform several large-scale tests
*/
for(mx=1; mx<=maxmn; mx++)
{
/*
* Initialize N/M, both are <=MX,
* at least one of them is exactly equal to MX
*/
n = 1+ae_randominteger(mx, _state);
m = 1+ae_randominteger(mx, _state);
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
n = mx;
}
else
{
m = mx;
}
/*
* First, test on zero matrix
*/
ae_matrix_set_length(&ra, m, n, _state);
ae_matrix_set_length(&ca, m, n, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
ra.ptr.pp_double[i][j] = (double)(0);
ca.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
testtrfacunit_testcluproblem(&ca, m, n, threshold, &cerr, &properr, _state);
testtrfacunit_testrluproblem(&ra, m, n, threshold, &rerr, &properr, _state);
/*
* Second, random matrix with moderate condition number
*/
ae_matrix_set_length(&ra, m, n, _state);
ae_matrix_set_length(&ca, m, n, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
ra.ptr.pp_double[i][j] = (double)(0);
ca.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
for(i=0; i<=ae_minint(m, n, _state)-1; i++)
{
ra.ptr.pp_double[i][i] = 1+10*ae_randomreal(_state);
ca.ptr.pp_complex[i][i] = ae_complex_from_d(1+10*ae_randomreal(_state));
}
cmatrixrndorthogonalfromtheleft(&ca, m, n, _state);
cmatrixrndorthogonalfromtheright(&ca, m, n, _state);
rmatrixrndorthogonalfromtheleft(&ra, m, n, _state);
rmatrixrndorthogonalfromtheright(&ra, m, n, _state);
testtrfacunit_testcluproblem(&ca, m, n, threshold, &cerr, &properr, _state);
testtrfacunit_testrluproblem(&ra, m, n, threshold, &rerr, &properr, _state);
}
for(pass=1; pass<=2; pass++)
{
m = largemn+(ae_randominteger(3, _state)-1);
n = largemn+(ae_randominteger(3, _state)-1);
/*
* Random matrix with moderate condition number
*/
ae_matrix_set_length(&ra, m, n, _state);
ae_matrix_set_length(&ca, m, n, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
ra.ptr.pp_double[i][j] = (double)(0);
ca.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
for(i=0; i<=ae_minint(m, n, _state)-1; i++)
{
ra.ptr.pp_double[i][i] = 1+10*ae_randomreal(_state);
ca.ptr.pp_complex[i][i] = ae_complex_from_d(1+10*ae_randomreal(_state));
}
cmatrixrndorthogonalfromtheleft(&ca, m, n, _state);
cmatrixrndorthogonalfromtheright(&ca, m, n, _state);
rmatrixrndorthogonalfromtheleft(&ra, m, n, _state);
rmatrixrndorthogonalfromtheright(&ra, m, n, _state);
testtrfacunit_testcluproblem(&ca, m, n, threshold, &cerr, &properr, _state);
testtrfacunit_testrluproblem(&ra, m, n, threshold, &rerr, &properr, _state);
}
/*
* Test Cholesky
*/
for(n=1; n<=maxmn; n++)
{
/*
* Load CA (HPD matrix with low condition number),
* CAL and CAU - its lower and upper triangles
*/
hpdmatrixrndcond(n, 1+50*ae_randomreal(_state), &ca, _state);
ae_matrix_set_length(&cal, n, n, _state);
ae_matrix_set_length(&cau, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
cal.ptr.pp_complex[i][j] = ae_complex_from_i(i);
cau.ptr.pp_complex[i][j] = ae_complex_from_i(j);
}
}
for(i=0; i<=n-1; i++)
{
ae_v_cmove(&cal.ptr.pp_complex[i][0], 1, &ca.ptr.pp_complex[i][0], 1, "N", ae_v_len(0,i));
ae_v_cmove(&cau.ptr.pp_complex[i][i], 1, &ca.ptr.pp_complex[i][i], 1, "N", ae_v_len(i,n-1));
}
/*
* Test HPDMatrixCholesky:
* 1. it must leave upper (lower) part unchanged
* 2. max(A-L*L^H) must be small
*/
if( hpdmatrixcholesky(&cal, n, ae_false, _state) )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( j>i )
{
hpderr = hpderr||ae_c_neq_d(cal.ptr.pp_complex[i][j],(double)(i));
}
else
{
vc = ae_v_cdotproduct(&cal.ptr.pp_complex[i][0], 1, "N", &cal.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,j));
hpderr = hpderr||ae_fp_greater(ae_c_abs(ae_c_sub(ca.ptr.pp_complex[i][j],vc), _state),threshold);
}
}
}
}
else
{
hpderr = ae_true;
}
if( hpdmatrixcholesky(&cau, n, ae_true, _state) )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ji )
{
dspderr = dspderr||ae_fp_neq(ral.ptr.pp_double[i][j],(double)(i));
}
else
{
vr = ae_v_dotproduct(&ral.ptr.pp_double[i][0], 1, &ral.ptr.pp_double[j][0], 1, ae_v_len(0,j));
dspderr = dspderr||ae_fp_greater(ae_fabs(ra.ptr.pp_double[i][j]-vr, _state),threshold);
}
}
}
}
else
{
dspderr = ae_true;
}
if( spdmatrixcholesky(&rau, n, ae_true, _state) )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( j1 )
{
pnz = (double)nz/(double)(n*n-n);
}
else
{
pnz = 1.0;
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=i; j++)
{
if( i==j )
{
a.ptr.pp_double[i][i] = 1+hqrnduniformr(&rs, _state);
continue;
}
if( ae_fp_less_eq(hqrnduniformr(&rs, _state),pnz) )
{
a.ptr.pp_double[i][j] = offscale*(hqrnduniformr(&rs, _state)-0.5);
a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j];
}
else
{
a.ptr.pp_double[i][j] = 0.0;
a.ptr.pp_double[j][i] = 0.0;
}
}
}
/*
* Problem statement
*/
isupper = ae_fp_greater(ae_randomreal(_state),0.5);
cfmt = ae_randominteger(maxfmt+1, _state);
cord = ae_randominteger(maxord+1-minord, _state)+minord;
/*
* Create matrix is hash-based storage format, convert it to random storage format.
*/
sparsecreate(n, n, 0, &sa, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (j<=i&&!isupper)||(j>=i&&isupper) )
{
sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state);
}
}
}
sparseconvertto(&sa, hqrnduniformi(&rs, maxfmt+1, _state), _state);
/*
* Perform sparse Cholesky and make several tests:
* * correctness of P0 and P1 (they are correct permutations and one is inverse of another)
* * format of SC matches CFmt
* * SC has correct size (exactly N*N)
* * check that correct triangle is returned
*/
if( !sparsecholeskyx(&sa, n, isupper, &p0, &p1, cord, ae_randominteger(3, _state), cfmt, &sbuf, &sc, _state) )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:682");
ae_frame_leave(_state);
return result;
}
ae_set_error_flag(&result, p0.cnt=n, __FILE__, __LINE__, "testtrfacunit.ap:697");
ae_set_error_flag(&result, p1.ptr.p_int[i]>=n, __FILE__, __LINE__, "testtrfacunit.ap:698");
if( result )
{
ae_frame_leave(_state);
return result;
}
ae_set_error_flag(&result, b1.ptr.p_bool[p0.ptr.p_int[i]], __FILE__, __LINE__, "testtrfacunit.ap:703");
b1.ptr.p_bool[p0.ptr.p_int[i]] = ae_true;
ae_set_error_flag(&result, p1.ptr.p_int[p0.ptr.p_int[i]]!=i, __FILE__, __LINE__, "testtrfacunit.ap:707");
}
ae_set_error_flag(&result, sparsegetmatrixtype(&sc, _state)!=cfmt, __FILE__, __LINE__, "testtrfacunit.ap:709");
ae_set_error_flag(&result, sparsegetncols(&sc, _state)!=n, __FILE__, __LINE__, "testtrfacunit.ap:710");
ae_set_error_flag(&result, sparsegetnrows(&sc, _state)!=n, __FILE__, __LINE__, "testtrfacunit.ap:711");
t0 = 0;
t1 = 0;
while(sparseenumerate(&sc, &t0, &t1, &i, &j, &v, _state))
{
ae_set_error_flag(&result, ji&&!isupper, __FILE__, __LINE__, "testtrfacunit.ap:717");
}
/*
* Now, test correctness of Cholesky decomposition itself.
* We calculate U'*U (or L*L') and check at against permutation
* of A given by P0.
*
* NOTE: we expect that only one triangle of SC is filled,
* and another one is exactly zero.
*/
if( isupper )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = 0.0;
for(k=0; k<=n-1; k++)
{
v = v+sparseget(&sc, k, j, _state)*sparseget(&sc, k, i, _state);
}
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(a.ptr.pp_double[p0.ptr.p_int[i]][p0.ptr.p_int[j]]-v, _state),tol), __FILE__, __LINE__, "testtrfacunit.ap:736");
}
}
}
else
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = 0.0;
for(k=0; k<=n-1; k++)
{
v = v+sparseget(&sc, j, k, _state)*sparseget(&sc, i, k, _state);
}
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(a.ptr.pp_double[p0.ptr.p_int[i]][p0.ptr.p_int[j]]-v, _state),tol), __FILE__, __LINE__, "testtrfacunit.ap:747");
}
}
}
/*
* Increase problem sparcity and try one more time.
* Stop after testing NZ=0.
*/
if( nz==0 )
{
break;
}
nz = nz/2;
}
}
/*
* SparseCholeskySkyline test: performed for matrices
* of all sizes in 1..20 and all sparcity percentages.
*/
for(n=1; n<=20; n++)
{
nz = n*n-n;
for(;;)
{
/*
* Choose IsUpper - main triangle to work with.
*
* Generate A - symmetric N*N matrix where probability of non-diagonal
* element being non-zero is PNZ. Off-diagonal elements are set to
* very small values, so positive definiteness is guaranteed. Full matrix
* is generated.
*
* Additionally, we create A1 - same as A, but one of the triangles is
* asymmetrically spoiled. If IsUpper is True, we spoil lower one, or vice versa.
*/
isupper = ae_fp_greater(ae_randomreal(_state),0.5);
if( n>1 )
{
pnz = (double)nz/(double)(n*n-n);
}
else
{
pnz = 1.0;
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=i; j++)
{
if( i==j )
{
a.ptr.pp_double[i][i] = 1+hqrnduniformr(&rs, _state);
continue;
}
if( ae_fp_less_eq(hqrnduniformr(&rs, _state),pnz) )
{
a.ptr.pp_double[i][j] = offscale*(hqrnduniformr(&rs, _state)-0.5);
a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j];
}
else
{
a.ptr.pp_double[i][j] = 0.0;
a.ptr.pp_double[j][i] = 0.0;
}
}
}
ae_matrix_set_length(&a1, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (j<=i&&!isupper)||(j>=i&&isupper) )
{
/*
* Copy one triangle
*/
a1.ptr.pp_double[i][j] = a.ptr.pp_double[i][j];
}
else
{
/*
* Form another sparse pattern in different triangle.
*/
if( ae_fp_less_eq(hqrnduniformr(&rs, _state),pnz) )
{
a1.ptr.pp_double[i][j] = offscale*(hqrnduniformr(&rs, _state)-0.5);
}
else
{
a1.ptr.pp_double[i][j] = 0.0;
}
}
}
}
/*
* Create copies of A and A1 in hash-based storage format.
* Only one triangle of A is copied, but A1 is copied fully.
* Convert them to SKS
*/
sparsecreate(n, n, 0, &sa, _state);
sparsecreate(n, n, 0, &sa1, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (j<=i&&!isupper)||(j>=i&&isupper) )
{
sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state);
}
sparseset(&sa1, i, j, a1.ptr.pp_double[i][j], _state);
}
}
sparseconverttosks(&sa, _state);
sparseconverttosks(&sa1, _state);
/*
* Call SparseCholeskySkyline() for SA and make several tests:
* * check that it is still SKS
* * check that it has correct size (exactly N*N)
* * check that correct triangle is returned (and another one is unchanged - zero)
* * check that it is correct Cholesky decomposition.
* We calculate U'*U (or L*L') and check at against A. We expect
* that only one triangle of SA is filled, and another one is
* exactly zero.
*/
if( !sparsecholeskyskyline(&sa, n, isupper, _state) )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:859");
ae_frame_leave(_state);
return result;
}
ae_set_error_flag(&result, !sparseissks(&sa, _state), __FILE__, __LINE__, "testtrfacunit.ap:862");
ae_set_error_flag(&result, sparsegetncols(&sa, _state)!=n, __FILE__, __LINE__, "testtrfacunit.ap:863");
ae_set_error_flag(&result, sparsegetnrows(&sa, _state)!=n, __FILE__, __LINE__, "testtrfacunit.ap:864");
t0 = 0;
t1 = 0;
while(sparseenumerate(&sa, &t0, &t1, &i, &j, &v, _state))
{
ae_set_error_flag(&result, ji&&!isupper, __FILE__, __LINE__, "testtrfacunit.ap:870");
}
if( isupper )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = 0.0;
for(k=0; k<=n-1; k++)
{
v = v+sparseget(&sa, k, j, _state)*sparseget(&sa, k, i, _state);
}
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-v, _state),tol), __FILE__, __LINE__, "testtrfacunit.ap:880");
}
}
}
else
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = 0.0;
for(k=0; k<=n-1; k++)
{
v = v+sparseget(&sa, j, k, _state)*sparseget(&sa, i, k, _state);
}
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-v, _state),tol), __FILE__, __LINE__, "testtrfacunit.ap:891");
}
}
}
/*
* Call SparseCholeskySkyline() for SA1 and make several tests:
* * check that it is still SKS
* * check that it has correct size (exactly N*N)
* * check that factorized triangle matches contents of SA,
* and another triangle was unchanged (matches contents of A1).
*/
if( !sparsecholeskyskyline(&sa1, n, isupper, _state) )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testtrfacunit.ap:904");
ae_frame_leave(_state);
return result;
}
ae_set_error_flag(&result, !sparseissks(&sa1, _state), __FILE__, __LINE__, "testtrfacunit.ap:907");
ae_set_error_flag(&result, sparsegetncols(&sa1, _state)!=n, __FILE__, __LINE__, "testtrfacunit.ap:908");
ae_set_error_flag(&result, sparsegetnrows(&sa1, _state)!=n, __FILE__, __LINE__, "testtrfacunit.ap:909");
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (j<=i&&!isupper)||(j>=i&&isupper) )
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(sparseget(&sa1, i, j, _state)-sparseget(&sa, i, j, _state), _state),10*ae_machineepsilon), __FILE__, __LINE__, "testtrfacunit.ap:913");
}
else
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(sparseget(&sa1, i, j, _state)-a1.ptr.pp_double[i][j], _state),10*ae_machineepsilon), __FILE__, __LINE__, "testtrfacunit.ap:915");
}
}
}
/*
* Increase problem sparcity and try one more time.
* Stop after testing NZ=0.
*/
if( nz==0 )
{
break;
}
nz = nz/2;
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Function for testing sparse real LU decomposition.
Sets error flag on failure, leave is unchanged on success.
-- ALGLIB PROJECT --
Copyright 16.01.1014 by Bochkanov Sergey
*************************************************************************/
void sparsereallutest(ae_bool* err, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t nz;
double pnz;
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
ae_matrix a;
ae_matrix b1;
ae_matrix b2;
ae_matrix c;
ae_vector pivr;
ae_vector pivc;
sparsematrix sa;
sparsematrix crsa;
ae_bool success;
double tol;
ae_bool haszero;
ae_int_t pivottype;
hqrndstate rs;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&b1, 0, sizeof(b1));
memset(&b2, 0, sizeof(b2));
memset(&c, 0, sizeof(c));
memset(&pivr, 0, sizeof(pivr));
memset(&pivc, 0, sizeof(pivc));
memset(&sa, 0, sizeof(sa));
memset(&crsa, 0, sizeof(crsa));
memset(&rs, 0, sizeof(rs));
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&b1, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&b2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&pivr, 0, DT_INT, _state, ae_true);
ae_vector_init(&pivc, 0, DT_INT, _state, ae_true);
_sparsematrix_init(&sa, _state, ae_true);
_sparsematrix_init(&crsa, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
tol = 1.0E4*ae_machineepsilon;
/*
* Test matrix sizes in 1...20 and with all sparsity percentages
*/
for(n=1; n<=20; n++)
{
nz = n*n;
for(;;)
{
/*
* Generate N*N matrix where probability of element being
* non-zero is PNZ. Create sparse matrix in hash-based storage format.
*/
pnz = (double)nz/(double)(n*n);
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_less_eq(hqrnduniformr(&rs, _state),pnz) )
{
a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
else
{
a.ptr.pp_double[i][j] = 0.0;
}
}
}
sparsecreate(n, n, 0, &sa, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state);
}
}
/*
* Test SparseLU()
*/
for(pivottype=0; pivottype<=2; pivottype++)
{
sparsecopytocrs(&sa, &crsa, _state);
ae_vector_set_length(&pivr, 0, _state);
ae_vector_set_length(&pivc, 0, _state);
success = sparselu(&crsa, pivottype, &pivr, &pivc, _state);
ae_set_error_flag(err, !sparseiscrs(&crsa, _state), __FILE__, __LINE__, "testtrfacunit.ap:993");
ae_set_error_flag(err, sparsegetncols(&crsa, _state)!=n, __FILE__, __LINE__, "testtrfacunit.ap:994");
ae_set_error_flag(err, sparsegetnrows(&crsa, _state)!=n, __FILE__, __LINE__, "testtrfacunit.ap:995");
ae_set_error_flag(err, pivr.cnt!=n, __FILE__, __LINE__, "testtrfacunit.ap:996");
ae_set_error_flag(err, pivc.cnt!=n, __FILE__, __LINE__, "testtrfacunit.ap:997");
if( *err )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(err, ((pivr.ptr.p_int[i]<0||pivr.ptr.p_int[i]>=n)||pivc.ptr.p_int[i]<0)||pivc.ptr.p_int[i]>=n, __FILE__, __LINE__, "testtrfacunit.ap:1001");
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(err, pivottype==1&&pivc.ptr.p_int[i]!=i, __FILE__, __LINE__, "testtrfacunit.ap:1003");
}
ae_matrix_set_length(&b1, n, n, _state);
ae_matrix_set_length(&b2, n, n, _state);
haszero = ae_false;
for(i=0; i<=n-1; i++)
{
for(j=0; j<=i-1; j++)
{
b1.ptr.pp_double[i][j] = sparseget(&crsa, i, j, _state);
}
b1.ptr.pp_double[i][i] = (double)(1);
for(j=i+1; j<=n-1; j++)
{
b1.ptr.pp_double[i][j] = (double)(0);
}
for(j=0; j<=i-1; j++)
{
b2.ptr.pp_double[i][j] = (double)(0);
}
for(j=i; j<=n-1; j++)
{
b2.ptr.pp_double[i][j] = sparseget(&crsa, i, j, _state);
}
haszero = haszero||ae_fp_eq(b2.ptr.pp_double[i][i],(double)(0));
}
ae_matrix_set_length(&c, n, n, _state);
rmatrixgemm(n, n, n, 1.0, &b1, 0, 0, 0, &b2, 0, 0, 0, 0.0, &c, 0, 0, _state);
for(i=n-1; i>=0; i--)
{
j = pivr.ptr.p_int[i];
for(k=0; k<=n-1; k++)
{
v = c.ptr.pp_double[i][k];
c.ptr.pp_double[i][k] = c.ptr.pp_double[j][k];
c.ptr.pp_double[j][k] = v;
}
}
for(i=n-1; i>=0; i--)
{
j = pivc.ptr.p_int[i];
for(k=0; k<=n-1; k++)
{
v = c.ptr.pp_double[k][i];
c.ptr.pp_double[k][i] = c.ptr.pp_double[k][j];
c.ptr.pp_double[k][j] = v;
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(c.ptr.pp_double[i][j]-a.ptr.pp_double[i][j], _state),tol), __FILE__, __LINE__, "testtrfacunit.ap:1052");
}
}
ae_set_error_flag(err, (success&&haszero)||(!haszero&&!success), __FILE__, __LINE__, "testtrfacunit.ap:1053");
}
/*
* Increase problem sparcity and try one more time.
* Stop after testing NZ=0.
*/
if( nz==0 )
{
break;
}
nz = nz/2;
}
}
ae_frame_leave(_state);
}
static void testtrfacunit_testcluproblem(/* Complex */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double threshold,
ae_bool* err,
ae_bool* properr,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix ca;
ae_matrix cl;
ae_matrix cu;
ae_matrix ca2;
ae_vector ct;
ae_int_t i;
ae_int_t j;
ae_int_t minmn;
ae_complex v;
ae_vector p;
ae_frame_make(_state, &_frame_block);
memset(&ca, 0, sizeof(ca));
memset(&cl, 0, sizeof(cl));
memset(&cu, 0, sizeof(cu));
memset(&ca2, 0, sizeof(ca2));
memset(&ct, 0, sizeof(ct));
memset(&p, 0, sizeof(p));
ae_matrix_init(&ca, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&cl, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&cu, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&ca2, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&ct, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&p, 0, DT_INT, _state, ae_true);
minmn = ae_minint(m, n, _state);
/*
* PLU test
*/
ae_matrix_set_length(&ca, m, n, _state);
for(i=0; i<=m-1; i++)
{
ae_v_cmove(&ca.ptr.pp_complex[i][0], 1, &a->ptr.pp_complex[i][0], 1, "N", ae_v_len(0,n-1));
}
cmatrixplu(&ca, m, n, &p, _state);
for(i=0; i<=minmn-1; i++)
{
if( p.ptr.p_int[i]=m )
{
*properr = ae_true;
ae_frame_leave(_state);
return;
}
}
ae_matrix_set_length(&cl, m, minmn, _state);
for(j=0; j<=minmn-1; j++)
{
for(i=0; i<=j-1; i++)
{
cl.ptr.pp_complex[i][j] = ae_complex_from_d(0.0);
}
cl.ptr.pp_complex[j][j] = ae_complex_from_d(1.0);
for(i=j+1; i<=m-1; i++)
{
cl.ptr.pp_complex[i][j] = ca.ptr.pp_complex[i][j];
}
}
ae_matrix_set_length(&cu, minmn, n, _state);
for(i=0; i<=minmn-1; i++)
{
for(j=0; j<=i-1; j++)
{
cu.ptr.pp_complex[i][j] = ae_complex_from_d(0.0);
}
for(j=i; j<=n-1; j++)
{
cu.ptr.pp_complex[i][j] = ca.ptr.pp_complex[i][j];
}
}
ae_matrix_set_length(&ca2, m, n, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_cdotproduct(&cl.ptr.pp_complex[i][0], 1, "N", &cu.ptr.pp_complex[0][j], cu.stride, "N", ae_v_len(0,minmn-1));
ca2.ptr.pp_complex[i][j] = v;
}
}
ae_vector_set_length(&ct, n, _state);
for(i=minmn-1; i>=0; i--)
{
if( i!=p.ptr.p_int[i] )
{
ae_v_cmove(&ct.ptr.p_complex[0], 1, &ca2.ptr.pp_complex[i][0], 1, "N", ae_v_len(0,n-1));
ae_v_cmove(&ca2.ptr.pp_complex[i][0], 1, &ca2.ptr.pp_complex[p.ptr.p_int[i]][0], 1, "N", ae_v_len(0,n-1));
ae_v_cmove(&ca2.ptr.pp_complex[p.ptr.p_int[i]][0], 1, &ct.ptr.p_complex[0], 1, "N", ae_v_len(0,n-1));
}
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
*err = *err||ae_fp_greater(ae_c_abs(ae_c_sub(a->ptr.pp_complex[i][j],ca2.ptr.pp_complex[i][j]), _state),threshold);
}
}
/*
* LUP test
*/
ae_matrix_set_length(&ca, m, n, _state);
for(i=0; i<=m-1; i++)
{
ae_v_cmove(&ca.ptr.pp_complex[i][0], 1, &a->ptr.pp_complex[i][0], 1, "N", ae_v_len(0,n-1));
}
cmatrixlup(&ca, m, n, &p, _state);
for(i=0; i<=minmn-1; i++)
{
if( p.ptr.p_int[i]=n )
{
*properr = ae_true;
ae_frame_leave(_state);
return;
}
}
ae_matrix_set_length(&cl, m, minmn, _state);
for(j=0; j<=minmn-1; j++)
{
for(i=0; i<=j-1; i++)
{
cl.ptr.pp_complex[i][j] = ae_complex_from_d(0.0);
}
for(i=j; i<=m-1; i++)
{
cl.ptr.pp_complex[i][j] = ca.ptr.pp_complex[i][j];
}
}
ae_matrix_set_length(&cu, minmn, n, _state);
for(i=0; i<=minmn-1; i++)
{
for(j=0; j<=i-1; j++)
{
cu.ptr.pp_complex[i][j] = ae_complex_from_d(0.0);
}
cu.ptr.pp_complex[i][i] = ae_complex_from_d(1.0);
for(j=i+1; j<=n-1; j++)
{
cu.ptr.pp_complex[i][j] = ca.ptr.pp_complex[i][j];
}
}
ae_matrix_set_length(&ca2, m, n, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_cdotproduct(&cl.ptr.pp_complex[i][0], 1, "N", &cu.ptr.pp_complex[0][j], cu.stride, "N", ae_v_len(0,minmn-1));
ca2.ptr.pp_complex[i][j] = v;
}
}
ae_vector_set_length(&ct, m, _state);
for(i=minmn-1; i>=0; i--)
{
if( i!=p.ptr.p_int[i] )
{
ae_v_cmove(&ct.ptr.p_complex[0], 1, &ca2.ptr.pp_complex[0][i], ca2.stride, "N", ae_v_len(0,m-1));
ae_v_cmove(&ca2.ptr.pp_complex[0][i], ca2.stride, &ca2.ptr.pp_complex[0][p.ptr.p_int[i]], ca2.stride, "N", ae_v_len(0,m-1));
ae_v_cmove(&ca2.ptr.pp_complex[0][p.ptr.p_int[i]], ca2.stride, &ct.ptr.p_complex[0], 1, "N", ae_v_len(0,m-1));
}
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
*err = *err||ae_fp_greater(ae_c_abs(ae_c_sub(a->ptr.pp_complex[i][j],ca2.ptr.pp_complex[i][j]), _state),threshold);
}
}
ae_frame_leave(_state);
}
static void testtrfacunit_testrluproblem(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double threshold,
ae_bool* err,
ae_bool* properr,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix ca;
ae_matrix cl;
ae_matrix cu;
ae_matrix ca2;
ae_vector ct;
ae_int_t i;
ae_int_t j;
ae_int_t minmn;
double v;
ae_vector p;
ae_frame_make(_state, &_frame_block);
memset(&ca, 0, sizeof(ca));
memset(&cl, 0, sizeof(cl));
memset(&cu, 0, sizeof(cu));
memset(&ca2, 0, sizeof(ca2));
memset(&ct, 0, sizeof(ct));
memset(&p, 0, sizeof(p));
ae_matrix_init(&ca, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&cl, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&cu, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ca2, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ct, 0, DT_REAL, _state, ae_true);
ae_vector_init(&p, 0, DT_INT, _state, ae_true);
minmn = ae_minint(m, n, _state);
/*
* PLU test
*/
ae_matrix_set_length(&ca, m, n, _state);
for(i=0; i<=m-1; i++)
{
ae_v_move(&ca.ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
}
rmatrixplu(&ca, m, n, &p, _state);
for(i=0; i<=minmn-1; i++)
{
if( p.ptr.p_int[i]=m )
{
*properr = ae_true;
ae_frame_leave(_state);
return;
}
}
ae_matrix_set_length(&cl, m, minmn, _state);
for(j=0; j<=minmn-1; j++)
{
for(i=0; i<=j-1; i++)
{
cl.ptr.pp_double[i][j] = 0.0;
}
cl.ptr.pp_double[j][j] = 1.0;
for(i=j+1; i<=m-1; i++)
{
cl.ptr.pp_double[i][j] = ca.ptr.pp_double[i][j];
}
}
ae_matrix_set_length(&cu, minmn, n, _state);
for(i=0; i<=minmn-1; i++)
{
for(j=0; j<=i-1; j++)
{
cu.ptr.pp_double[i][j] = 0.0;
}
for(j=i; j<=n-1; j++)
{
cu.ptr.pp_double[i][j] = ca.ptr.pp_double[i][j];
}
}
ae_matrix_set_length(&ca2, m, n, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&cl.ptr.pp_double[i][0], 1, &cu.ptr.pp_double[0][j], cu.stride, ae_v_len(0,minmn-1));
ca2.ptr.pp_double[i][j] = v;
}
}
ae_vector_set_length(&ct, n, _state);
for(i=minmn-1; i>=0; i--)
{
if( i!=p.ptr.p_int[i] )
{
ae_v_move(&ct.ptr.p_double[0], 1, &ca2.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
ae_v_move(&ca2.ptr.pp_double[i][0], 1, &ca2.ptr.pp_double[p.ptr.p_int[i]][0], 1, ae_v_len(0,n-1));
ae_v_move(&ca2.ptr.pp_double[p.ptr.p_int[i]][0], 1, &ct.ptr.p_double[0], 1, ae_v_len(0,n-1));
}
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
*err = *err||ae_fp_greater(ae_fabs(a->ptr.pp_double[i][j]-ca2.ptr.pp_double[i][j], _state),threshold);
}
}
/*
* LUP test
*/
ae_matrix_set_length(&ca, m, n, _state);
for(i=0; i<=m-1; i++)
{
ae_v_move(&ca.ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
}
rmatrixlup(&ca, m, n, &p, _state);
for(i=0; i<=minmn-1; i++)
{
if( p.ptr.p_int[i]=n )
{
*properr = ae_true;
ae_frame_leave(_state);
return;
}
}
ae_matrix_set_length(&cl, m, minmn, _state);
for(j=0; j<=minmn-1; j++)
{
for(i=0; i<=j-1; i++)
{
cl.ptr.pp_double[i][j] = 0.0;
}
for(i=j; i<=m-1; i++)
{
cl.ptr.pp_double[i][j] = ca.ptr.pp_double[i][j];
}
}
ae_matrix_set_length(&cu, minmn, n, _state);
for(i=0; i<=minmn-1; i++)
{
for(j=0; j<=i-1; j++)
{
cu.ptr.pp_double[i][j] = 0.0;
}
cu.ptr.pp_double[i][i] = 1.0;
for(j=i+1; j<=n-1; j++)
{
cu.ptr.pp_double[i][j] = ca.ptr.pp_double[i][j];
}
}
ae_matrix_set_length(&ca2, m, n, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&cl.ptr.pp_double[i][0], 1, &cu.ptr.pp_double[0][j], cu.stride, ae_v_len(0,minmn-1));
ca2.ptr.pp_double[i][j] = v;
}
}
ae_vector_set_length(&ct, m, _state);
for(i=minmn-1; i>=0; i--)
{
if( i!=p.ptr.p_int[i] )
{
ae_v_move(&ct.ptr.p_double[0], 1, &ca2.ptr.pp_double[0][i], ca2.stride, ae_v_len(0,m-1));
ae_v_move(&ca2.ptr.pp_double[0][i], ca2.stride, &ca2.ptr.pp_double[0][p.ptr.p_int[i]], ca2.stride, ae_v_len(0,m-1));
ae_v_move(&ca2.ptr.pp_double[0][p.ptr.p_int[i]], ca2.stride, &ct.ptr.p_double[0], 1, ae_v_len(0,m-1));
}
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
*err = *err||ae_fp_greater(ae_fabs(a->ptr.pp_double[i][j]-ca2.ptr.pp_double[i][j], _state),threshold);
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Function for testing dense Cholesky updates
Sets error flag to True on errors, does not change it on success.
-- ALGLIB PROJECT --
Copyright 16.01.1014 by Bochkanov Sergey
*************************************************************************/
static void testtrfacunit_testdensecholeskyupdates(ae_bool* spdupderrorflag,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
double pfix;
ae_matrix a0;
ae_matrix a1;
ae_vector u;
ae_vector fix;
ae_int_t i;
ae_int_t j;
ae_bool isupper;
double tol;
ae_vector bufr;
hqrndstate rs;
ae_frame_make(_state, &_frame_block);
memset(&a0, 0, sizeof(a0));
memset(&a1, 0, sizeof(a1));
memset(&u, 0, sizeof(u));
memset(&fix, 0, sizeof(fix));
memset(&bufr, 0, sizeof(bufr));
memset(&rs, 0, sizeof(rs));
ae_matrix_init(&a0, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&u, 0, DT_REAL, _state, ae_true);
ae_vector_init(&fix, 0, DT_BOOL, _state, ae_true);
ae_vector_init(&bufr, 0, DT_REAL, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Settings
*/
tol = 1.0E-8;
/*
* Test rank-1 updates
*
* For each matrix size in 1..30 select sparse update vector with probability of element
* being non-zero equal to 1/2.
*/
for(n=1; n<=30; n++)
{
/*
* Generate two matrices A0=A1, fill one triangle with SPD matrix,
* another one with trash. Prepare vector U.
*/
isupper = ae_fp_less(hqrnduniformr(&rs, _state),0.5);
spdmatrixrndcond(n, 1.0E4, &a0, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (ji&&!isupper) )
{
a0.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5;
}
}
}
ae_matrix_set_length(&a1, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a1.ptr.pp_double[i][j] = a0.ptr.pp_double[i][j];
}
}
ae_vector_set_length(&u, n, _state);
for(i=0; i<=n-1; i++)
{
if( ae_fp_less_eq(hqrnduniformr(&rs, _state),0.5) )
{
u.ptr.p_double[i] = hqrnduniformr(&rs, _state)-0.5;
}
else
{
u.ptr.p_double[i] = (double)(0);
}
}
/*
* Factorize and compare:
* * A0 is factorized as follows: first with full Cholesky, then
* we call SPDMatrixCholeskyUpdateAdd1
* * A1 is transformed explicitly before factorization with full Cholesky
*
* We randomly test either SPDMatrixCholeskyUpdateFix() or its
* buffered version, SPDMatrixCholeskyUpdateFixBuf()
*/
ae_set_error_flag(spdupderrorflag, !spdmatrixcholesky(&a0, n, isupper, _state), __FILE__, __LINE__, "testtrfacunit.ap:1135");
if( *spdupderrorflag )
{
ae_frame_leave(_state);
return;
}
if( ae_fp_less(hqrnduniformr(&rs, _state),0.5) )
{
spdmatrixcholeskyupdateadd1(&a0, n, isupper, &u, _state);
}
else
{
spdmatrixcholeskyupdateadd1buf(&a0, n, isupper, &u, &bufr, _state);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (j>=i&&isupper)||(j<=i&&!isupper) )
{
a1.ptr.pp_double[i][j] = a1.ptr.pp_double[i][j]+u.ptr.p_double[i]*u.ptr.p_double[j];
}
}
}
ae_set_error_flag(spdupderrorflag, !spdmatrixcholesky(&a1, n, isupper, _state), __FILE__, __LINE__, "testtrfacunit.ap:1146");
if( *spdupderrorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
ae_set_error_flag(spdupderrorflag, ae_fp_greater(ae_fabs(a0.ptr.pp_double[i][j]-a1.ptr.pp_double[i][j], _state),tol), __FILE__, __LINE__, "testtrfacunit.ap:1151");
}
}
}
/*
* Test variable fixing functions.
*
* For each matrix size in 1..30 select PFix - probability of each variable being fixed,
* and perform test.
*/
for(n=1; n<=30; n++)
{
/*
* Generate two matrices A0=A1, fill one triangle with SPD matrix,
* another one with trash. Prepare vector Fix.
*/
pfix = (double)hqrnduniformi(&rs, n+1, _state)/(double)n;
isupper = ae_fp_less(hqrnduniformr(&rs, _state),0.5);
spdmatrixrndcond(n, 1.0E4, &a0, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (ji&&!isupper) )
{
a0.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5;
}
}
}
ae_matrix_set_length(&a1, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a1.ptr.pp_double[i][j] = a0.ptr.pp_double[i][j];
}
}
ae_vector_set_length(&fix, n, _state);
for(i=0; i<=n-1; i++)
{
fix.ptr.p_bool[i] = ae_fp_less_eq(hqrnduniformr(&rs, _state),pfix);
}
/*
* Factorize and compare:
* * A0 is factorized as follows: first with full Cholesky, then
* variables are fixed with SPDMatrixCholeskyUpdateFix
* * A1 is fixed explicitly before factorization with full Cholesky
*
* We randomly test either SPDMatrixCholeskyUpdateFix() or its
* buffered version, SPDMatrixCholeskyUpdateFixBuf()
*/
ae_set_error_flag(spdupderrorflag, !spdmatrixcholesky(&a0, n, isupper, _state), __FILE__, __LINE__, "testtrfacunit.ap:1190");
if( *spdupderrorflag )
{
ae_frame_leave(_state);
return;
}
if( ae_fp_less(hqrnduniformr(&rs, _state),0.5) )
{
spdmatrixcholeskyupdatefixbuf(&a0, n, isupper, &fix, &bufr, _state);
}
else
{
spdmatrixcholeskyupdatefix(&a0, n, isupper, &fix, _state);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (j>=i&&isupper)||(j<=i&&!isupper) )
{
if( fix.ptr.p_bool[i]||fix.ptr.p_bool[j] )
{
if( i==j )
{
a1.ptr.pp_double[i][j] = (double)(1);
}
else
{
a1.ptr.pp_double[i][j] = (double)(0);
}
}
}
}
}
ae_set_error_flag(spdupderrorflag, !spdmatrixcholesky(&a1, n, isupper, _state), __FILE__, __LINE__, "testtrfacunit.ap:1207");
if( *spdupderrorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
ae_set_error_flag(spdupderrorflag, ae_fp_greater(ae_fabs(a0.ptr.pp_double[i][j]-a1.ptr.pp_double[i][j], _state),tol), __FILE__, __LINE__, "testtrfacunit.ap:1212");
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Main unittest subroutine
*************************************************************************/
ae_bool testtrlinsolve(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t maxmn;
ae_int_t passcount;
double threshold;
ae_matrix aeffective;
ae_matrix aparam;
ae_vector xe;
ae_vector b;
ae_int_t n;
ae_int_t pass;
ae_int_t i;
ae_int_t j;
ae_int_t cnts;
ae_int_t cntu;
ae_int_t cntt;
ae_int_t cntm;
ae_bool waserrors;
ae_bool isupper;
ae_bool istrans;
ae_bool isunit;
double v;
double s;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&aeffective, 0, sizeof(aeffective));
memset(&aparam, 0, sizeof(aparam));
memset(&xe, 0, sizeof(xe));
memset(&b, 0, sizeof(b));
ae_matrix_init(&aeffective, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&aparam, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xe, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
waserrors = ae_false;
maxmn = 15;
passcount = 15;
threshold = 1000*ae_machineepsilon;
/*
* Different problems
*/
for(n=1; n<=maxmn; n++)
{
ae_matrix_set_length(&aeffective, n-1+1, n-1+1, _state);
ae_matrix_set_length(&aparam, n-1+1, n-1+1, _state);
ae_vector_set_length(&xe, n-1+1, _state);
ae_vector_set_length(&b, n-1+1, _state);
for(pass=1; pass<=passcount; pass++)
{
for(cnts=0; cnts<=1; cnts++)
{
for(cntu=0; cntu<=1; cntu++)
{
for(cntt=0; cntt<=1; cntt++)
{
for(cntm=0; cntm<=2; cntm++)
{
isupper = cnts==0;
isunit = cntu==0;
istrans = cntt==0;
/*
* Skip meaningless combinations of parameters:
* (matrix is singular) AND (matrix is unit diagonal)
*/
if( cntm==2&&isunit )
{
continue;
}
/*
* Clear matrices
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
aeffective.ptr.pp_double[i][j] = (double)(0);
aparam.ptr.pp_double[i][j] = (double)(0);
}
}
/*
* Prepare matrices
*/
if( isupper )
{
for(i=0; i<=n-1; i++)
{
for(j=i; j<=n-1; j++)
{
aeffective.ptr.pp_double[i][j] = 0.9*(2*ae_randomreal(_state)-1);
aparam.ptr.pp_double[i][j] = aeffective.ptr.pp_double[i][j];
}
aeffective.ptr.pp_double[i][i] = (2*ae_randominteger(2, _state)-1)*(0.8+ae_randomreal(_state));
aparam.ptr.pp_double[i][i] = aeffective.ptr.pp_double[i][i];
}
}
else
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=i; j++)
{
aeffective.ptr.pp_double[i][j] = 0.9*(2*ae_randomreal(_state)-1);
aparam.ptr.pp_double[i][j] = aeffective.ptr.pp_double[i][j];
}
aeffective.ptr.pp_double[i][i] = (2*ae_randominteger(2, _state)-1)*(0.8+ae_randomreal(_state));
aparam.ptr.pp_double[i][i] = aeffective.ptr.pp_double[i][i];
}
}
if( isunit )
{
for(i=0; i<=n-1; i++)
{
aeffective.ptr.pp_double[i][i] = (double)(1);
aparam.ptr.pp_double[i][i] = (double)(0);
}
}
if( istrans )
{
if( isupper )
{
for(i=0; i<=n-1; i++)
{
for(j=i+1; j<=n-1; j++)
{
aeffective.ptr.pp_double[j][i] = aeffective.ptr.pp_double[i][j];
aeffective.ptr.pp_double[i][j] = (double)(0);
}
}
}
else
{
for(i=0; i<=n-1; i++)
{
for(j=i+1; j<=n-1; j++)
{
aeffective.ptr.pp_double[i][j] = aeffective.ptr.pp_double[j][i];
aeffective.ptr.pp_double[j][i] = (double)(0);
}
}
}
}
/*
* Prepare task, solve, compare
*/
for(i=0; i<=n-1; i++)
{
xe.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&aeffective.ptr.pp_double[i][0], 1, &xe.ptr.p_double[0], 1, ae_v_len(0,n-1));
b.ptr.p_double[i] = v;
}
rmatrixtrsafesolve(&aparam, n, &b, &s, isupper, istrans, isunit, _state);
ae_v_muld(&xe.ptr.p_double[0], 1, ae_v_len(0,n-1), s);
ae_v_sub(&xe.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = ae_v_dotproduct(&xe.ptr.p_double[0], 1, &xe.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = ae_sqrt(v, _state);
waserrors = waserrors||ae_fp_greater(v,threshold);
}
}
}
}
}
}
/*
* report
*/
if( !silent )
{
printf("TESTING RMatrixTRSafeSolve\n");
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
static void testsafesolveunit_rmatrixmakeacopy(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Real */ ae_matrix* b,
ae_state *_state);
static void testsafesolveunit_cmatrixmakeacopy(/* Complex */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Complex */ ae_matrix* b,
ae_state *_state);
/*************************************************************************
Main unittest subroutine
*************************************************************************/
ae_bool testsafesolve(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t maxmn;
double threshold;
ae_bool rerrors;
ae_bool cerrors;
ae_bool waserrors;
ae_bool isupper;
ae_int_t trans;
ae_bool isunit;
double scalea;
double growth;
ae_int_t i;
ae_int_t j;
ae_int_t n;
ae_int_t j1;
ae_int_t j2;
ae_complex cv;
ae_matrix ca;
ae_matrix cea;
ae_matrix ctmpa;
ae_vector cxs;
ae_vector cxe;
double rv;
ae_matrix ra;
ae_matrix rea;
ae_matrix rtmpa;
ae_vector rxs;
ae_vector rxe;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&ca, 0, sizeof(ca));
memset(&cea, 0, sizeof(cea));
memset(&ctmpa, 0, sizeof(ctmpa));
memset(&cxs, 0, sizeof(cxs));
memset(&cxe, 0, sizeof(cxe));
memset(&ra, 0, sizeof(ra));
memset(&rea, 0, sizeof(rea));
memset(&rtmpa, 0, sizeof(rtmpa));
memset(&rxs, 0, sizeof(rxs));
memset(&rxe, 0, sizeof(rxe));
ae_matrix_init(&ca, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&cea, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&ctmpa, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&cxs, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&cxe, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&ra, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&rea, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&rtmpa, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rxs, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rxe, 0, DT_REAL, _state, ae_true);
maxmn = 30;
threshold = 100000*ae_machineepsilon;
rerrors = ae_false;
cerrors = ae_false;
waserrors = ae_false;
/*
* Different problems: general tests
*/
for(n=1; n<=maxmn; n++)
{
/*
* test complex solver with well-conditioned matrix:
* 1. generate A: fill off-diagonal elements with small values,
* diagonal elements are filled with larger values
* 2. generate 'effective' A
* 3. prepare task (exact X is stored in CXE, right part - in CXS),
* solve and compare CXS and CXE
*/
isupper = ae_fp_greater(ae_randomreal(_state),0.5);
trans = ae_randominteger(3, _state);
isunit = ae_fp_greater(ae_randomreal(_state),0.5);
scalea = ae_randomreal(_state)+0.5;
ae_matrix_set_length(&ca, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( i==j )
{
ca.ptr.pp_complex[i][j].x = (2*ae_randominteger(2, _state)-1)*(5+ae_randomreal(_state));
ca.ptr.pp_complex[i][j].y = (2*ae_randominteger(2, _state)-1)*(5+ae_randomreal(_state));
}
else
{
ca.ptr.pp_complex[i][j].x = 0.2*ae_randomreal(_state)-0.1;
ca.ptr.pp_complex[i][j].y = 0.2*ae_randomreal(_state)-0.1;
}
}
}
testsafesolveunit_cmatrixmakeacopy(&ca, n, n, &ctmpa, _state);
for(i=0; i<=n-1; i++)
{
if( isupper )
{
j1 = 0;
j2 = i-1;
}
else
{
j1 = i+1;
j2 = n-1;
}
for(j=j1; j<=j2; j++)
{
ctmpa.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
if( isunit )
{
ctmpa.ptr.pp_complex[i][i] = ae_complex_from_i(1);
}
}
ae_matrix_set_length(&cea, n, n, _state);
for(i=0; i<=n-1; i++)
{
if( trans==0 )
{
ae_v_cmoved(&cea.ptr.pp_complex[i][0], 1, &ctmpa.ptr.pp_complex[i][0], 1, "N", ae_v_len(0,n-1), scalea);
}
if( trans==1 )
{
ae_v_cmoved(&cea.ptr.pp_complex[0][i], cea.stride, &ctmpa.ptr.pp_complex[i][0], 1, "N", ae_v_len(0,n-1), scalea);
}
if( trans==2 )
{
ae_v_cmoved(&cea.ptr.pp_complex[0][i], cea.stride, &ctmpa.ptr.pp_complex[i][0], 1, "Conj", ae_v_len(0,n-1), scalea);
}
}
ae_vector_set_length(&cxe, n, _state);
for(i=0; i<=n-1; i++)
{
cxe.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1;
cxe.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1;
}
ae_vector_set_length(&cxs, n, _state);
for(i=0; i<=n-1; i++)
{
cv = ae_v_cdotproduct(&cea.ptr.pp_complex[i][0], 1, "N", &cxe.ptr.p_complex[0], 1, "N", ae_v_len(0,n-1));
cxs.ptr.p_complex[i] = cv;
}
if( cmatrixscaledtrsafesolve(&ca, scalea, n, &cxs, isupper, trans, isunit, ae_sqrt(ae_maxrealnumber, _state), _state) )
{
for(i=0; i<=n-1; i++)
{
cerrors = cerrors||ae_fp_greater(ae_c_abs(ae_c_sub(cxs.ptr.p_complex[i],cxe.ptr.p_complex[i]), _state),threshold);
}
}
else
{
cerrors = ae_true;
}
/*
* same with real
*/
isupper = ae_fp_greater(ae_randomreal(_state),0.5);
trans = ae_randominteger(2, _state);
isunit = ae_fp_greater(ae_randomreal(_state),0.5);
scalea = ae_randomreal(_state)+0.5;
ae_matrix_set_length(&ra, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( i==j )
{
ra.ptr.pp_double[i][j] = (2*ae_randominteger(2, _state)-1)*(5+ae_randomreal(_state));
}
else
{
ra.ptr.pp_double[i][j] = 0.2*ae_randomreal(_state)-0.1;
}
}
}
testsafesolveunit_rmatrixmakeacopy(&ra, n, n, &rtmpa, _state);
for(i=0; i<=n-1; i++)
{
if( isupper )
{
j1 = 0;
j2 = i-1;
}
else
{
j1 = i+1;
j2 = n-1;
}
for(j=j1; j<=j2; j++)
{
rtmpa.ptr.pp_double[i][j] = (double)(0);
}
if( isunit )
{
rtmpa.ptr.pp_double[i][i] = (double)(1);
}
}
ae_matrix_set_length(&rea, n, n, _state);
for(i=0; i<=n-1; i++)
{
if( trans==0 )
{
ae_v_moved(&rea.ptr.pp_double[i][0], 1, &rtmpa.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), scalea);
}
if( trans==1 )
{
ae_v_moved(&rea.ptr.pp_double[0][i], rea.stride, &rtmpa.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), scalea);
}
}
ae_vector_set_length(&rxe, n, _state);
for(i=0; i<=n-1; i++)
{
rxe.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
ae_vector_set_length(&rxs, n, _state);
for(i=0; i<=n-1; i++)
{
rv = ae_v_dotproduct(&rea.ptr.pp_double[i][0], 1, &rxe.ptr.p_double[0], 1, ae_v_len(0,n-1));
rxs.ptr.p_double[i] = rv;
}
if( rmatrixscaledtrsafesolve(&ra, scalea, n, &rxs, isupper, trans, isunit, ae_sqrt(ae_maxrealnumber, _state), _state) )
{
for(i=0; i<=n-1; i++)
{
rerrors = rerrors||ae_fp_greater(ae_fabs(rxs.ptr.p_double[i]-rxe.ptr.p_double[i], _state),threshold);
}
}
else
{
rerrors = ae_true;
}
}
/*
* Special test with diagonal ill-conditioned matrix:
* * ability to solve it when resulting growth is less than threshold
* * ability to stop solve when resulting growth is greater than threshold
*
* A = diag(1, 1/growth)
* b = (1, 0.5)
*/
n = 2;
growth = (double)(10);
ae_matrix_set_length(&ca, n, n, _state);
ca.ptr.pp_complex[0][0] = ae_complex_from_i(1);
ca.ptr.pp_complex[0][1] = ae_complex_from_i(0);
ca.ptr.pp_complex[1][0] = ae_complex_from_i(0);
ca.ptr.pp_complex[1][1] = ae_complex_from_d(1/growth);
ae_vector_set_length(&cxs, n, _state);
cxs.ptr.p_complex[0] = ae_complex_from_d(1.0);
cxs.ptr.p_complex[1] = ae_complex_from_d(0.5);
cerrors = cerrors||!cmatrixscaledtrsafesolve(&ca, 1.0, n, &cxs, ae_fp_greater(ae_randomreal(_state),0.5), ae_randominteger(3, _state), ae_false, 1.05*ae_maxreal(ae_c_abs(cxs.ptr.p_complex[1], _state)*growth, 1.0, _state), _state);
cerrors = cerrors||!cmatrixscaledtrsafesolve(&ca, 1.0, n, &cxs, ae_fp_greater(ae_randomreal(_state),0.5), ae_randominteger(3, _state), ae_false, 0.95*ae_maxreal(ae_c_abs(cxs.ptr.p_complex[1], _state)*growth, 1.0, _state), _state);
ae_matrix_set_length(&ra, n, n, _state);
ra.ptr.pp_double[0][0] = (double)(1);
ra.ptr.pp_double[0][1] = (double)(0);
ra.ptr.pp_double[1][0] = (double)(0);
ra.ptr.pp_double[1][1] = 1/growth;
ae_vector_set_length(&rxs, n, _state);
rxs.ptr.p_double[0] = 1.0;
rxs.ptr.p_double[1] = 0.5;
rerrors = rerrors||!rmatrixscaledtrsafesolve(&ra, 1.0, n, &rxs, ae_fp_greater(ae_randomreal(_state),0.5), ae_randominteger(2, _state), ae_false, 1.05*ae_maxreal(ae_fabs(rxs.ptr.p_double[1], _state)*growth, 1.0, _state), _state);
rerrors = rerrors||!rmatrixscaledtrsafesolve(&ra, 1.0, n, &rxs, ae_fp_greater(ae_randomreal(_state),0.5), ae_randominteger(2, _state), ae_false, 0.95*ae_maxreal(ae_fabs(rxs.ptr.p_double[1], _state)*growth, 1.0, _state), _state);
/*
* Special test with diagonal degenerate matrix:
* * ability to solve it when resulting growth is less than threshold
* * ability to stop solve when resulting growth is greater than threshold
*
* A = diag(1, 0)
* b = (1, 0.5)
*/
n = 2;
ae_matrix_set_length(&ca, n, n, _state);
ca.ptr.pp_complex[0][0] = ae_complex_from_i(1);
ca.ptr.pp_complex[0][1] = ae_complex_from_i(0);
ca.ptr.pp_complex[1][0] = ae_complex_from_i(0);
ca.ptr.pp_complex[1][1] = ae_complex_from_i(0);
ae_vector_set_length(&cxs, n, _state);
cxs.ptr.p_complex[0] = ae_complex_from_d(1.0);
cxs.ptr.p_complex[1] = ae_complex_from_d(0.5);
cerrors = cerrors||cmatrixscaledtrsafesolve(&ca, 1.0, n, &cxs, ae_fp_greater(ae_randomreal(_state),0.5), ae_randominteger(3, _state), ae_false, ae_sqrt(ae_maxrealnumber, _state), _state);
ae_matrix_set_length(&ra, n, n, _state);
ra.ptr.pp_double[0][0] = (double)(1);
ra.ptr.pp_double[0][1] = (double)(0);
ra.ptr.pp_double[1][0] = (double)(0);
ra.ptr.pp_double[1][1] = (double)(0);
ae_vector_set_length(&rxs, n, _state);
rxs.ptr.p_double[0] = 1.0;
rxs.ptr.p_double[1] = 0.5;
rerrors = rerrors||rmatrixscaledtrsafesolve(&ra, 1.0, n, &rxs, ae_fp_greater(ae_randomreal(_state),0.5), ae_randominteger(2, _state), ae_false, ae_sqrt(ae_maxrealnumber, _state), _state);
/*
* report
*/
waserrors = rerrors||cerrors;
if( !silent )
{
printf("TESTING SAFE TR SOLVER\n");
printf("REAL: ");
if( !rerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("COMPLEX: ");
if( !cerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Copy
*************************************************************************/
static void testsafesolveunit_rmatrixmakeacopy(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Real */ ae_matrix* b,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_matrix_clear(b);
ae_matrix_set_length(b, m-1+1, n-1+1, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
b->ptr.pp_double[i][j] = a->ptr.pp_double[i][j];
}
}
}
/*************************************************************************
Copy
*************************************************************************/
static void testsafesolveunit_cmatrixmakeacopy(/* Complex */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Complex */ ae_matrix* b,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_matrix_clear(b);
ae_matrix_set_length(b, m-1+1, n-1+1, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
b->ptr.pp_complex[i][j] = a->ptr.pp_complex[i][j];
}
}
}
static double testrcondunit_threshold50 = 0.25;
static double testrcondunit_threshold90 = 0.10;
static void testrcondunit_rmatrixmakeacopy(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Real */ ae_matrix* b,
ae_state *_state);
static void testrcondunit_rmatrixdrophalf(/* Real */ ae_matrix* a,
ae_int_t n,
ae_bool droplower,
ae_state *_state);
static void testrcondunit_cmatrixdrophalf(/* Complex */ ae_matrix* a,
ae_int_t n,
ae_bool droplower,
ae_state *_state);
static void testrcondunit_rmatrixgenzero(/* Real */ ae_matrix* a0,
ae_int_t n,
ae_state *_state);
static ae_bool testrcondunit_rmatrixinvmattr(/* Real */ ae_matrix* a,
ae_int_t n,
ae_bool isupper,
ae_bool isunittriangular,
ae_state *_state);
static ae_bool testrcondunit_rmatrixinvmatlu(/* Real */ ae_matrix* a,
/* Integer */ ae_vector* pivots,
ae_int_t n,
ae_state *_state);
static ae_bool testrcondunit_rmatrixinvmat(/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state);
static void testrcondunit_rmatrixrefrcond(/* Real */ ae_matrix* a,
ae_int_t n,
double* rc1,
double* rcinf,
ae_state *_state);
static void testrcondunit_cmatrixmakeacopy(/* Complex */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Complex */ ae_matrix* b,
ae_state *_state);
static void testrcondunit_cmatrixgenzero(/* Complex */ ae_matrix* a0,
ae_int_t n,
ae_state *_state);
static ae_bool testrcondunit_cmatrixinvmattr(/* Complex */ ae_matrix* a,
ae_int_t n,
ae_bool isupper,
ae_bool isunittriangular,
ae_state *_state);
static ae_bool testrcondunit_cmatrixinvmatlu(/* Complex */ ae_matrix* a,
/* Integer */ ae_vector* pivots,
ae_int_t n,
ae_state *_state);
static ae_bool testrcondunit_cmatrixinvmat(/* Complex */ ae_matrix* a,
ae_int_t n,
ae_state *_state);
static void testrcondunit_cmatrixrefrcond(/* Complex */ ae_matrix* a,
ae_int_t n,
double* rc1,
double* rcinf,
ae_state *_state);
static ae_bool testrcondunit_testrmatrixtrrcond(ae_int_t maxn,
ae_int_t passcount,
ae_state *_state);
static ae_bool testrcondunit_testcmatrixtrrcond(ae_int_t maxn,
ae_int_t passcount,
ae_state *_state);
static ae_bool testrcondunit_testrmatrixrcond(ae_int_t maxn,
ae_int_t passcount,
ae_state *_state);
static ae_bool testrcondunit_testspdmatrixrcond(ae_int_t maxn,
ae_int_t passcount,
ae_state *_state);
static ae_bool testrcondunit_testcmatrixrcond(ae_int_t maxn,
ae_int_t passcount,
ae_state *_state);
static ae_bool testrcondunit_testhpdmatrixrcond(ae_int_t maxn,
ae_int_t passcount,
ae_state *_state);
ae_bool testrcond(ae_bool silent, ae_state *_state)
{
ae_int_t maxn;
ae_int_t passcount;
ae_bool waserrors;
ae_bool rtrerr;
ae_bool ctrerr;
ae_bool rerr;
ae_bool cerr;
ae_bool spderr;
ae_bool hpderr;
ae_bool result;
maxn = 10;
passcount = 100;
/*
* report
*/
rtrerr = !testrcondunit_testrmatrixtrrcond(maxn, passcount, _state);
ctrerr = !testrcondunit_testcmatrixtrrcond(maxn, passcount, _state);
rerr = !testrcondunit_testrmatrixrcond(maxn, passcount, _state);
cerr = !testrcondunit_testcmatrixrcond(maxn, passcount, _state);
spderr = !testrcondunit_testspdmatrixrcond(maxn, passcount, _state);
hpderr = !testrcondunit_testhpdmatrixrcond(maxn, passcount, _state);
waserrors = ((((rtrerr||ctrerr)||rerr)||cerr)||spderr)||hpderr;
if( !silent )
{
printf("TESTING RCOND\n");
printf("REAL TRIANGULAR: ");
if( !rtrerr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("COMPLEX TRIANGULAR: ");
if( !ctrerr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("REAL: ");
if( !rerr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("SPD: ");
if( !spderr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("HPD: ");
if( !hpderr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("COMPLEX: ");
if( !cerr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
return result;
}
/*************************************************************************
Copy
*************************************************************************/
static void testrcondunit_rmatrixmakeacopy(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Real */ ae_matrix* b,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_matrix_clear(b);
ae_matrix_set_length(b, m-1+1, n-1+1, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
b->ptr.pp_double[i][j] = a->ptr.pp_double[i][j];
}
}
}
/*************************************************************************
Drops upper or lower half of the matrix - fills it by special pattern
which may be used later to ensure that this part wasn't changed
*************************************************************************/
static void testrcondunit_rmatrixdrophalf(/* Real */ ae_matrix* a,
ae_int_t n,
ae_bool droplower,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (droplower&&i>j)||(!droplower&&iptr.pp_double[i][j] = (double)(1+2*i+3*j);
}
}
}
}
/*************************************************************************
Drops upper or lower half of the matrix - fills it by special pattern
which may be used later to ensure that this part wasn't changed
*************************************************************************/
static void testrcondunit_cmatrixdrophalf(/* Complex */ ae_matrix* a,
ae_int_t n,
ae_bool droplower,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (droplower&&i>j)||(!droplower&&iptr.pp_complex[i][j] = ae_complex_from_i(1+2*i+3*j);
}
}
}
}
/*************************************************************************
Generate matrix with given condition number C (2-norm)
*************************************************************************/
static void testrcondunit_rmatrixgenzero(/* Real */ ae_matrix* a0,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_matrix_set_length(a0, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a0->ptr.pp_double[i][j] = (double)(0);
}
}
}
/*************************************************************************
triangular inverse
*************************************************************************/
static ae_bool testrcondunit_rmatrixinvmattr(/* Real */ ae_matrix* a,
ae_int_t n,
ae_bool isupper,
ae_bool isunittriangular,
ae_state *_state)
{
ae_frame _frame_block;
ae_bool nounit;
ae_int_t i;
ae_int_t j;
double v;
double ajj;
ae_vector t;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&t, 0, sizeof(t));
ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
result = ae_true;
ae_vector_set_length(&t, n-1+1, _state);
/*
* Test the input parameters.
*/
nounit = !isunittriangular;
if( isupper )
{
/*
* Compute inverse of upper triangular matrix.
*/
for(j=0; j<=n-1; j++)
{
if( nounit )
{
if( ae_fp_eq(a->ptr.pp_double[j][j],(double)(0)) )
{
result = ae_false;
ae_frame_leave(_state);
return result;
}
a->ptr.pp_double[j][j] = 1/a->ptr.pp_double[j][j];
ajj = -a->ptr.pp_double[j][j];
}
else
{
ajj = (double)(-1);
}
/*
* Compute elements 1:j-1 of j-th column.
*/
if( j>0 )
{
ae_v_move(&t.ptr.p_double[0], 1, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,j-1));
for(i=0; i<=j-1; i++)
{
if( iptr.pp_double[i][i+1], 1, &t.ptr.p_double[i+1], 1, ae_v_len(i+1,j-1));
}
else
{
v = (double)(0);
}
if( nounit )
{
a->ptr.pp_double[i][j] = v+a->ptr.pp_double[i][i]*t.ptr.p_double[i];
}
else
{
a->ptr.pp_double[i][j] = v+t.ptr.p_double[i];
}
}
ae_v_muld(&a->ptr.pp_double[0][j], a->stride, ae_v_len(0,j-1), ajj);
}
}
}
else
{
/*
* Compute inverse of lower triangular matrix.
*/
for(j=n-1; j>=0; j--)
{
if( nounit )
{
if( ae_fp_eq(a->ptr.pp_double[j][j],(double)(0)) )
{
result = ae_false;
ae_frame_leave(_state);
return result;
}
a->ptr.pp_double[j][j] = 1/a->ptr.pp_double[j][j];
ajj = -a->ptr.pp_double[j][j];
}
else
{
ajj = (double)(-1);
}
if( jptr.pp_double[j+1][j], a->stride, ae_v_len(j+1,n-1));
for(i=j+1; i<=n-1; i++)
{
if( i>j+1 )
{
v = ae_v_dotproduct(&a->ptr.pp_double[i][j+1], 1, &t.ptr.p_double[j+1], 1, ae_v_len(j+1,i-1));
}
else
{
v = (double)(0);
}
if( nounit )
{
a->ptr.pp_double[i][j] = v+a->ptr.pp_double[i][i]*t.ptr.p_double[i];
}
else
{
a->ptr.pp_double[i][j] = v+t.ptr.p_double[i];
}
}
ae_v_muld(&a->ptr.pp_double[j+1][j], a->stride, ae_v_len(j+1,n-1), ajj);
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
LU inverse
*************************************************************************/
static ae_bool testrcondunit_rmatrixinvmatlu(/* Real */ ae_matrix* a,
/* Integer */ ae_vector* pivots,
ae_int_t n,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector work;
ae_int_t i;
ae_int_t j;
ae_int_t jp;
double v;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&work, 0, sizeof(work));
ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
result = ae_true;
/*
* Quick return if possible
*/
if( n==0 )
{
ae_frame_leave(_state);
return result;
}
ae_vector_set_length(&work, n-1+1, _state);
/*
* Form inv(U)
*/
if( !testrcondunit_rmatrixinvmattr(a, n, ae_true, ae_false, _state) )
{
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*
* Solve the equation inv(A)*L = inv(U) for inv(A).
*/
for(j=n-1; j>=0; j--)
{
/*
* Copy current column of L to WORK and replace with zeros.
*/
for(i=j+1; i<=n-1; i++)
{
work.ptr.p_double[i] = a->ptr.pp_double[i][j];
a->ptr.pp_double[i][j] = (double)(0);
}
/*
* Compute current column of inv(A).
*/
if( jptr.pp_double[i][j+1], 1, &work.ptr.p_double[j+1], 1, ae_v_len(j+1,n-1));
a->ptr.pp_double[i][j] = a->ptr.pp_double[i][j]-v;
}
}
}
/*
* Apply column interchanges.
*/
for(j=n-2; j>=0; j--)
{
jp = pivots->ptr.p_int[j];
if( jp!=j )
{
ae_v_move(&work.ptr.p_double[0], 1, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,n-1));
ae_v_move(&a->ptr.pp_double[0][j], a->stride, &a->ptr.pp_double[0][jp], a->stride, ae_v_len(0,n-1));
ae_v_move(&a->ptr.pp_double[0][jp], a->stride, &work.ptr.p_double[0], 1, ae_v_len(0,n-1));
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Matrix inverse
*************************************************************************/
static ae_bool testrcondunit_rmatrixinvmat(/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector pivots;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&pivots, 0, sizeof(pivots));
ae_vector_init(&pivots, 0, DT_INT, _state, ae_true);
rmatrixlu(a, n, n, &pivots, _state);
result = testrcondunit_rmatrixinvmatlu(a, &pivots, n, _state);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
reference RCond
*************************************************************************/
static void testrcondunit_rmatrixrefrcond(/* Real */ ae_matrix* a,
ae_int_t n,
double* rc1,
double* rcinf,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix inva;
double nrm1a;
double nrminfa;
double nrm1inva;
double nrminfinva;
double v;
ae_int_t k;
ae_int_t i;
ae_frame_make(_state, &_frame_block);
memset(&inva, 0, sizeof(inva));
*rc1 = 0;
*rcinf = 0;
ae_matrix_init(&inva, 0, 0, DT_REAL, _state, ae_true);
/*
* inv A
*/
testrcondunit_rmatrixmakeacopy(a, n, n, &inva, _state);
if( !testrcondunit_rmatrixinvmat(&inva, n, _state) )
{
*rc1 = (double)(0);
*rcinf = (double)(0);
ae_frame_leave(_state);
return;
}
/*
* norm A
*/
nrm1a = (double)(0);
nrminfa = (double)(0);
for(k=0; k<=n-1; k++)
{
v = (double)(0);
for(i=0; i<=n-1; i++)
{
v = v+ae_fabs(a->ptr.pp_double[i][k], _state);
}
nrm1a = ae_maxreal(nrm1a, v, _state);
v = (double)(0);
for(i=0; i<=n-1; i++)
{
v = v+ae_fabs(a->ptr.pp_double[k][i], _state);
}
nrminfa = ae_maxreal(nrminfa, v, _state);
}
/*
* norm inv A
*/
nrm1inva = (double)(0);
nrminfinva = (double)(0);
for(k=0; k<=n-1; k++)
{
v = (double)(0);
for(i=0; i<=n-1; i++)
{
v = v+ae_fabs(inva.ptr.pp_double[i][k], _state);
}
nrm1inva = ae_maxreal(nrm1inva, v, _state);
v = (double)(0);
for(i=0; i<=n-1; i++)
{
v = v+ae_fabs(inva.ptr.pp_double[k][i], _state);
}
nrminfinva = ae_maxreal(nrminfinva, v, _state);
}
/*
* result
*/
*rc1 = nrm1inva*nrm1a;
*rcinf = nrminfinva*nrminfa;
ae_frame_leave(_state);
}
/*************************************************************************
Copy
*************************************************************************/
static void testrcondunit_cmatrixmakeacopy(/* Complex */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Complex */ ae_matrix* b,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_matrix_clear(b);
ae_matrix_set_length(b, m-1+1, n-1+1, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
b->ptr.pp_complex[i][j] = a->ptr.pp_complex[i][j];
}
}
}
/*************************************************************************
Generate matrix with given condition number C (2-norm)
*************************************************************************/
static void testrcondunit_cmatrixgenzero(/* Complex */ ae_matrix* a0,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_matrix_set_length(a0, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a0->ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
}
/*************************************************************************
triangular inverse
*************************************************************************/
static ae_bool testrcondunit_cmatrixinvmattr(/* Complex */ ae_matrix* a,
ae_int_t n,
ae_bool isupper,
ae_bool isunittriangular,
ae_state *_state)
{
ae_frame _frame_block;
ae_bool nounit;
ae_int_t i;
ae_int_t j;
ae_complex v;
ae_complex ajj;
ae_vector t;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&t, 0, sizeof(t));
ae_vector_init(&t, 0, DT_COMPLEX, _state, ae_true);
result = ae_true;
ae_vector_set_length(&t, n-1+1, _state);
/*
* Test the input parameters.
*/
nounit = !isunittriangular;
if( isupper )
{
/*
* Compute inverse of upper triangular matrix.
*/
for(j=0; j<=n-1; j++)
{
if( nounit )
{
if( ae_c_eq_d(a->ptr.pp_complex[j][j],(double)(0)) )
{
result = ae_false;
ae_frame_leave(_state);
return result;
}
a->ptr.pp_complex[j][j] = ae_c_d_div(1,a->ptr.pp_complex[j][j]);
ajj = ae_c_neg(a->ptr.pp_complex[j][j]);
}
else
{
ajj = ae_complex_from_i(-1);
}
/*
* Compute elements 1:j-1 of j-th column.
*/
if( j>0 )
{
ae_v_cmove(&t.ptr.p_complex[0], 1, &a->ptr.pp_complex[0][j], a->stride, "N", ae_v_len(0,j-1));
for(i=0; i<=j-1; i++)
{
if( iptr.pp_complex[i][i+1], 1, "N", &t.ptr.p_complex[i+1], 1, "N", ae_v_len(i+1,j-1));
}
else
{
v = ae_complex_from_i(0);
}
if( nounit )
{
a->ptr.pp_complex[i][j] = ae_c_add(v,ae_c_mul(a->ptr.pp_complex[i][i],t.ptr.p_complex[i]));
}
else
{
a->ptr.pp_complex[i][j] = ae_c_add(v,t.ptr.p_complex[i]);
}
}
ae_v_cmulc(&a->ptr.pp_complex[0][j], a->stride, ae_v_len(0,j-1), ajj);
}
}
}
else
{
/*
* Compute inverse of lower triangular matrix.
*/
for(j=n-1; j>=0; j--)
{
if( nounit )
{
if( ae_c_eq_d(a->ptr.pp_complex[j][j],(double)(0)) )
{
result = ae_false;
ae_frame_leave(_state);
return result;
}
a->ptr.pp_complex[j][j] = ae_c_d_div(1,a->ptr.pp_complex[j][j]);
ajj = ae_c_neg(a->ptr.pp_complex[j][j]);
}
else
{
ajj = ae_complex_from_i(-1);
}
if( jptr.pp_complex[j+1][j], a->stride, "N", ae_v_len(j+1,n-1));
for(i=j+1; i<=n-1; i++)
{
if( i>j+1 )
{
v = ae_v_cdotproduct(&a->ptr.pp_complex[i][j+1], 1, "N", &t.ptr.p_complex[j+1], 1, "N", ae_v_len(j+1,i-1));
}
else
{
v = ae_complex_from_i(0);
}
if( nounit )
{
a->ptr.pp_complex[i][j] = ae_c_add(v,ae_c_mul(a->ptr.pp_complex[i][i],t.ptr.p_complex[i]));
}
else
{
a->ptr.pp_complex[i][j] = ae_c_add(v,t.ptr.p_complex[i]);
}
}
ae_v_cmulc(&a->ptr.pp_complex[j+1][j], a->stride, ae_v_len(j+1,n-1), ajj);
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
LU inverse
*************************************************************************/
static ae_bool testrcondunit_cmatrixinvmatlu(/* Complex */ ae_matrix* a,
/* Integer */ ae_vector* pivots,
ae_int_t n,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector work;
ae_int_t i;
ae_int_t j;
ae_int_t jp;
ae_complex v;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&work, 0, sizeof(work));
ae_vector_init(&work, 0, DT_COMPLEX, _state, ae_true);
result = ae_true;
/*
* Quick return if possible
*/
if( n==0 )
{
ae_frame_leave(_state);
return result;
}
ae_vector_set_length(&work, n-1+1, _state);
/*
* Form inv(U)
*/
if( !testrcondunit_cmatrixinvmattr(a, n, ae_true, ae_false, _state) )
{
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*
* Solve the equation inv(A)*L = inv(U) for inv(A).
*/
for(j=n-1; j>=0; j--)
{
/*
* Copy current column of L to WORK and replace with zeros.
*/
for(i=j+1; i<=n-1; i++)
{
work.ptr.p_complex[i] = a->ptr.pp_complex[i][j];
a->ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
/*
* Compute current column of inv(A).
*/
if( jptr.pp_complex[i][j+1], 1, "N", &work.ptr.p_complex[j+1], 1, "N", ae_v_len(j+1,n-1));
a->ptr.pp_complex[i][j] = ae_c_sub(a->ptr.pp_complex[i][j],v);
}
}
}
/*
* Apply column interchanges.
*/
for(j=n-2; j>=0; j--)
{
jp = pivots->ptr.p_int[j];
if( jp!=j )
{
ae_v_cmove(&work.ptr.p_complex[0], 1, &a->ptr.pp_complex[0][j], a->stride, "N", ae_v_len(0,n-1));
ae_v_cmove(&a->ptr.pp_complex[0][j], a->stride, &a->ptr.pp_complex[0][jp], a->stride, "N", ae_v_len(0,n-1));
ae_v_cmove(&a->ptr.pp_complex[0][jp], a->stride, &work.ptr.p_complex[0], 1, "N", ae_v_len(0,n-1));
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Matrix inverse
*************************************************************************/
static ae_bool testrcondunit_cmatrixinvmat(/* Complex */ ae_matrix* a,
ae_int_t n,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector pivots;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&pivots, 0, sizeof(pivots));
ae_vector_init(&pivots, 0, DT_INT, _state, ae_true);
cmatrixlu(a, n, n, &pivots, _state);
result = testrcondunit_cmatrixinvmatlu(a, &pivots, n, _state);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
reference RCond
*************************************************************************/
static void testrcondunit_cmatrixrefrcond(/* Complex */ ae_matrix* a,
ae_int_t n,
double* rc1,
double* rcinf,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix inva;
double nrm1a;
double nrminfa;
double nrm1inva;
double nrminfinva;
double v;
ae_int_t k;
ae_int_t i;
ae_frame_make(_state, &_frame_block);
memset(&inva, 0, sizeof(inva));
*rc1 = 0;
*rcinf = 0;
ae_matrix_init(&inva, 0, 0, DT_COMPLEX, _state, ae_true);
/*
* inv A
*/
testrcondunit_cmatrixmakeacopy(a, n, n, &inva, _state);
if( !testrcondunit_cmatrixinvmat(&inva, n, _state) )
{
*rc1 = (double)(0);
*rcinf = (double)(0);
ae_frame_leave(_state);
return;
}
/*
* norm A
*/
nrm1a = (double)(0);
nrminfa = (double)(0);
for(k=0; k<=n-1; k++)
{
v = (double)(0);
for(i=0; i<=n-1; i++)
{
v = v+ae_c_abs(a->ptr.pp_complex[i][k], _state);
}
nrm1a = ae_maxreal(nrm1a, v, _state);
v = (double)(0);
for(i=0; i<=n-1; i++)
{
v = v+ae_c_abs(a->ptr.pp_complex[k][i], _state);
}
nrminfa = ae_maxreal(nrminfa, v, _state);
}
/*
* norm inv A
*/
nrm1inva = (double)(0);
nrminfinva = (double)(0);
for(k=0; k<=n-1; k++)
{
v = (double)(0);
for(i=0; i<=n-1; i++)
{
v = v+ae_c_abs(inva.ptr.pp_complex[i][k], _state);
}
nrm1inva = ae_maxreal(nrm1inva, v, _state);
v = (double)(0);
for(i=0; i<=n-1; i++)
{
v = v+ae_c_abs(inva.ptr.pp_complex[k][i], _state);
}
nrminfinva = ae_maxreal(nrminfinva, v, _state);
}
/*
* result
*/
*rc1 = nrm1inva*nrm1a;
*rcinf = nrminfinva*nrminfa;
ae_frame_leave(_state);
}
/*************************************************************************
Returns True for successful test, False - for failed test
*************************************************************************/
static ae_bool testrcondunit_testrmatrixtrrcond(ae_int_t maxn,
ae_int_t passcount,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix ea;
ae_vector p;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_int_t j1;
ae_int_t j2;
ae_int_t pass;
ae_bool err50;
ae_bool err90;
ae_bool errspec;
ae_bool errless;
double erc1;
double ercinf;
ae_vector q50;
ae_vector q90;
double v;
ae_bool isupper;
ae_bool isunit;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&ea, 0, sizeof(ea));
memset(&p, 0, sizeof(p));
memset(&q50, 0, sizeof(q50));
memset(&q90, 0, sizeof(q90));
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ea, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&p, 0, DT_INT, _state, ae_true);
ae_vector_init(&q50, 0, DT_REAL, _state, ae_true);
ae_vector_init(&q90, 0, DT_REAL, _state, ae_true);
err50 = ae_false;
err90 = ae_false;
errless = ae_false;
errspec = ae_false;
ae_vector_set_length(&q50, 2, _state);
ae_vector_set_length(&q90, 2, _state);
for(n=1; n<=maxn; n++)
{
/*
* special test for zero matrix
*/
testrcondunit_rmatrixgenzero(&a, n, _state);
errspec = errspec||ae_fp_neq(rmatrixtrrcond1(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0));
errspec = errspec||ae_fp_neq(rmatrixtrrcondinf(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0));
/*
* general test
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=1; i++)
{
q50.ptr.p_double[i] = (double)(0);
q90.ptr.p_double[i] = (double)(0);
}
for(pass=1; pass<=passcount; pass++)
{
isupper = ae_fp_greater(ae_randomreal(_state),0.5);
isunit = ae_fp_greater(ae_randomreal(_state),0.5);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = ae_randomreal(_state)-0.5;
}
}
for(i=0; i<=n-1; i++)
{
a.ptr.pp_double[i][i] = 1+ae_randomreal(_state);
}
testrcondunit_rmatrixmakeacopy(&a, n, n, &ea, _state);
for(i=0; i<=n-1; i++)
{
if( isupper )
{
j1 = 0;
j2 = i-1;
}
else
{
j1 = i+1;
j2 = n-1;
}
for(j=j1; j<=j2; j++)
{
ea.ptr.pp_double[i][j] = (double)(0);
}
if( isunit )
{
ea.ptr.pp_double[i][i] = (double)(1);
}
}
testrcondunit_rmatrixrefrcond(&ea, n, &erc1, &ercinf, _state);
/*
* 1-norm
*/
v = 1/rmatrixtrrcond1(&a, n, isupper, isunit, _state);
if( ae_fp_greater_eq(v,testrcondunit_threshold50*erc1) )
{
q50.ptr.p_double[0] = q50.ptr.p_double[0]+(double)1/(double)passcount;
}
if( ae_fp_greater_eq(v,testrcondunit_threshold90*erc1) )
{
q90.ptr.p_double[0] = q90.ptr.p_double[0]+(double)1/(double)passcount;
}
errless = errless||ae_fp_greater(v,erc1*1.001);
/*
* Inf-norm
*/
v = 1/rmatrixtrrcondinf(&a, n, isupper, isunit, _state);
if( ae_fp_greater_eq(v,testrcondunit_threshold50*ercinf) )
{
q50.ptr.p_double[1] = q50.ptr.p_double[1]+(double)1/(double)passcount;
}
if( ae_fp_greater_eq(v,testrcondunit_threshold90*ercinf) )
{
q90.ptr.p_double[1] = q90.ptr.p_double[1]+(double)1/(double)passcount;
}
errless = errless||ae_fp_greater(v,ercinf*1.001);
}
for(i=0; i<=1; i++)
{
err50 = err50||ae_fp_less(q50.ptr.p_double[i],0.50);
err90 = err90||ae_fp_less(q90.ptr.p_double[i],0.90);
}
/*
* degenerate matrix test
*/
if( n>=3 )
{
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
a.ptr.pp_double[0][0] = (double)(1);
a.ptr.pp_double[n-1][n-1] = (double)(1);
errspec = errspec||ae_fp_neq(rmatrixtrrcond1(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0));
errspec = errspec||ae_fp_neq(rmatrixtrrcondinf(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0));
}
/*
* near-degenerate matrix test
*/
if( n>=2 )
{
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
for(i=0; i<=n-1; i++)
{
a.ptr.pp_double[i][i] = (double)(1);
}
i = ae_randominteger(n, _state);
a.ptr.pp_double[i][i] = 0.1*ae_maxrealnumber;
errspec = errspec||ae_fp_neq(rmatrixtrrcond1(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0));
errspec = errspec||ae_fp_neq(rmatrixtrrcondinf(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0));
}
}
/*
* report
*/
result = !(((err50||err90)||errless)||errspec);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Returns True for successful test, False - for failed test
*************************************************************************/
static ae_bool testrcondunit_testcmatrixtrrcond(ae_int_t maxn,
ae_int_t passcount,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix ea;
ae_vector p;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_int_t j1;
ae_int_t j2;
ae_int_t pass;
ae_bool err50;
ae_bool err90;
ae_bool errspec;
ae_bool errless;
double erc1;
double ercinf;
ae_vector q50;
ae_vector q90;
double v;
ae_bool isupper;
ae_bool isunit;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&ea, 0, sizeof(ea));
memset(&p, 0, sizeof(p));
memset(&q50, 0, sizeof(q50));
memset(&q90, 0, sizeof(q90));
ae_matrix_init(&a, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&ea, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&p, 0, DT_INT, _state, ae_true);
ae_vector_init(&q50, 0, DT_REAL, _state, ae_true);
ae_vector_init(&q90, 0, DT_REAL, _state, ae_true);
err50 = ae_false;
err90 = ae_false;
errless = ae_false;
errspec = ae_false;
ae_vector_set_length(&q50, 2, _state);
ae_vector_set_length(&q90, 2, _state);
for(n=1; n<=maxn; n++)
{
/*
* special test for zero matrix
*/
testrcondunit_cmatrixgenzero(&a, n, _state);
errspec = errspec||ae_fp_neq(cmatrixtrrcond1(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0));
errspec = errspec||ae_fp_neq(cmatrixtrrcondinf(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0));
/*
* general test
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=1; i++)
{
q50.ptr.p_double[i] = (double)(0);
q90.ptr.p_double[i] = (double)(0);
}
for(pass=1; pass<=passcount; pass++)
{
isupper = ae_fp_greater(ae_randomreal(_state),0.5);
isunit = ae_fp_greater(ae_randomreal(_state),0.5);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j].x = ae_randomreal(_state)-0.5;
a.ptr.pp_complex[i][j].y = ae_randomreal(_state)-0.5;
}
}
for(i=0; i<=n-1; i++)
{
a.ptr.pp_complex[i][i].x = 1+ae_randomreal(_state);
a.ptr.pp_complex[i][i].y = 1+ae_randomreal(_state);
}
testrcondunit_cmatrixmakeacopy(&a, n, n, &ea, _state);
for(i=0; i<=n-1; i++)
{
if( isupper )
{
j1 = 0;
j2 = i-1;
}
else
{
j1 = i+1;
j2 = n-1;
}
for(j=j1; j<=j2; j++)
{
ea.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
if( isunit )
{
ea.ptr.pp_complex[i][i] = ae_complex_from_i(1);
}
}
testrcondunit_cmatrixrefrcond(&ea, n, &erc1, &ercinf, _state);
/*
* 1-norm
*/
v = 1/cmatrixtrrcond1(&a, n, isupper, isunit, _state);
if( ae_fp_greater_eq(v,testrcondunit_threshold50*erc1) )
{
q50.ptr.p_double[0] = q50.ptr.p_double[0]+(double)1/(double)passcount;
}
if( ae_fp_greater_eq(v,testrcondunit_threshold90*erc1) )
{
q90.ptr.p_double[0] = q90.ptr.p_double[0]+(double)1/(double)passcount;
}
errless = errless||ae_fp_greater(v,erc1*1.001);
/*
* Inf-norm
*/
v = 1/cmatrixtrrcondinf(&a, n, isupper, isunit, _state);
if( ae_fp_greater_eq(v,testrcondunit_threshold50*ercinf) )
{
q50.ptr.p_double[1] = q50.ptr.p_double[1]+(double)1/(double)passcount;
}
if( ae_fp_greater_eq(v,testrcondunit_threshold90*ercinf) )
{
q90.ptr.p_double[1] = q90.ptr.p_double[1]+(double)1/(double)passcount;
}
errless = errless||ae_fp_greater(v,ercinf*1.001);
}
for(i=0; i<=1; i++)
{
err50 = err50||ae_fp_less(q50.ptr.p_double[i],0.50);
err90 = err90||ae_fp_less(q90.ptr.p_double[i],0.90);
}
/*
* degenerate matrix test
*/
if( n>=3 )
{
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j] = ae_complex_from_d(0.0);
}
}
a.ptr.pp_complex[0][0] = ae_complex_from_i(1);
a.ptr.pp_complex[n-1][n-1] = ae_complex_from_i(1);
errspec = errspec||ae_fp_neq(cmatrixtrrcond1(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0));
errspec = errspec||ae_fp_neq(cmatrixtrrcondinf(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0));
}
/*
* near-degenerate matrix test
*/
if( n>=2 )
{
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j] = ae_complex_from_d(0.0);
}
}
for(i=0; i<=n-1; i++)
{
a.ptr.pp_complex[i][i] = ae_complex_from_i(1);
}
i = ae_randominteger(n, _state);
a.ptr.pp_complex[i][i] = ae_complex_from_d(0.1*ae_maxrealnumber);
errspec = errspec||ae_fp_neq(cmatrixtrrcond1(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0));
errspec = errspec||ae_fp_neq(cmatrixtrrcondinf(&a, n, ae_fp_greater(ae_randomreal(_state),0.5), ae_false, _state),(double)(0));
}
}
/*
* report
*/
result = !(((err50||err90)||errless)||errspec);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Returns True for successful test, False - for failed test
*************************************************************************/
static ae_bool testrcondunit_testrmatrixrcond(ae_int_t maxn,
ae_int_t passcount,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix lua;
ae_vector p;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_int_t pass;
ae_bool err50;
ae_bool err90;
ae_bool errspec;
ae_bool errless;
double erc1;
double ercinf;
ae_vector q50;
ae_vector q90;
double v;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&lua, 0, sizeof(lua));
memset(&p, 0, sizeof(p));
memset(&q50, 0, sizeof(q50));
memset(&q90, 0, sizeof(q90));
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&lua, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&p, 0, DT_INT, _state, ae_true);
ae_vector_init(&q50, 0, DT_REAL, _state, ae_true);
ae_vector_init(&q90, 0, DT_REAL, _state, ae_true);
err50 = ae_false;
err90 = ae_false;
errless = ae_false;
errspec = ae_false;
ae_vector_set_length(&q50, 3+1, _state);
ae_vector_set_length(&q90, 3+1, _state);
for(n=1; n<=maxn; n++)
{
/*
* special test for zero matrix
*/
testrcondunit_rmatrixgenzero(&a, n, _state);
testrcondunit_rmatrixmakeacopy(&a, n, n, &lua, _state);
rmatrixlu(&lua, n, n, &p, _state);
errspec = errspec||ae_fp_neq(rmatrixrcond1(&a, n, _state),(double)(0));
errspec = errspec||ae_fp_neq(rmatrixrcondinf(&a, n, _state),(double)(0));
errspec = errspec||ae_fp_neq(rmatrixlurcond1(&lua, n, _state),(double)(0));
errspec = errspec||ae_fp_neq(rmatrixlurcondinf(&lua, n, _state),(double)(0));
/*
* general test
*/
ae_matrix_set_length(&a, n-1+1, n-1+1, _state);
for(i=0; i<=3; i++)
{
q50.ptr.p_double[i] = (double)(0);
q90.ptr.p_double[i] = (double)(0);
}
for(pass=1; pass<=passcount; pass++)
{
rmatrixrndcond(n, ae_exp(ae_randomreal(_state)*ae_log((double)(1000), _state), _state), &a, _state);
testrcondunit_rmatrixmakeacopy(&a, n, n, &lua, _state);
rmatrixlu(&lua, n, n, &p, _state);
testrcondunit_rmatrixrefrcond(&a, n, &erc1, &ercinf, _state);
/*
* 1-norm, normal
*/
v = 1/rmatrixrcond1(&a, n, _state);
if( ae_fp_greater_eq(v,testrcondunit_threshold50*erc1) )
{
q50.ptr.p_double[0] = q50.ptr.p_double[0]+(double)1/(double)passcount;
}
if( ae_fp_greater_eq(v,testrcondunit_threshold90*erc1) )
{
q90.ptr.p_double[0] = q90.ptr.p_double[0]+(double)1/(double)passcount;
}
errless = errless||ae_fp_greater(v,erc1*1.001);
/*
* 1-norm, LU
*/
v = 1/rmatrixlurcond1(&lua, n, _state);
if( ae_fp_greater_eq(v,testrcondunit_threshold50*erc1) )
{
q50.ptr.p_double[1] = q50.ptr.p_double[1]+(double)1/(double)passcount;
}
if( ae_fp_greater_eq(v,testrcondunit_threshold90*erc1) )
{
q90.ptr.p_double[1] = q90.ptr.p_double[1]+(double)1/(double)passcount;
}
errless = errless||ae_fp_greater(v,erc1*1.001);
/*
* Inf-norm, normal
*/
v = 1/rmatrixrcondinf(&a, n, _state);
if( ae_fp_greater_eq(v,testrcondunit_threshold50*ercinf) )
{
q50.ptr.p_double[2] = q50.ptr.p_double[2]+(double)1/(double)passcount;
}
if( ae_fp_greater_eq(v,testrcondunit_threshold90*ercinf) )
{
q90.ptr.p_double[2] = q90.ptr.p_double[2]+(double)1/(double)passcount;
}
errless = errless||ae_fp_greater(v,ercinf*1.001);
/*
* Inf-norm, LU
*/
v = 1/rmatrixlurcondinf(&lua, n, _state);
if( ae_fp_greater_eq(v,testrcondunit_threshold50*ercinf) )
{
q50.ptr.p_double[3] = q50.ptr.p_double[3]+(double)1/(double)passcount;
}
if( ae_fp_greater_eq(v,testrcondunit_threshold90*ercinf) )
{
q90.ptr.p_double[3] = q90.ptr.p_double[3]+(double)1/(double)passcount;
}
errless = errless||ae_fp_greater(v,ercinf*1.001);
}
for(i=0; i<=3; i++)
{
err50 = err50||ae_fp_less(q50.ptr.p_double[i],0.50);
err90 = err90||ae_fp_less(q90.ptr.p_double[i],0.90);
}
/*
* degenerate matrix test
*/
if( n>=3 )
{
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
a.ptr.pp_double[0][0] = (double)(1);
a.ptr.pp_double[n-1][n-1] = (double)(1);
errspec = errspec||ae_fp_neq(rmatrixrcond1(&a, n, _state),(double)(0));
errspec = errspec||ae_fp_neq(rmatrixrcondinf(&a, n, _state),(double)(0));
errspec = errspec||ae_fp_neq(rmatrixlurcond1(&a, n, _state),(double)(0));
errspec = errspec||ae_fp_neq(rmatrixlurcondinf(&a, n, _state),(double)(0));
}
/*
* near-degenerate matrix test
*/
if( n>=2 )
{
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
for(i=0; i<=n-1; i++)
{
a.ptr.pp_double[i][i] = (double)(1);
}
i = ae_randominteger(n, _state);
a.ptr.pp_double[i][i] = 0.1*ae_maxrealnumber;
errspec = errspec||ae_fp_neq(rmatrixrcond1(&a, n, _state),(double)(0));
errspec = errspec||ae_fp_neq(rmatrixrcondinf(&a, n, _state),(double)(0));
errspec = errspec||ae_fp_neq(rmatrixlurcond1(&a, n, _state),(double)(0));
errspec = errspec||ae_fp_neq(rmatrixlurcondinf(&a, n, _state),(double)(0));
}
}
/*
* report
*/
result = !(((err50||err90)||errless)||errspec);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Returns True for successful test, False - for failed test
*************************************************************************/
static ae_bool testrcondunit_testspdmatrixrcond(ae_int_t maxn,
ae_int_t passcount,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix cha;
ae_vector p;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_int_t pass;
ae_bool err50;
ae_bool err90;
ae_bool errspec;
ae_bool errless;
ae_bool isupper;
double erc1;
double ercinf;
ae_vector q50;
ae_vector q90;
double v;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&cha, 0, sizeof(cha));
memset(&p, 0, sizeof(p));
memset(&q50, 0, sizeof(q50));
memset(&q90, 0, sizeof(q90));
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&cha, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&p, 0, DT_INT, _state, ae_true);
ae_vector_init(&q50, 0, DT_REAL, _state, ae_true);
ae_vector_init(&q90, 0, DT_REAL, _state, ae_true);
err50 = ae_false;
err90 = ae_false;
errless = ae_false;
errspec = ae_false;
ae_vector_set_length(&q50, 2, _state);
ae_vector_set_length(&q90, 2, _state);
for(n=1; n<=maxn; n++)
{
isupper = ae_fp_greater(ae_randomreal(_state),0.5);
/*
* general test
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=1; i++)
{
q50.ptr.p_double[i] = (double)(0);
q90.ptr.p_double[i] = (double)(0);
}
for(pass=1; pass<=passcount; pass++)
{
spdmatrixrndcond(n, ae_exp(ae_randomreal(_state)*ae_log((double)(1000), _state), _state), &a, _state);
testrcondunit_rmatrixrefrcond(&a, n, &erc1, &ercinf, _state);
testrcondunit_rmatrixdrophalf(&a, n, isupper, _state);
testrcondunit_rmatrixmakeacopy(&a, n, n, &cha, _state);
spdmatrixcholesky(&cha, n, isupper, _state);
/*
* normal
*/
v = 1/spdmatrixrcond(&a, n, isupper, _state);
if( ae_fp_greater_eq(v,testrcondunit_threshold50*erc1) )
{
q50.ptr.p_double[0] = q50.ptr.p_double[0]+(double)1/(double)passcount;
}
if( ae_fp_greater_eq(v,testrcondunit_threshold90*erc1) )
{
q90.ptr.p_double[0] = q90.ptr.p_double[0]+(double)1/(double)passcount;
}
errless = errless||ae_fp_greater(v,erc1*1.001);
/*
* Cholesky
*/
v = 1/spdmatrixcholeskyrcond(&cha, n, isupper, _state);
if( ae_fp_greater_eq(v,testrcondunit_threshold50*erc1) )
{
q50.ptr.p_double[1] = q50.ptr.p_double[1]+(double)1/(double)passcount;
}
if( ae_fp_greater_eq(v,testrcondunit_threshold90*erc1) )
{
q90.ptr.p_double[1] = q90.ptr.p_double[1]+(double)1/(double)passcount;
}
errless = errless||ae_fp_greater(v,erc1*1.001);
}
for(i=0; i<=1; i++)
{
err50 = err50||ae_fp_less(q50.ptr.p_double[i],0.50);
err90 = err90||ae_fp_less(q90.ptr.p_double[i],0.90);
}
/*
* degenerate matrix test
*/
if( n>=3 )
{
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
a.ptr.pp_double[0][0] = (double)(1);
a.ptr.pp_double[n-1][n-1] = (double)(1);
errspec = errspec||ae_fp_neq(spdmatrixrcond(&a, n, isupper, _state),(double)(-1));
errspec = errspec||ae_fp_neq(spdmatrixcholeskyrcond(&a, n, isupper, _state),(double)(0));
}
/*
* near-degenerate matrix test
*/
if( n>=2 )
{
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
for(i=0; i<=n-1; i++)
{
a.ptr.pp_double[i][i] = (double)(1);
}
i = ae_randominteger(n, _state);
a.ptr.pp_double[i][i] = 0.1*ae_maxrealnumber;
errspec = errspec||ae_fp_neq(spdmatrixrcond(&a, n, isupper, _state),(double)(0));
errspec = errspec||ae_fp_neq(spdmatrixcholeskyrcond(&a, n, isupper, _state),(double)(0));
}
}
/*
* report
*/
result = !(((err50||err90)||errless)||errspec);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Returns True for successful test, False - for failed test
*************************************************************************/
static ae_bool testrcondunit_testcmatrixrcond(ae_int_t maxn,
ae_int_t passcount,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix lua;
ae_vector p;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_int_t pass;
ae_bool err50;
ae_bool err90;
ae_bool errless;
ae_bool errspec;
double erc1;
double ercinf;
ae_vector q50;
ae_vector q90;
double v;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&lua, 0, sizeof(lua));
memset(&p, 0, sizeof(p));
memset(&q50, 0, sizeof(q50));
memset(&q90, 0, sizeof(q90));
ae_matrix_init(&a, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&lua, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&p, 0, DT_INT, _state, ae_true);
ae_vector_init(&q50, 0, DT_REAL, _state, ae_true);
ae_vector_init(&q90, 0, DT_REAL, _state, ae_true);
ae_vector_set_length(&q50, 3+1, _state);
ae_vector_set_length(&q90, 3+1, _state);
err50 = ae_false;
err90 = ae_false;
errless = ae_false;
errspec = ae_false;
/*
* process
*/
for(n=1; n<=maxn; n++)
{
/*
* special test for zero matrix
*/
testrcondunit_cmatrixgenzero(&a, n, _state);
testrcondunit_cmatrixmakeacopy(&a, n, n, &lua, _state);
cmatrixlu(&lua, n, n, &p, _state);
errspec = errspec||ae_fp_neq(cmatrixrcond1(&a, n, _state),(double)(0));
errspec = errspec||ae_fp_neq(cmatrixrcondinf(&a, n, _state),(double)(0));
errspec = errspec||ae_fp_neq(cmatrixlurcond1(&lua, n, _state),(double)(0));
errspec = errspec||ae_fp_neq(cmatrixlurcondinf(&lua, n, _state),(double)(0));
/*
* general test
*/
ae_matrix_set_length(&a, n-1+1, n-1+1, _state);
for(i=0; i<=3; i++)
{
q50.ptr.p_double[i] = (double)(0);
q90.ptr.p_double[i] = (double)(0);
}
for(pass=1; pass<=passcount; pass++)
{
cmatrixrndcond(n, ae_exp(ae_randomreal(_state)*ae_log((double)(1000), _state), _state), &a, _state);
testrcondunit_cmatrixmakeacopy(&a, n, n, &lua, _state);
cmatrixlu(&lua, n, n, &p, _state);
testrcondunit_cmatrixrefrcond(&a, n, &erc1, &ercinf, _state);
/*
* 1-norm, normal
*/
v = 1/cmatrixrcond1(&a, n, _state);
if( ae_fp_greater_eq(v,testrcondunit_threshold50*erc1) )
{
q50.ptr.p_double[0] = q50.ptr.p_double[0]+(double)1/(double)passcount;
}
if( ae_fp_greater_eq(v,testrcondunit_threshold90*erc1) )
{
q90.ptr.p_double[0] = q90.ptr.p_double[0]+(double)1/(double)passcount;
}
errless = errless||ae_fp_greater(v,erc1*1.001);
/*
* 1-norm, LU
*/
v = 1/cmatrixlurcond1(&lua, n, _state);
if( ae_fp_greater_eq(v,testrcondunit_threshold50*erc1) )
{
q50.ptr.p_double[1] = q50.ptr.p_double[1]+(double)1/(double)passcount;
}
if( ae_fp_greater_eq(v,testrcondunit_threshold90*erc1) )
{
q90.ptr.p_double[1] = q90.ptr.p_double[1]+(double)1/(double)passcount;
}
errless = errless||ae_fp_greater(v,erc1*1.001);
/*
* Inf-norm, normal
*/
v = 1/cmatrixrcondinf(&a, n, _state);
if( ae_fp_greater_eq(v,testrcondunit_threshold50*ercinf) )
{
q50.ptr.p_double[2] = q50.ptr.p_double[2]+(double)1/(double)passcount;
}
if( ae_fp_greater_eq(v,testrcondunit_threshold90*ercinf) )
{
q90.ptr.p_double[2] = q90.ptr.p_double[2]+(double)1/(double)passcount;
}
errless = errless||ae_fp_greater(v,ercinf*1.001);
/*
* Inf-norm, LU
*/
v = 1/cmatrixlurcondinf(&lua, n, _state);
if( ae_fp_greater_eq(v,testrcondunit_threshold50*ercinf) )
{
q50.ptr.p_double[3] = q50.ptr.p_double[3]+(double)1/(double)passcount;
}
if( ae_fp_greater_eq(v,testrcondunit_threshold90*ercinf) )
{
q90.ptr.p_double[3] = q90.ptr.p_double[3]+(double)1/(double)passcount;
}
errless = errless||ae_fp_greater(v,ercinf*1.001);
}
for(i=0; i<=3; i++)
{
err50 = err50||ae_fp_less(q50.ptr.p_double[i],0.50);
err90 = err90||ae_fp_less(q90.ptr.p_double[i],0.90);
}
/*
* degenerate matrix test
*/
if( n>=3 )
{
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j] = ae_complex_from_d(0.0);
}
}
a.ptr.pp_complex[0][0] = ae_complex_from_i(1);
a.ptr.pp_complex[n-1][n-1] = ae_complex_from_i(1);
errspec = errspec||ae_fp_neq(cmatrixrcond1(&a, n, _state),(double)(0));
errspec = errspec||ae_fp_neq(cmatrixrcondinf(&a, n, _state),(double)(0));
errspec = errspec||ae_fp_neq(cmatrixlurcond1(&a, n, _state),(double)(0));
errspec = errspec||ae_fp_neq(cmatrixlurcondinf(&a, n, _state),(double)(0));
}
/*
* near-degenerate matrix test
*/
if( n>=2 )
{
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j] = ae_complex_from_d(0.0);
}
}
for(i=0; i<=n-1; i++)
{
a.ptr.pp_complex[i][i] = ae_complex_from_i(1);
}
i = ae_randominteger(n, _state);
a.ptr.pp_complex[i][i] = ae_complex_from_d(0.1*ae_maxrealnumber);
errspec = errspec||ae_fp_neq(cmatrixrcond1(&a, n, _state),(double)(0));
errspec = errspec||ae_fp_neq(cmatrixrcondinf(&a, n, _state),(double)(0));
errspec = errspec||ae_fp_neq(cmatrixlurcond1(&a, n, _state),(double)(0));
errspec = errspec||ae_fp_neq(cmatrixlurcondinf(&a, n, _state),(double)(0));
}
}
/*
* report
*/
result = !(((err50||err90)||errless)||errspec);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Returns True for successful test, False - for failed test
*************************************************************************/
static ae_bool testrcondunit_testhpdmatrixrcond(ae_int_t maxn,
ae_int_t passcount,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix cha;
ae_vector p;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_int_t pass;
ae_bool err50;
ae_bool err90;
ae_bool errspec;
ae_bool errless;
ae_bool isupper;
double erc1;
double ercinf;
ae_vector q50;
ae_vector q90;
double v;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&cha, 0, sizeof(cha));
memset(&p, 0, sizeof(p));
memset(&q50, 0, sizeof(q50));
memset(&q90, 0, sizeof(q90));
ae_matrix_init(&a, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&cha, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&p, 0, DT_INT, _state, ae_true);
ae_vector_init(&q50, 0, DT_REAL, _state, ae_true);
ae_vector_init(&q90, 0, DT_REAL, _state, ae_true);
err50 = ae_false;
err90 = ae_false;
errless = ae_false;
errspec = ae_false;
ae_vector_set_length(&q50, 2, _state);
ae_vector_set_length(&q90, 2, _state);
for(n=1; n<=maxn; n++)
{
isupper = ae_fp_greater(ae_randomreal(_state),0.5);
/*
* general test
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=1; i++)
{
q50.ptr.p_double[i] = (double)(0);
q90.ptr.p_double[i] = (double)(0);
}
for(pass=1; pass<=passcount; pass++)
{
hpdmatrixrndcond(n, ae_exp(ae_randomreal(_state)*ae_log((double)(1000), _state), _state), &a, _state);
testrcondunit_cmatrixrefrcond(&a, n, &erc1, &ercinf, _state);
testrcondunit_cmatrixdrophalf(&a, n, isupper, _state);
testrcondunit_cmatrixmakeacopy(&a, n, n, &cha, _state);
hpdmatrixcholesky(&cha, n, isupper, _state);
/*
* normal
*/
v = 1/hpdmatrixrcond(&a, n, isupper, _state);
if( ae_fp_greater_eq(v,testrcondunit_threshold50*erc1) )
{
q50.ptr.p_double[0] = q50.ptr.p_double[0]+(double)1/(double)passcount;
}
if( ae_fp_greater_eq(v,testrcondunit_threshold90*erc1) )
{
q90.ptr.p_double[0] = q90.ptr.p_double[0]+(double)1/(double)passcount;
}
errless = errless||ae_fp_greater(v,erc1*1.001);
/*
* Cholesky
*/
v = 1/hpdmatrixcholeskyrcond(&cha, n, isupper, _state);
if( ae_fp_greater_eq(v,testrcondunit_threshold50*erc1) )
{
q50.ptr.p_double[1] = q50.ptr.p_double[1]+(double)1/(double)passcount;
}
if( ae_fp_greater_eq(v,testrcondunit_threshold90*erc1) )
{
q90.ptr.p_double[1] = q90.ptr.p_double[1]+(double)1/(double)passcount;
}
errless = errless||ae_fp_greater(v,erc1*1.001);
}
for(i=0; i<=1; i++)
{
err50 = err50||ae_fp_less(q50.ptr.p_double[i],0.50);
err90 = err90||ae_fp_less(q90.ptr.p_double[i],0.90);
}
/*
* degenerate matrix test
*/
if( n>=3 )
{
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j] = ae_complex_from_d(0.0);
}
}
a.ptr.pp_complex[0][0] = ae_complex_from_i(1);
a.ptr.pp_complex[n-1][n-1] = ae_complex_from_i(1);
errspec = errspec||ae_fp_neq(hpdmatrixrcond(&a, n, isupper, _state),(double)(-1));
errspec = errspec||ae_fp_neq(hpdmatrixcholeskyrcond(&a, n, isupper, _state),(double)(0));
}
/*
* near-degenerate matrix test
*/
if( n>=2 )
{
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j] = ae_complex_from_d(0.0);
}
}
for(i=0; i<=n-1; i++)
{
a.ptr.pp_complex[i][i] = ae_complex_from_i(1);
}
i = ae_randominteger(n, _state);
a.ptr.pp_complex[i][i] = ae_complex_from_d(0.1*ae_maxrealnumber);
errspec = errspec||ae_fp_neq(hpdmatrixrcond(&a, n, isupper, _state),(double)(0));
errspec = errspec||ae_fp_neq(hpdmatrixcholeskyrcond(&a, n, isupper, _state),(double)(0));
}
}
/*
* report
*/
result = !(((err50||err90)||errless)||errspec);
ae_frame_leave(_state);
return result;
}
static void testmatinvunit_rmatrixmakeacopy(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Real */ ae_matrix* b,
ae_state *_state);
static void testmatinvunit_cmatrixmakeacopy(/* Complex */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Complex */ ae_matrix* b,
ae_state *_state);
static ae_bool testmatinvunit_rmatrixcheckinverse(/* Real */ ae_matrix* a,
/* Real */ ae_matrix* inva,
ae_int_t n,
double threshold,
ae_int_t info,
matinvreport* rep,
ae_state *_state);
static ae_bool testmatinvunit_spdmatrixcheckinverse(/* Real */ ae_matrix* a,
/* Real */ ae_matrix* inva,
ae_bool isupper,
ae_int_t n,
double threshold,
ae_int_t info,
matinvreport* rep,
ae_state *_state);
static ae_bool testmatinvunit_hpdmatrixcheckinverse(/* Complex */ ae_matrix* a,
/* Complex */ ae_matrix* inva,
ae_bool isupper,
ae_int_t n,
double threshold,
ae_int_t info,
matinvreport* rep,
ae_state *_state);
static ae_bool testmatinvunit_rmatrixcheckinversesingular(/* Real */ ae_matrix* inva,
ae_int_t n,
double threshold,
ae_int_t info,
matinvreport* rep,
ae_state *_state);
static ae_bool testmatinvunit_cmatrixcheckinverse(/* Complex */ ae_matrix* a,
/* Complex */ ae_matrix* inva,
ae_int_t n,
double threshold,
ae_int_t info,
matinvreport* rep,
ae_state *_state);
static ae_bool testmatinvunit_cmatrixcheckinversesingular(/* Complex */ ae_matrix* inva,
ae_int_t n,
double threshold,
ae_int_t info,
matinvreport* rep,
ae_state *_state);
static void testmatinvunit_rmatrixdrophalf(/* Real */ ae_matrix* a,
ae_int_t n,
ae_bool droplower,
ae_state *_state);
static void testmatinvunit_cmatrixdrophalf(/* Complex */ ae_matrix* a,
ae_int_t n,
ae_bool droplower,
ae_state *_state);
static void testmatinvunit_testrtrinv(ae_int_t minn,
ae_int_t maxn,
ae_int_t passcount,
double threshold,
ae_bool* rtrerrors,
ae_state *_state);
static void testmatinvunit_testctrinv(ae_int_t minn,
ae_int_t maxn,
ae_int_t passcount,
double threshold,
ae_bool* ctrerrors,
ae_state *_state);
static void testmatinvunit_testrinv(ae_int_t minn,
ae_int_t maxn,
ae_int_t passcount,
double threshold,
ae_bool* rerrors,
ae_state *_state);
static void testmatinvunit_testcinv(ae_int_t minn,
ae_int_t maxn,
ae_int_t passcount,
double threshold,
ae_bool* cerrors,
ae_state *_state);
static void testmatinvunit_testspdinv(ae_int_t minn,
ae_int_t maxn,
ae_int_t passcount,
double threshold,
ae_bool* spderrors,
ae_state *_state);
static void testmatinvunit_testhpdinv(ae_int_t minn,
ae_int_t maxn,
ae_int_t passcount,
double threshold,
ae_bool* hpderrors,
ae_state *_state);
static void testmatinvunit_unset2d(/* Real */ ae_matrix* x,
ae_state *_state);
static void testmatinvunit_cunset2d(/* Complex */ ae_matrix* x,
ae_state *_state);
static void testmatinvunit_unsetrep(matinvreport* r, ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testmatinv(ae_bool silent, ae_state *_state)
{
ae_int_t maxrn;
ae_int_t maxcn;
ae_int_t largen;
ae_int_t passcount;
double threshold;
ae_bool rtrerrors;
ae_bool ctrerrors;
ae_bool rerrors;
ae_bool cerrors;
ae_bool spderrors;
ae_bool hpderrors;
ae_bool waserrors;
ae_bool result;
maxrn = 3*matrixtilesizea(_state)+1;
maxcn = 3*matrixtilesizea(_state)+1;
largen = 4*matrixtilesizeb(_state)+1;
passcount = 1;
threshold = 10000*ae_machineepsilon;
rtrerrors = ae_false;
ctrerrors = ae_false;
rerrors = ae_false;
cerrors = ae_false;
spderrors = ae_false;
hpderrors = ae_false;
testmatinvunit_testrtrinv(1, maxrn, passcount, threshold, &rtrerrors, _state);
testmatinvunit_testctrinv(1, maxcn, passcount, threshold, &ctrerrors, _state);
testmatinvunit_testrinv(1, maxrn, passcount, threshold, &rerrors, _state);
testmatinvunit_testspdinv(1, maxrn, passcount, threshold, &spderrors, _state);
testmatinvunit_testcinv(1, maxcn, passcount, threshold, &cerrors, _state);
testmatinvunit_testhpdinv(1, maxcn, passcount, threshold, &hpderrors, _state);
testmatinvunit_testrtrinv(largen, largen, passcount, threshold, &rtrerrors, _state);
testmatinvunit_testctrinv(largen, largen, passcount, threshold, &ctrerrors, _state);
testmatinvunit_testrinv(largen, largen, passcount, threshold, &rerrors, _state);
testmatinvunit_testspdinv(largen, largen, passcount, threshold, &spderrors, _state);
testmatinvunit_testcinv(largen, largen, passcount, threshold, &cerrors, _state);
testmatinvunit_testhpdinv(largen, largen, passcount, threshold, &hpderrors, _state);
waserrors = ((((rtrerrors||ctrerrors)||rerrors)||cerrors)||spderrors)||hpderrors;
if( !silent )
{
printf("TESTING MATINV\n");
printf("* REAL TRIANGULAR: ");
if( rtrerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* COMPLEX TRIANGULAR: ");
if( ctrerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* REAL: ");
if( rerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* COMPLEX: ");
if( cerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* SPD: ");
if( spderrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* HPD: ");
if( hpderrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
}
result = !waserrors;
return result;
}
/*************************************************************************
Copy
*************************************************************************/
static void testmatinvunit_rmatrixmakeacopy(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Real */ ae_matrix* b,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_matrix_clear(b);
ae_matrix_set_length(b, m-1+1, n-1+1, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
b->ptr.pp_double[i][j] = a->ptr.pp_double[i][j];
}
}
}
/*************************************************************************
Copy
*************************************************************************/
static void testmatinvunit_cmatrixmakeacopy(/* Complex */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Complex */ ae_matrix* b,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_matrix_clear(b);
ae_matrix_set_length(b, m-1+1, n-1+1, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
b->ptr.pp_complex[i][j] = a->ptr.pp_complex[i][j];
}
}
}
/*************************************************************************
Checks whether inverse is correct
Returns True on success.
*************************************************************************/
static ae_bool testmatinvunit_rmatrixcheckinverse(/* Real */ ae_matrix* a,
/* Real */ ae_matrix* inva,
ae_int_t n,
double threshold,
ae_int_t info,
matinvreport* rep,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
double v;
ae_bool result;
result = ae_true;
if( info<=0 )
{
result = ae_false;
}
else
{
result = result&&!(ae_fp_less(rep->r1,100*ae_machineepsilon)||ae_fp_greater(rep->r1,1+1000*ae_machineepsilon));
result = result&&!(ae_fp_less(rep->rinf,100*ae_machineepsilon)||ae_fp_greater(rep->rinf,1+1000*ae_machineepsilon));
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&a->ptr.pp_double[i][0], 1, &inva->ptr.pp_double[0][j], inva->stride, ae_v_len(0,n-1));
if( i==j )
{
v = v-1;
}
result = result&&ae_fp_less_eq(ae_fabs(v, _state),threshold);
}
}
}
return result;
}
/*************************************************************************
Checks whether inverse is correct
Returns True on success.
*************************************************************************/
static ae_bool testmatinvunit_spdmatrixcheckinverse(/* Real */ ae_matrix* a,
/* Real */ ae_matrix* inva,
ae_bool isupper,
ae_int_t n,
double threshold,
ae_int_t info,
matinvreport* rep,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix _a;
ae_matrix _inva;
ae_int_t i;
ae_int_t j;
double v;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&_a, 0, sizeof(_a));
memset(&_inva, 0, sizeof(_inva));
ae_matrix_init_copy(&_a, a, _state, ae_true);
a = &_a;
ae_matrix_init_copy(&_inva, inva, _state, ae_true);
inva = &_inva;
for(i=0; i<=n-2; i++)
{
if( isupper )
{
ae_v_move(&a->ptr.pp_double[i+1][i], a->stride, &a->ptr.pp_double[i][i+1], 1, ae_v_len(i+1,n-1));
ae_v_move(&inva->ptr.pp_double[i+1][i], inva->stride, &inva->ptr.pp_double[i][i+1], 1, ae_v_len(i+1,n-1));
}
else
{
ae_v_move(&a->ptr.pp_double[i][i+1], 1, &a->ptr.pp_double[i+1][i], a->stride, ae_v_len(i+1,n-1));
ae_v_move(&inva->ptr.pp_double[i][i+1], 1, &inva->ptr.pp_double[i+1][i], inva->stride, ae_v_len(i+1,n-1));
}
}
result = ae_true;
if( info<=0 )
{
result = ae_false;
}
else
{
result = result&&!(ae_fp_less(rep->r1,100*ae_machineepsilon)||ae_fp_greater(rep->r1,1+1000*ae_machineepsilon));
result = result&&!(ae_fp_less(rep->rinf,100*ae_machineepsilon)||ae_fp_greater(rep->rinf,1+1000*ae_machineepsilon));
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&a->ptr.pp_double[i][0], 1, &inva->ptr.pp_double[0][j], inva->stride, ae_v_len(0,n-1));
if( i==j )
{
v = v-1;
}
result = result&&ae_fp_less_eq(ae_fabs(v, _state),threshold);
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Checks whether inverse is correct
Returns True on success.
*************************************************************************/
static ae_bool testmatinvunit_hpdmatrixcheckinverse(/* Complex */ ae_matrix* a,
/* Complex */ ae_matrix* inva,
ae_bool isupper,
ae_int_t n,
double threshold,
ae_int_t info,
matinvreport* rep,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix _a;
ae_matrix _inva;
ae_int_t i;
ae_int_t j;
ae_complex v;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&_a, 0, sizeof(_a));
memset(&_inva, 0, sizeof(_inva));
ae_matrix_init_copy(&_a, a, _state, ae_true);
a = &_a;
ae_matrix_init_copy(&_inva, inva, _state, ae_true);
inva = &_inva;
for(i=0; i<=n-2; i++)
{
if( isupper )
{
ae_v_cmove(&a->ptr.pp_complex[i+1][i], a->stride, &a->ptr.pp_complex[i][i+1], 1, "Conj", ae_v_len(i+1,n-1));
ae_v_cmove(&inva->ptr.pp_complex[i+1][i], inva->stride, &inva->ptr.pp_complex[i][i+1], 1, "Conj", ae_v_len(i+1,n-1));
}
else
{
ae_v_cmove(&a->ptr.pp_complex[i][i+1], 1, &a->ptr.pp_complex[i+1][i], a->stride, "Conj", ae_v_len(i+1,n-1));
ae_v_cmove(&inva->ptr.pp_complex[i][i+1], 1, &inva->ptr.pp_complex[i+1][i], inva->stride, "Conj", ae_v_len(i+1,n-1));
}
}
result = ae_true;
if( info<=0 )
{
result = ae_false;
}
else
{
result = result&&!(ae_fp_less(rep->r1,100*ae_machineepsilon)||ae_fp_greater(rep->r1,1+1000*ae_machineepsilon));
result = result&&!(ae_fp_less(rep->rinf,100*ae_machineepsilon)||ae_fp_greater(rep->rinf,1+1000*ae_machineepsilon));
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_cdotproduct(&a->ptr.pp_complex[i][0], 1, "N", &inva->ptr.pp_complex[0][j], inva->stride, "N", ae_v_len(0,n-1));
if( i==j )
{
v = ae_c_sub_d(v,1);
}
result = result&&ae_fp_less_eq(ae_c_abs(v, _state),threshold);
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Checks whether inversion result indicate singular matrix
Returns True on success.
*************************************************************************/
static ae_bool testmatinvunit_rmatrixcheckinversesingular(/* Real */ ae_matrix* inva,
ae_int_t n,
double threshold,
ae_int_t info,
matinvreport* rep,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_bool result;
result = ae_true;
if( info!=-3&&info!=1 )
{
result = ae_false;
}
else
{
result = result&&!(ae_fp_less(rep->r1,(double)(0))||ae_fp_greater(rep->r1,1000*ae_machineepsilon));
result = result&&!(ae_fp_less(rep->rinf,(double)(0))||ae_fp_greater(rep->rinf,1000*ae_machineepsilon));
if( info==-3 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
result = result&&ae_fp_eq(inva->ptr.pp_double[i][j],(double)(0));
}
}
}
}
return result;
}
/*************************************************************************
Checks whether inverse is correct
Returns True on success.
*************************************************************************/
static ae_bool testmatinvunit_cmatrixcheckinverse(/* Complex */ ae_matrix* a,
/* Complex */ ae_matrix* inva,
ae_int_t n,
double threshold,
ae_int_t info,
matinvreport* rep,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_complex v;
ae_bool result;
result = ae_true;
if( info<=0 )
{
result = ae_false;
}
else
{
result = result&&!(ae_fp_less(rep->r1,100*ae_machineepsilon)||ae_fp_greater(rep->r1,1+1000*ae_machineepsilon));
result = result&&!(ae_fp_less(rep->rinf,100*ae_machineepsilon)||ae_fp_greater(rep->rinf,1+1000*ae_machineepsilon));
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_cdotproduct(&a->ptr.pp_complex[i][0], 1, "N", &inva->ptr.pp_complex[0][j], inva->stride, "N", ae_v_len(0,n-1));
if( i==j )
{
v = ae_c_sub_d(v,1);
}
result = result&&ae_fp_less_eq(ae_c_abs(v, _state),threshold);
}
}
}
return result;
}
/*************************************************************************
Checks whether inversion result indicate singular matrix
Returns True on success.
*************************************************************************/
static ae_bool testmatinvunit_cmatrixcheckinversesingular(/* Complex */ ae_matrix* inva,
ae_int_t n,
double threshold,
ae_int_t info,
matinvreport* rep,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_bool result;
result = ae_true;
if( info!=-3&&info!=1 )
{
result = ae_false;
}
else
{
result = result&&!(ae_fp_less(rep->r1,(double)(0))||ae_fp_greater(rep->r1,1000*ae_machineepsilon));
result = result&&!(ae_fp_less(rep->rinf,(double)(0))||ae_fp_greater(rep->rinf,1000*ae_machineepsilon));
if( info==-3 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
result = result&&ae_c_eq_d(inva->ptr.pp_complex[i][j],(double)(0));
}
}
}
}
return result;
}
/*************************************************************************
Drops upper or lower half of the matrix - fills it by special pattern
which may be used later to ensure that this part wasn't changed
*************************************************************************/
static void testmatinvunit_rmatrixdrophalf(/* Real */ ae_matrix* a,
ae_int_t n,
ae_bool droplower,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (droplower&&i>j)||(!droplower&&iptr.pp_double[i][j] = (double)(1+2*i+3*j);
}
}
}
}
/*************************************************************************
Drops upper or lower half of the matrix - fills it by special pattern
which may be used later to ensure that this part wasn't changed
*************************************************************************/
static void testmatinvunit_cmatrixdrophalf(/* Complex */ ae_matrix* a,
ae_int_t n,
ae_bool droplower,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (droplower&&i>j)||(!droplower&&iptr.pp_complex[i][j] = ae_complex_from_i(1+2*i+3*j);
}
}
}
}
/*************************************************************************
Real TR inverse
*************************************************************************/
static void testmatinvunit_testrtrinv(ae_int_t minn,
ae_int_t maxn,
ae_int_t passcount,
double threshold,
ae_bool* rtrerrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix b;
ae_int_t n;
ae_int_t pass;
ae_int_t i;
ae_int_t j;
ae_int_t task;
ae_bool isupper;
ae_bool isunit;
double v;
ae_int_t info;
matinvreport rep;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
memset(&rep, 0, sizeof(rep));
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true);
_matinvreport_init(&rep, _state, ae_true);
/*
* Test
*/
for(n=minn; n<=maxn; n++)
{
ae_matrix_set_length(&a, n, n, _state);
ae_matrix_set_length(&b, n, n, _state);
for(task=0; task<=3; task++)
{
for(pass=1; pass<=passcount; pass++)
{
/*
* Determine task
*/
isupper = task%2==0;
isunit = task/2%2==0;
/*
* Generate matrix
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( i==j )
{
a.ptr.pp_double[i][i] = 1+ae_randomreal(_state);
}
else
{
a.ptr.pp_double[i][j] = 0.2*ae_randomreal(_state)-0.1;
}
b.ptr.pp_double[i][j] = a.ptr.pp_double[i][j];
}
}
/*
* Inverse
*/
rmatrixtrinverse(&b, n, isupper, isunit, &info, &rep, _state);
if( info<=0 )
{
*rtrerrors = ae_true;
ae_frame_leave(_state);
return;
}
/*
* Structural test
*/
if( isunit )
{
for(i=0; i<=n-1; i++)
{
*rtrerrors = *rtrerrors||ae_fp_neq(a.ptr.pp_double[i][i],b.ptr.pp_double[i][i]);
}
}
if( isupper )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=i-1; j++)
{
*rtrerrors = *rtrerrors||ae_fp_neq(a.ptr.pp_double[i][j],b.ptr.pp_double[i][j]);
}
}
}
else
{
for(i=0; i<=n-1; i++)
{
for(j=i+1; j<=n-1; j++)
{
*rtrerrors = *rtrerrors||ae_fp_neq(a.ptr.pp_double[i][j],b.ptr.pp_double[i][j]);
}
}
}
/*
* Inverse test
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (ji&&!isupper) )
{
a.ptr.pp_double[i][j] = (double)(0);
b.ptr.pp_double[i][j] = (double)(0);
}
}
}
if( isunit )
{
for(i=0; i<=n-1; i++)
{
a.ptr.pp_double[i][i] = (double)(1);
b.ptr.pp_double[i][i] = (double)(1);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &b.ptr.pp_double[0][j], b.stride, ae_v_len(0,n-1));
if( j!=i )
{
*rtrerrors = *rtrerrors||ae_fp_greater(ae_fabs(v, _state),threshold);
}
else
{
*rtrerrors = *rtrerrors||ae_fp_greater(ae_fabs(v-1, _state),threshold);
}
}
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Complex TR inverse
*************************************************************************/
static void testmatinvunit_testctrinv(ae_int_t minn,
ae_int_t maxn,
ae_int_t passcount,
double threshold,
ae_bool* ctrerrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix b;
ae_int_t n;
ae_int_t pass;
ae_int_t i;
ae_int_t j;
ae_int_t task;
ae_bool isupper;
ae_bool isunit;
ae_complex v;
ae_int_t info;
matinvreport rep;
double emax;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
memset(&rep, 0, sizeof(rep));
ae_matrix_init(&a, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&b, 0, 0, DT_COMPLEX, _state, ae_true);
_matinvreport_init(&rep, _state, ae_true);
/*
* Test
*/
for(n=minn; n<=maxn; n++)
{
ae_matrix_set_length(&a, n, n, _state);
ae_matrix_set_length(&b, n, n, _state);
for(task=0; task<=3; task++)
{
for(pass=1; pass<=passcount; pass++)
{
/*
* Determine task
*/
isupper = task%2==0;
isunit = task/2%2==0;
/*
* Generate matrix
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( i==j )
{
a.ptr.pp_complex[i][i].x = 1+ae_randomreal(_state);
a.ptr.pp_complex[i][i].y = 1+ae_randomreal(_state);
}
else
{
a.ptr.pp_complex[i][j].x = 0.2*ae_randomreal(_state)-0.1;
a.ptr.pp_complex[i][j].y = 0.2*ae_randomreal(_state)-0.1;
}
b.ptr.pp_complex[i][j] = a.ptr.pp_complex[i][j];
}
}
/*
* Inverse
*/
cmatrixtrinverse(&b, n, isupper, isunit, &info, &rep, _state);
if( info<=0 )
{
*ctrerrors = ae_true;
ae_frame_leave(_state);
return;
}
/*
* Structural test
*/
if( isunit )
{
for(i=0; i<=n-1; i++)
{
*ctrerrors = *ctrerrors||ae_c_neq(a.ptr.pp_complex[i][i],b.ptr.pp_complex[i][i]);
}
}
if( isupper )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=i-1; j++)
{
*ctrerrors = *ctrerrors||ae_c_neq(a.ptr.pp_complex[i][j],b.ptr.pp_complex[i][j]);
}
}
}
else
{
for(i=0; i<=n-1; i++)
{
for(j=i+1; j<=n-1; j++)
{
*ctrerrors = *ctrerrors||ae_c_neq(a.ptr.pp_complex[i][j],b.ptr.pp_complex[i][j]);
}
}
}
/*
* Inverse test
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (ji&&!isupper) )
{
a.ptr.pp_complex[i][j] = ae_complex_from_i(0);
b.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
}
if( isunit )
{
for(i=0; i<=n-1; i++)
{
a.ptr.pp_complex[i][i] = ae_complex_from_i(1);
b.ptr.pp_complex[i][i] = ae_complex_from_i(1);
}
}
emax = (double)(0);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_cdotproduct(&a.ptr.pp_complex[i][0], 1, "N", &b.ptr.pp_complex[0][j], b.stride, "N", ae_v_len(0,n-1));
if( j==i )
{
v = ae_c_sub_d(v,1);
}
emax = ae_maxreal(emax, ae_c_abs(v, _state), _state);
}
}
*ctrerrors = *ctrerrors||ae_fp_greater(emax,threshold);
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Real test
*************************************************************************/
static void testmatinvunit_testrinv(ae_int_t minn,
ae_int_t maxn,
ae_int_t passcount,
double threshold,
ae_bool* rerrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix lua;
ae_matrix inva;
ae_matrix invlua;
ae_vector p;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t n;
ae_int_t pass;
ae_int_t taskkind;
ae_int_t info;
matinvreport rep;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&lua, 0, sizeof(lua));
memset(&inva, 0, sizeof(inva));
memset(&invlua, 0, sizeof(invlua));
memset(&p, 0, sizeof(p));
memset(&rep, 0, sizeof(rep));
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&lua, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&inva, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&invlua, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&p, 0, DT_INT, _state, ae_true);
_matinvreport_init(&rep, _state, ae_true);
/*
* General square matrices:
* * test general solvers
* * test least squares solver
*/
for(pass=1; pass<=passcount; pass++)
{
for(n=minn; n<=maxn; n++)
{
/*
* ********************************************************
* WELL CONDITIONED TASKS
* ability to find correct solution is tested
* ********************************************************
*
* 1. generate random well conditioned matrix A.
* 2. generate random solution vector xe
* 3. generate right part b=A*xe
* 4. test different methods on original A
*/
rmatrixrndcond(n, (double)(1000), &a, _state);
testmatinvunit_rmatrixmakeacopy(&a, n, n, &lua, _state);
rmatrixlu(&lua, n, n, &p, _state);
testmatinvunit_rmatrixmakeacopy(&a, n, n, &inva, _state);
testmatinvunit_rmatrixmakeacopy(&lua, n, n, &invlua, _state);
info = 0;
testmatinvunit_unsetrep(&rep, _state);
rmatrixinverse(&inva, n, &info, &rep, _state);
*rerrors = *rerrors||!testmatinvunit_rmatrixcheckinverse(&a, &inva, n, threshold, info, &rep, _state);
info = 0;
testmatinvunit_unsetrep(&rep, _state);
rmatrixluinverse(&invlua, &p, n, &info, &rep, _state);
*rerrors = *rerrors||!testmatinvunit_rmatrixcheckinverse(&a, &invlua, n, threshold, info, &rep, _state);
/*
* ********************************************************
* EXACTLY SINGULAR MATRICES
* ability to detect singularity is tested
* ********************************************************
*
* 1. generate different types of singular matrices:
* * zero
* * with zero columns
* * with zero rows
* * with equal rows/columns
* 2. test different methods
*/
for(taskkind=0; taskkind<=4; taskkind++)
{
testmatinvunit_unset2d(&a, _state);
if( taskkind==0 )
{
/*
* all zeros
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
}
if( taskkind==1 )
{
/*
* there is zero column
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
k = ae_randominteger(n, _state);
ae_v_muld(&a.ptr.pp_double[0][k], a.stride, ae_v_len(0,n-1), 0);
}
if( taskkind==2 )
{
/*
* there is zero row
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
k = ae_randominteger(n, _state);
ae_v_muld(&a.ptr.pp_double[k][0], 1, ae_v_len(0,n-1), 0);
}
if( taskkind==3 )
{
/*
* equal columns
*/
if( n<2 )
{
continue;
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
k = 1+ae_randominteger(n-1, _state);
ae_v_move(&a.ptr.pp_double[0][0], a.stride, &a.ptr.pp_double[0][k], a.stride, ae_v_len(0,n-1));
}
if( taskkind==4 )
{
/*
* equal rows
*/
if( n<2 )
{
continue;
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
k = 1+ae_randominteger(n-1, _state);
ae_v_move(&a.ptr.pp_double[0][0], 1, &a.ptr.pp_double[k][0], 1, ae_v_len(0,n-1));
}
testmatinvunit_rmatrixmakeacopy(&a, n, n, &lua, _state);
rmatrixlu(&lua, n, n, &p, _state);
info = 0;
testmatinvunit_unsetrep(&rep, _state);
rmatrixinverse(&a, n, &info, &rep, _state);
*rerrors = *rerrors||!testmatinvunit_rmatrixcheckinversesingular(&a, n, threshold, info, &rep, _state);
info = 0;
testmatinvunit_unsetrep(&rep, _state);
rmatrixluinverse(&lua, &p, n, &info, &rep, _state);
*rerrors = *rerrors||!testmatinvunit_rmatrixcheckinversesingular(&lua, n, threshold, info, &rep, _state);
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Complex test
*************************************************************************/
static void testmatinvunit_testcinv(ae_int_t minn,
ae_int_t maxn,
ae_int_t passcount,
double threshold,
ae_bool* cerrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix lua;
ae_matrix inva;
ae_matrix invlua;
ae_vector p;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t n;
ae_int_t pass;
ae_int_t taskkind;
ae_int_t info;
matinvreport rep;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&lua, 0, sizeof(lua));
memset(&inva, 0, sizeof(inva));
memset(&invlua, 0, sizeof(invlua));
memset(&p, 0, sizeof(p));
memset(&rep, 0, sizeof(rep));
ae_matrix_init(&a, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&lua, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&inva, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&invlua, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&p, 0, DT_INT, _state, ae_true);
_matinvreport_init(&rep, _state, ae_true);
/*
* General square matrices:
* * test general solvers
* * test least squares solver
*/
for(pass=1; pass<=passcount; pass++)
{
for(n=minn; n<=maxn; n++)
{
/*
* ********************************************************
* WELL CONDITIONED TASKS
* ability to find correct solution is tested
* ********************************************************
*
* 1. generate random well conditioned matrix A.
* 2. generate random solution vector xe
* 3. generate right part b=A*xe
* 4. test different methods on original A
*/
cmatrixrndcond(n, (double)(1000), &a, _state);
testmatinvunit_cmatrixmakeacopy(&a, n, n, &lua, _state);
cmatrixlu(&lua, n, n, &p, _state);
testmatinvunit_cmatrixmakeacopy(&a, n, n, &inva, _state);
testmatinvunit_cmatrixmakeacopy(&lua, n, n, &invlua, _state);
info = 0;
testmatinvunit_unsetrep(&rep, _state);
cmatrixinverse(&inva, n, &info, &rep, _state);
*cerrors = *cerrors||!testmatinvunit_cmatrixcheckinverse(&a, &inva, n, threshold, info, &rep, _state);
info = 0;
testmatinvunit_unsetrep(&rep, _state);
cmatrixluinverse(&invlua, &p, n, &info, &rep, _state);
*cerrors = *cerrors||!testmatinvunit_cmatrixcheckinverse(&a, &invlua, n, threshold, info, &rep, _state);
/*
* ********************************************************
* EXACTLY SINGULAR MATRICES
* ability to detect singularity is tested
* ********************************************************
*
* 1. generate different types of singular matrices:
* * zero
* * with zero columns
* * with zero rows
* * with equal rows/columns
* 2. test different methods
*/
for(taskkind=0; taskkind<=4; taskkind++)
{
testmatinvunit_cunset2d(&a, _state);
if( taskkind==0 )
{
/*
* all zeros
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
}
if( taskkind==1 )
{
/*
* there is zero column
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
k = ae_randominteger(n, _state);
ae_v_cmuld(&a.ptr.pp_complex[0][k], a.stride, ae_v_len(0,n-1), 0);
}
if( taskkind==2 )
{
/*
* there is zero row
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
k = ae_randominteger(n, _state);
ae_v_cmuld(&a.ptr.pp_complex[k][0], 1, ae_v_len(0,n-1), 0);
}
if( taskkind==3 )
{
/*
* equal columns
*/
if( n<2 )
{
continue;
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
k = 1+ae_randominteger(n-1, _state);
ae_v_cmove(&a.ptr.pp_complex[0][0], a.stride, &a.ptr.pp_complex[0][k], a.stride, "N", ae_v_len(0,n-1));
}
if( taskkind==4 )
{
/*
* equal rows
*/
if( n<2 )
{
continue;
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
k = 1+ae_randominteger(n-1, _state);
ae_v_cmove(&a.ptr.pp_complex[0][0], 1, &a.ptr.pp_complex[k][0], 1, "N", ae_v_len(0,n-1));
}
testmatinvunit_cmatrixmakeacopy(&a, n, n, &lua, _state);
cmatrixlu(&lua, n, n, &p, _state);
info = 0;
testmatinvunit_unsetrep(&rep, _state);
cmatrixinverse(&a, n, &info, &rep, _state);
*cerrors = *cerrors||!testmatinvunit_cmatrixcheckinversesingular(&a, n, threshold, info, &rep, _state);
info = 0;
testmatinvunit_unsetrep(&rep, _state);
cmatrixluinverse(&lua, &p, n, &info, &rep, _state);
*cerrors = *cerrors||!testmatinvunit_cmatrixcheckinversesingular(&lua, n, threshold, info, &rep, _state);
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
SPD test
*************************************************************************/
static void testmatinvunit_testspdinv(ae_int_t minn,
ae_int_t maxn,
ae_int_t passcount,
double threshold,
ae_bool* spderrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix cha;
ae_matrix inva;
ae_matrix invcha;
ae_bool isupper;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t n;
ae_int_t pass;
ae_int_t taskkind;
ae_int_t info;
matinvreport rep;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&cha, 0, sizeof(cha));
memset(&inva, 0, sizeof(inva));
memset(&invcha, 0, sizeof(invcha));
memset(&rep, 0, sizeof(rep));
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&cha, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&inva, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&invcha, 0, 0, DT_REAL, _state, ae_true);
_matinvreport_init(&rep, _state, ae_true);
/*
* General square matrices:
* * test general solvers
* * test least squares solver
*/
for(pass=1; pass<=passcount; pass++)
{
for(n=minn; n<=maxn; n++)
{
isupper = ae_fp_greater(ae_randomreal(_state),0.5);
/*
* ********************************************************
* WELL CONDITIONED TASKS
* ability to find correct solution is tested
* ********************************************************
*
* 1. generate random well conditioned matrix A.
* 2. generate random solution vector xe
* 3. generate right part b=A*xe
* 4. test different methods on original A
*/
spdmatrixrndcond(n, (double)(1000), &a, _state);
testmatinvunit_rmatrixdrophalf(&a, n, isupper, _state);
testmatinvunit_rmatrixmakeacopy(&a, n, n, &cha, _state);
if( !spdmatrixcholesky(&cha, n, isupper, _state) )
{
continue;
}
testmatinvunit_rmatrixmakeacopy(&a, n, n, &inva, _state);
testmatinvunit_rmatrixmakeacopy(&cha, n, n, &invcha, _state);
info = 0;
testmatinvunit_unsetrep(&rep, _state);
spdmatrixinverse(&inva, n, isupper, &info, &rep, _state);
*spderrors = *spderrors||!testmatinvunit_spdmatrixcheckinverse(&a, &inva, isupper, n, threshold, info, &rep, _state);
info = 0;
testmatinvunit_unsetrep(&rep, _state);
spdmatrixcholeskyinverse(&invcha, n, isupper, &info, &rep, _state);
*spderrors = *spderrors||!testmatinvunit_spdmatrixcheckinverse(&a, &invcha, isupper, n, threshold, info, &rep, _state);
/*
* ********************************************************
* EXACTLY SINGULAR MATRICES
* ability to detect singularity is tested
* ********************************************************
*
* 1. generate different types of singular matrices:
* * zero
* * with zero columns
* * with zero rows
* 2. test different methods
*/
for(taskkind=0; taskkind<=2; taskkind++)
{
testmatinvunit_unset2d(&a, _state);
if( taskkind==0 )
{
/*
* all zeros
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
}
if( taskkind==1 )
{
/*
* there is zero column
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
k = ae_randominteger(n, _state);
ae_v_muld(&a.ptr.pp_double[0][k], a.stride, ae_v_len(0,n-1), 0);
}
if( taskkind==2 )
{
/*
* there is zero row
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
k = ae_randominteger(n, _state);
ae_v_muld(&a.ptr.pp_double[k][0], 1, ae_v_len(0,n-1), 0);
}
info = 0;
testmatinvunit_unsetrep(&rep, _state);
spdmatrixcholeskyinverse(&a, n, isupper, &info, &rep, _state);
if( info!=-3&&info!=1 )
{
*spderrors = ae_true;
}
else
{
*spderrors = (*spderrors||ae_fp_less(rep.r1,(double)(0)))||ae_fp_greater(rep.r1,1000*ae_machineepsilon);
*spderrors = (*spderrors||ae_fp_less(rep.rinf,(double)(0)))||ae_fp_greater(rep.rinf,1000*ae_machineepsilon);
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
HPD test
*************************************************************************/
static void testmatinvunit_testhpdinv(ae_int_t minn,
ae_int_t maxn,
ae_int_t passcount,
double threshold,
ae_bool* hpderrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix cha;
ae_matrix inva;
ae_matrix invcha;
ae_bool isupper;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t n;
ae_int_t pass;
ae_int_t taskkind;
ae_int_t info;
matinvreport rep;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&cha, 0, sizeof(cha));
memset(&inva, 0, sizeof(inva));
memset(&invcha, 0, sizeof(invcha));
memset(&rep, 0, sizeof(rep));
ae_matrix_init(&a, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&cha, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&inva, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&invcha, 0, 0, DT_COMPLEX, _state, ae_true);
_matinvreport_init(&rep, _state, ae_true);
/*
* General square matrices:
* * test general solvers
* * test least squares solver
*/
for(pass=1; pass<=passcount; pass++)
{
for(n=minn; n<=maxn; n++)
{
isupper = ae_fp_greater(ae_randomreal(_state),0.5);
/*
* ********************************************************
* WELL CONDITIONED TASKS
* ability to find correct solution is tested
* ********************************************************
*
* 1. generate random well conditioned matrix A.
* 2. generate random solution vector xe
* 3. generate right part b=A*xe
* 4. test different methods on original A
*/
hpdmatrixrndcond(n, (double)(1000), &a, _state);
testmatinvunit_cmatrixdrophalf(&a, n, isupper, _state);
testmatinvunit_cmatrixmakeacopy(&a, n, n, &cha, _state);
if( !hpdmatrixcholesky(&cha, n, isupper, _state) )
{
continue;
}
testmatinvunit_cmatrixmakeacopy(&a, n, n, &inva, _state);
testmatinvunit_cmatrixmakeacopy(&cha, n, n, &invcha, _state);
info = 0;
testmatinvunit_unsetrep(&rep, _state);
hpdmatrixinverse(&inva, n, isupper, &info, &rep, _state);
*hpderrors = *hpderrors||!testmatinvunit_hpdmatrixcheckinverse(&a, &inva, isupper, n, threshold, info, &rep, _state);
info = 0;
testmatinvunit_unsetrep(&rep, _state);
hpdmatrixcholeskyinverse(&invcha, n, isupper, &info, &rep, _state);
*hpderrors = *hpderrors||!testmatinvunit_hpdmatrixcheckinverse(&a, &invcha, isupper, n, threshold, info, &rep, _state);
/*
* ********************************************************
* EXACTLY SINGULAR MATRICES
* ability to detect singularity is tested
* ********************************************************
*
* 1. generate different types of singular matrices:
* * zero
* * with zero columns
* * with zero rows
* 2. test different methods
*/
for(taskkind=0; taskkind<=2; taskkind++)
{
testmatinvunit_cunset2d(&a, _state);
if( taskkind==0 )
{
/*
* all zeros
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
}
if( taskkind==1 )
{
/*
* there is zero column
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
k = ae_randominteger(n, _state);
ae_v_cmuld(&a.ptr.pp_complex[0][k], a.stride, ae_v_len(0,n-1), 0);
ae_v_cmuld(&a.ptr.pp_complex[k][0], 1, ae_v_len(0,n-1), 0);
}
if( taskkind==2 )
{
/*
* there is zero row
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
k = ae_randominteger(n, _state);
ae_v_cmuld(&a.ptr.pp_complex[k][0], 1, ae_v_len(0,n-1), 0);
ae_v_cmuld(&a.ptr.pp_complex[0][k], a.stride, ae_v_len(0,n-1), 0);
}
info = 0;
testmatinvunit_unsetrep(&rep, _state);
hpdmatrixcholeskyinverse(&a, n, isupper, &info, &rep, _state);
if( info!=-3&&info!=1 )
{
*hpderrors = ae_true;
}
else
{
*hpderrors = (*hpderrors||ae_fp_less(rep.r1,(double)(0)))||ae_fp_greater(rep.r1,1000*ae_machineepsilon);
*hpderrors = (*hpderrors||ae_fp_less(rep.rinf,(double)(0)))||ae_fp_greater(rep.rinf,1000*ae_machineepsilon);
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Unsets real matrix
*************************************************************************/
static void testmatinvunit_unset2d(/* Real */ ae_matrix* x,
ae_state *_state)
{
ae_matrix_set_length(x, 1, 1, _state);
x->ptr.pp_double[0][0] = 2*ae_randomreal(_state)-1;
}
/*************************************************************************
Unsets real matrix
*************************************************************************/
static void testmatinvunit_cunset2d(/* Complex */ ae_matrix* x,
ae_state *_state)
{
ae_matrix_set_length(x, 1, 1, _state);
x->ptr.pp_complex[0][0] = ae_complex_from_d(2*ae_randomreal(_state)-1);
}
/*************************************************************************
Unsets report
*************************************************************************/
static void testmatinvunit_unsetrep(matinvreport* r, ae_state *_state)
{
r->r1 = (double)(-1);
r->rinf = (double)(-1);
}
ae_bool testhblas(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix ua;
ae_matrix la;
ae_vector x;
ae_vector y1;
ae_vector y2;
ae_vector y3;
ae_int_t n;
ae_int_t maxn;
ae_int_t i;
ae_int_t j;
ae_int_t i1;
ae_int_t i2;
ae_bool waserrors;
double mverr;
double threshold;
ae_complex alpha;
ae_complex v;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&ua, 0, sizeof(ua));
memset(&la, 0, sizeof(la));
memset(&x, 0, sizeof(x));
memset(&y1, 0, sizeof(y1));
memset(&y2, 0, sizeof(y2));
memset(&y3, 0, sizeof(y3));
ae_matrix_init(&a, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&ua, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&la, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&x, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&y1, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&y2, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&y3, 0, DT_COMPLEX, _state, ae_true);
mverr = (double)(0);
waserrors = ae_false;
maxn = 10;
threshold = 1000*ae_machineepsilon;
/*
* Test MV
*/
for(n=2; n<=maxn; n++)
{
ae_matrix_set_length(&a, n+1, n+1, _state);
ae_matrix_set_length(&ua, n+1, n+1, _state);
ae_matrix_set_length(&la, n+1, n+1, _state);
ae_vector_set_length(&x, n+1, _state);
ae_vector_set_length(&y1, n+1, _state);
ae_vector_set_length(&y2, n+1, _state);
ae_vector_set_length(&y3, n+1, _state);
/*
* fill A, UA, LA
*/
for(i=1; i<=n; i++)
{
a.ptr.pp_complex[i][i].x = 2*ae_randomreal(_state)-1;
a.ptr.pp_complex[i][i].y = (double)(0);
for(j=i+1; j<=n; j++)
{
a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
a.ptr.pp_complex[j][i] = ae_c_conj(a.ptr.pp_complex[i][j], _state);
}
}
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
ua.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
for(i=1; i<=n; i++)
{
for(j=i; j<=n; j++)
{
ua.ptr.pp_complex[i][j] = a.ptr.pp_complex[i][j];
}
}
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
la.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
for(i=1; i<=n; i++)
{
for(j=1; j<=i; j++)
{
la.ptr.pp_complex[i][j] = a.ptr.pp_complex[i][j];
}
}
/*
* test on different I1, I2
*/
for(i1=1; i1<=n; i1++)
{
for(i2=i1; i2<=n; i2++)
{
/*
* Fill X, choose Alpha
*/
for(i=1; i<=i2-i1+1; i++)
{
x.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1;
x.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1;
}
alpha.x = 2*ae_randomreal(_state)-1;
alpha.y = 2*ae_randomreal(_state)-1;
/*
* calculate A*x, UA*x, LA*x
*/
for(i=i1; i<=i2; i++)
{
v = ae_v_cdotproduct(&a.ptr.pp_complex[i][i1], 1, "N", &x.ptr.p_complex[1], 1, "N", ae_v_len(i1,i2));
y1.ptr.p_complex[i-i1+1] = ae_c_mul(alpha,v);
}
hermitianmatrixvectormultiply(&ua, ae_true, i1, i2, &x, alpha, &y2, _state);
hermitianmatrixvectormultiply(&la, ae_false, i1, i2, &x, alpha, &y3, _state);
/*
* Calculate error
*/
ae_v_csub(&y2.ptr.p_complex[1], 1, &y1.ptr.p_complex[1], 1, "N", ae_v_len(1,i2-i1+1));
v = ae_v_cdotproduct(&y2.ptr.p_complex[1], 1, "N", &y2.ptr.p_complex[1], 1, "Conj", ae_v_len(1,i2-i1+1));
mverr = ae_maxreal(mverr, ae_sqrt(ae_c_abs(v, _state), _state), _state);
ae_v_csub(&y3.ptr.p_complex[1], 1, &y1.ptr.p_complex[1], 1, "N", ae_v_len(1,i2-i1+1));
v = ae_v_cdotproduct(&y3.ptr.p_complex[1], 1, "N", &y3.ptr.p_complex[1], 1, "Conj", ae_v_len(1,i2-i1+1));
mverr = ae_maxreal(mverr, ae_sqrt(ae_c_abs(v, _state), _state), _state);
}
}
}
/*
* report
*/
waserrors = ae_fp_greater(mverr,threshold);
if( !silent )
{
printf("TESTING HERMITIAN BLAS\n");
printf("MV error: %5.3e\n",
(double)(mverr));
printf("Threshold: %5.3e\n",
(double)(threshold));
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
ae_bool testsblas(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix ua;
ae_matrix la;
ae_vector x;
ae_vector y1;
ae_vector y2;
ae_vector y3;
ae_int_t n;
ae_int_t maxn;
ae_int_t i;
ae_int_t j;
ae_int_t i1;
ae_int_t i2;
ae_bool waserrors;
double mverr;
double threshold;
double alpha;
double v;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&ua, 0, sizeof(ua));
memset(&la, 0, sizeof(la));
memset(&x, 0, sizeof(x));
memset(&y1, 0, sizeof(y1));
memset(&y2, 0, sizeof(y2));
memset(&y3, 0, sizeof(y3));
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ua, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&la, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y3, 0, DT_REAL, _state, ae_true);
mverr = (double)(0);
waserrors = ae_false;
maxn = 10;
threshold = 1000*ae_machineepsilon;
/*
* Test MV
*/
for(n=2; n<=maxn; n++)
{
ae_matrix_set_length(&a, n+1, n+1, _state);
ae_matrix_set_length(&ua, n+1, n+1, _state);
ae_matrix_set_length(&la, n+1, n+1, _state);
ae_vector_set_length(&x, n+1, _state);
ae_vector_set_length(&y1, n+1, _state);
ae_vector_set_length(&y2, n+1, _state);
ae_vector_set_length(&y3, n+1, _state);
/*
* fill A, UA, LA
*/
for(i=1; i<=n; i++)
{
a.ptr.pp_double[i][i] = 2*ae_randomreal(_state)-1;
for(j=i+1; j<=n; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j];
}
}
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
ua.ptr.pp_double[i][j] = (double)(0);
}
}
for(i=1; i<=n; i++)
{
for(j=i; j<=n; j++)
{
ua.ptr.pp_double[i][j] = a.ptr.pp_double[i][j];
}
}
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
la.ptr.pp_double[i][j] = (double)(0);
}
}
for(i=1; i<=n; i++)
{
for(j=1; j<=i; j++)
{
la.ptr.pp_double[i][j] = a.ptr.pp_double[i][j];
}
}
/*
* test on different I1, I2
*/
for(i1=1; i1<=n; i1++)
{
for(i2=i1; i2<=n; i2++)
{
/*
* Fill X, choose Alpha
*/
for(i=1; i<=i2-i1+1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
alpha = 2*ae_randomreal(_state)-1;
/*
* calculate A*x, UA*x, LA*x
*/
for(i=i1; i<=i2; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][i1], 1, &x.ptr.p_double[1], 1, ae_v_len(i1,i2));
y1.ptr.p_double[i-i1+1] = alpha*v;
}
symmetricmatrixvectormultiply(&ua, ae_true, i1, i2, &x, alpha, &y2, _state);
symmetricmatrixvectormultiply(&la, ae_false, i1, i2, &x, alpha, &y3, _state);
/*
* Calculate error
*/
ae_v_sub(&y2.ptr.p_double[1], 1, &y1.ptr.p_double[1], 1, ae_v_len(1,i2-i1+1));
v = ae_v_dotproduct(&y2.ptr.p_double[1], 1, &y2.ptr.p_double[1], 1, ae_v_len(1,i2-i1+1));
mverr = ae_maxreal(mverr, ae_sqrt(v, _state), _state);
ae_v_sub(&y3.ptr.p_double[1], 1, &y1.ptr.p_double[1], 1, ae_v_len(1,i2-i1+1));
v = ae_v_dotproduct(&y3.ptr.p_double[1], 1, &y3.ptr.p_double[1], 1, ae_v_len(1,i2-i1+1));
mverr = ae_maxreal(mverr, ae_sqrt(v, _state), _state);
}
}
}
/*
* report
*/
waserrors = ae_fp_greater(mverr,threshold);
if( !silent )
{
printf("TESTING SYMMETRIC BLAS\n");
printf("MV error: %5.3e\n",
(double)(mverr));
printf("Threshold: %5.3e\n",
(double)(threshold));
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
static double testortfacunit_rmatrixdiff(/* Real */ ae_matrix* a,
/* Real */ ae_matrix* b,
ae_int_t m,
ae_int_t n,
ae_state *_state);
static void testortfacunit_rmatrixmakeacopy(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Real */ ae_matrix* b,
ae_state *_state);
static void testortfacunit_cmatrixmakeacopy(/* Complex */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Complex */ ae_matrix* b,
ae_state *_state);
static void testortfacunit_rmatrixfillsparsea(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double sparcity,
ae_state *_state);
static void testortfacunit_cmatrixfillsparsea(/* Complex */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double sparcity,
ae_state *_state);
static void testortfacunit_internalmatrixmatrixmultiply(/* Real */ ae_matrix* a,
ae_int_t ai1,
ae_int_t ai2,
ae_int_t aj1,
ae_int_t aj2,
ae_bool transa,
/* Real */ ae_matrix* b,
ae_int_t bi1,
ae_int_t bi2,
ae_int_t bj1,
ae_int_t bj2,
ae_bool transb,
/* Real */ ae_matrix* c,
ae_int_t ci1,
ae_int_t ci2,
ae_int_t cj1,
ae_int_t cj2,
ae_state *_state);
static void testortfacunit_testrqrproblem(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double threshold,
ae_bool* qrerrors,
ae_state *_state);
static void testortfacunit_testcqrproblem(/* Complex */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double threshold,
ae_bool* qrerrors,
ae_state *_state);
static void testortfacunit_testrlqproblem(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double threshold,
ae_bool* lqerrors,
ae_state *_state);
static void testortfacunit_testclqproblem(/* Complex */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double threshold,
ae_bool* lqerrors,
ae_state *_state);
static void testortfacunit_testrbdproblem(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double threshold,
ae_bool* bderrors,
ae_state *_state);
static void testortfacunit_testrhessproblem(/* Real */ ae_matrix* a,
ae_int_t n,
double threshold,
ae_bool* hesserrors,
ae_state *_state);
static void testortfacunit_testrtdproblem(/* Real */ ae_matrix* a,
ae_int_t n,
double threshold,
ae_bool* tderrors,
ae_state *_state);
static void testortfacunit_testctdproblem(/* Complex */ ae_matrix* a,
ae_int_t n,
double threshold,
ae_bool* tderrors,
ae_state *_state);
/*************************************************************************
Main unittest subroutine
*************************************************************************/
ae_bool testortfac(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
double threshold;
ae_int_t mx;
ae_matrix ra;
ae_matrix ca;
ae_int_t m;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_bool rqrerrors;
ae_bool rlqerrors;
ae_bool cqrerrors;
ae_bool clqerrors;
ae_bool rbderrors;
ae_bool rhesserrors;
ae_bool rtderrors;
ae_bool ctderrors;
ae_bool waserrors;
hqrndstate rs;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&ra, 0, sizeof(ra));
memset(&ca, 0, sizeof(ca));
memset(&rs, 0, sizeof(rs));
ae_matrix_init(&ra, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ca, 0, 0, DT_COMPLEX, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
waserrors = ae_false;
rqrerrors = ae_false;
rlqerrors = ae_false;
cqrerrors = ae_false;
clqerrors = ae_false;
rbderrors = ae_false;
rhesserrors = ae_false;
rtderrors = ae_false;
ctderrors = ae_false;
threshold = 5*1000*ae_machineepsilon;
/*
* Medium-scale problems with various sparseness profiles
*/
for(mx=1; mx<=3*matrixtilesizea(_state)+1; mx++)
{
/*
* Rectangular factorizations: QR, LQ, bidiagonal
* Matrix types: zero, dense, sparse
*/
n = 1+ae_randominteger(mx, _state);
m = 1+ae_randominteger(mx, _state);
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
n = mx;
}
else
{
m = mx;
}
ae_matrix_set_length(&ra, m, n, _state);
ae_matrix_set_length(&ca, m, n, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
ra.ptr.pp_double[i][j] = (double)(0);
ca.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
testortfacunit_testrqrproblem(&ra, m, n, threshold, &rqrerrors, _state);
testortfacunit_testrlqproblem(&ra, m, n, threshold, &rlqerrors, _state);
testortfacunit_testcqrproblem(&ca, m, n, threshold, &cqrerrors, _state);
testortfacunit_testclqproblem(&ca, m, n, threshold, &clqerrors, _state);
testortfacunit_testrbdproblem(&ra, m, n, threshold, &rbderrors, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
ra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
ca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
ca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
testortfacunit_testrqrproblem(&ra, m, n, threshold, &rqrerrors, _state);
testortfacunit_testrlqproblem(&ra, m, n, threshold, &rlqerrors, _state);
testortfacunit_testcqrproblem(&ca, m, n, threshold, &cqrerrors, _state);
testortfacunit_testclqproblem(&ca, m, n, threshold, &clqerrors, _state);
testortfacunit_testrbdproblem(&ra, m, n, threshold, &rbderrors, _state);
testortfacunit_rmatrixfillsparsea(&ra, m, n, 0.95, _state);
testortfacunit_cmatrixfillsparsea(&ca, m, n, 0.95, _state);
testortfacunit_testrqrproblem(&ra, m, n, threshold, &rqrerrors, _state);
testortfacunit_testrlqproblem(&ra, m, n, threshold, &rlqerrors, _state);
testortfacunit_testcqrproblem(&ca, m, n, threshold, &cqrerrors, _state);
testortfacunit_testclqproblem(&ca, m, n, threshold, &clqerrors, _state);
testortfacunit_testrbdproblem(&ra, m, n, threshold, &rbderrors, _state);
/*
* Square factorizations: Hessenberg, tridiagonal
* Matrix types: zero, dense, sparse
*/
ae_matrix_set_length(&ra, mx, mx, _state);
ae_matrix_set_length(&ca, mx, mx, _state);
for(i=0; i<=mx-1; i++)
{
for(j=0; j<=mx-1; j++)
{
ra.ptr.pp_double[i][j] = (double)(0);
ca.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
testortfacunit_testrhessproblem(&ra, mx, threshold, &rhesserrors, _state);
for(i=0; i<=mx-1; i++)
{
for(j=0; j<=mx-1; j++)
{
ra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
ca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
ca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
testortfacunit_testrhessproblem(&ra, mx, threshold, &rhesserrors, _state);
testortfacunit_rmatrixfillsparsea(&ra, mx, mx, 0.95, _state);
testortfacunit_cmatrixfillsparsea(&ca, mx, mx, 0.95, _state);
testortfacunit_testrhessproblem(&ra, mx, threshold, &rhesserrors, _state);
/*
* Symetric factorizations: tridiagonal
* Matrix types: zero, dense, sparse
*/
ae_matrix_set_length(&ra, mx, mx, _state);
ae_matrix_set_length(&ca, mx, mx, _state);
for(i=0; i<=mx-1; i++)
{
for(j=0; j<=mx-1; j++)
{
ra.ptr.pp_double[i][j] = (double)(0);
ca.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
testortfacunit_testrtdproblem(&ra, mx, threshold, &rtderrors, _state);
testortfacunit_testctdproblem(&ca, mx, threshold, &ctderrors, _state);
for(i=0; i<=mx-1; i++)
{
for(j=i; j<=mx-1; j++)
{
ra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
ca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
ca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
ra.ptr.pp_double[j][i] = ra.ptr.pp_double[i][j];
ca.ptr.pp_complex[j][i] = ae_c_conj(ca.ptr.pp_complex[i][j], _state);
}
}
for(i=0; i<=mx-1; i++)
{
ca.ptr.pp_complex[i][i] = ae_complex_from_d(2*ae_randomreal(_state)-1);
}
testortfacunit_testrtdproblem(&ra, mx, threshold, &rtderrors, _state);
testortfacunit_testctdproblem(&ca, mx, threshold, &ctderrors, _state);
testortfacunit_rmatrixfillsparsea(&ra, mx, mx, 0.95, _state);
testortfacunit_cmatrixfillsparsea(&ca, mx, mx, 0.95, _state);
for(i=0; i<=mx-1; i++)
{
for(j=i; j<=mx-1; j++)
{
ra.ptr.pp_double[j][i] = ra.ptr.pp_double[i][j];
ca.ptr.pp_complex[j][i] = ae_c_conj(ca.ptr.pp_complex[i][j], _state);
}
}
for(i=0; i<=mx-1; i++)
{
ca.ptr.pp_complex[i][i] = ae_complex_from_d(2*ae_randomreal(_state)-1);
}
testortfacunit_testrtdproblem(&ra, mx, threshold, &rtderrors, _state);
testortfacunit_testctdproblem(&ca, mx, threshold, &ctderrors, _state);
}
/*
* Large-scale tests
*/
for(mx=4*matrixtilesizeb(_state); mx<=4*matrixtilesizeb(_state); mx++)
{
/*
* Rectangular factorizations: QR, LQ, bidiagonal
* Matrix types: dense
*/
n = 1+ae_randominteger(mx, _state);
m = 1+ae_randominteger(mx, _state);
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
n = mx;
}
else
{
m = mx;
}
ae_matrix_set_length(&ra, m, n, _state);
ae_matrix_set_length(&ca, m, n, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
ra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
ca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
ca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
testortfacunit_testrqrproblem(&ra, m, n, threshold, &rqrerrors, _state);
testortfacunit_testrlqproblem(&ra, m, n, threshold, &rlqerrors, _state);
testortfacunit_testcqrproblem(&ca, m, n, threshold, &cqrerrors, _state);
testortfacunit_testclqproblem(&ca, m, n, threshold, &clqerrors, _state);
testortfacunit_testrbdproblem(&ra, m, n, threshold, &rbderrors, _state);
/*
* Square factorizations: Hessenberg, tridiagonal
* Matrix types: dense
*/
ae_matrix_set_length(&ra, mx, mx, _state);
ae_matrix_set_length(&ca, mx, mx, _state);
for(i=0; i<=mx-1; i++)
{
for(j=0; j<=mx-1; j++)
{
ra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
ca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
ca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
testortfacunit_testrhessproblem(&ra, mx, threshold, &rhesserrors, _state);
/*
* Symetric factorizations: tridiagonal
* Matrix types: dense
*/
ae_matrix_set_length(&ra, mx, mx, _state);
ae_matrix_set_length(&ca, mx, mx, _state);
for(i=0; i<=mx-1; i++)
{
for(j=i; j<=mx-1; j++)
{
ra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
ca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
ca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
ra.ptr.pp_double[j][i] = ra.ptr.pp_double[i][j];
ca.ptr.pp_complex[j][i] = ae_c_conj(ca.ptr.pp_complex[i][j], _state);
}
}
for(i=0; i<=mx-1; i++)
{
ca.ptr.pp_complex[i][i] = ae_complex_from_d(2*ae_randomreal(_state)-1);
}
testortfacunit_testrtdproblem(&ra, mx, threshold, &rtderrors, _state);
testortfacunit_testctdproblem(&ca, mx, threshold, &ctderrors, _state);
}
/*
* report
*/
waserrors = ((((((rqrerrors||rlqerrors)||cqrerrors)||clqerrors)||rbderrors)||rhesserrors)||rtderrors)||ctderrors;
if( !silent )
{
printf("TESTING ORTFAC UNIT\n");
printf("RQR ERRORS: ");
if( !rqrerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("RLQ ERRORS: ");
if( !rlqerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("CQR ERRORS: ");
if( !cqrerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("CLQ ERRORS: ");
if( !clqerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("RBD ERRORS: ");
if( !rbderrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("RHESS ERRORS: ");
if( !rhesserrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("RTD ERRORS: ");
if( !rtderrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("CTD ERRORS: ");
if( !ctderrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Diff
*************************************************************************/
static double testortfacunit_rmatrixdiff(/* Real */ ae_matrix* a,
/* Real */ ae_matrix* b,
ae_int_t m,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
double result;
result = (double)(0);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
result = ae_maxreal(result, ae_fabs(b->ptr.pp_double[i][j]-a->ptr.pp_double[i][j], _state), _state);
}
}
return result;
}
/*************************************************************************
Copy
*************************************************************************/
static void testortfacunit_rmatrixmakeacopy(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Real */ ae_matrix* b,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_matrix_clear(b);
ae_matrix_set_length(b, m-1+1, n-1+1, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
b->ptr.pp_double[i][j] = a->ptr.pp_double[i][j];
}
}
}
/*************************************************************************
Copy
*************************************************************************/
static void testortfacunit_cmatrixmakeacopy(/* Complex */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Complex */ ae_matrix* b,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_matrix_clear(b);
ae_matrix_set_length(b, m-1+1, n-1+1, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
b->ptr.pp_complex[i][j] = a->ptr.pp_complex[i][j];
}
}
}
/*************************************************************************
Sparse fill
*************************************************************************/
static void testortfacunit_rmatrixfillsparsea(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double sparcity,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_greater_eq(ae_randomreal(_state),sparcity) )
{
a->ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
else
{
a->ptr.pp_double[i][j] = (double)(0);
}
}
}
}
/*************************************************************************
Sparse fill
*************************************************************************/
static void testortfacunit_cmatrixfillsparsea(/* Complex */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double sparcity,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_greater_eq(ae_randomreal(_state),sparcity) )
{
a->ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
a->ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
else
{
a->ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
}
}
/*************************************************************************
Matrix multiplication
*************************************************************************/
static void testortfacunit_internalmatrixmatrixmultiply(/* Real */ ae_matrix* a,
ae_int_t ai1,
ae_int_t ai2,
ae_int_t aj1,
ae_int_t aj2,
ae_bool transa,
/* Real */ ae_matrix* b,
ae_int_t bi1,
ae_int_t bi2,
ae_int_t bj1,
ae_int_t bj2,
ae_bool transb,
/* Real */ ae_matrix* c,
ae_int_t ci1,
ae_int_t ci2,
ae_int_t cj1,
ae_int_t cj2,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t arows;
ae_int_t acols;
ae_int_t brows;
ae_int_t bcols;
ae_int_t crows;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t l;
ae_int_t r;
double v;
ae_vector work;
double beta;
double alpha;
ae_frame_make(_state, &_frame_block);
memset(&work, 0, sizeof(work));
ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
/*
* Pre-setup
*/
k = ae_maxint(ai2-ai1+1, aj2-aj1+1, _state);
k = ae_maxint(k, bi2-bi1+1, _state);
k = ae_maxint(k, bj2-bj1+1, _state);
ae_vector_set_length(&work, k+1, _state);
beta = (double)(0);
alpha = (double)(1);
/*
* Setup
*/
if( !transa )
{
arows = ai2-ai1+1;
acols = aj2-aj1+1;
}
else
{
arows = aj2-aj1+1;
acols = ai2-ai1+1;
}
if( !transb )
{
brows = bi2-bi1+1;
bcols = bj2-bj1+1;
}
else
{
brows = bj2-bj1+1;
bcols = bi2-bi1+1;
}
ae_assert(acols==brows, "MatrixMatrixMultiply: incorrect matrix sizes!", _state);
if( ((arows<=0||acols<=0)||brows<=0)||bcols<=0 )
{
ae_frame_leave(_state);
return;
}
crows = arows;
/*
* Test WORK
*/
i = ae_maxint(arows, acols, _state);
i = ae_maxint(brows, i, _state);
i = ae_maxint(i, bcols, _state);
work.ptr.p_double[1] = (double)(0);
work.ptr.p_double[i] = (double)(0);
/*
* Prepare C
*/
if( ae_fp_eq(beta,(double)(0)) )
{
for(i=ci1; i<=ci2; i++)
{
for(j=cj1; j<=cj2; j++)
{
c->ptr.pp_double[i][j] = (double)(0);
}
}
}
else
{
for(i=ci1; i<=ci2; i++)
{
ae_v_muld(&c->ptr.pp_double[i][cj1], 1, ae_v_len(cj1,cj2), beta);
}
}
/*
* A*B
*/
if( !transa&&!transb )
{
for(l=ai1; l<=ai2; l++)
{
for(r=bi1; r<=bi2; r++)
{
v = alpha*a->ptr.pp_double[l][aj1+r-bi1];
k = ci1+l-ai1;
ae_v_addd(&c->ptr.pp_double[k][cj1], 1, &b->ptr.pp_double[r][bj1], 1, ae_v_len(cj1,cj2), v);
}
}
ae_frame_leave(_state);
return;
}
/*
* A*B'
*/
if( !transa&&transb )
{
if( arows*acolsptr.pp_double[l][aj1], 1, &b->ptr.pp_double[r][bj1], 1, ae_v_len(aj1,aj2));
c->ptr.pp_double[ci1+l-ai1][cj1+r-bi1] = c->ptr.pp_double[ci1+l-ai1][cj1+r-bi1]+alpha*v;
}
}
ae_frame_leave(_state);
return;
}
else
{
for(l=ai1; l<=ai2; l++)
{
for(r=bi1; r<=bi2; r++)
{
v = ae_v_dotproduct(&a->ptr.pp_double[l][aj1], 1, &b->ptr.pp_double[r][bj1], 1, ae_v_len(aj1,aj2));
c->ptr.pp_double[ci1+l-ai1][cj1+r-bi1] = c->ptr.pp_double[ci1+l-ai1][cj1+r-bi1]+alpha*v;
}
}
ae_frame_leave(_state);
return;
}
}
/*
* A'*B
*/
if( transa&&!transb )
{
for(l=aj1; l<=aj2; l++)
{
for(r=bi1; r<=bi2; r++)
{
v = alpha*a->ptr.pp_double[ai1+r-bi1][l];
k = ci1+l-aj1;
ae_v_addd(&c->ptr.pp_double[k][cj1], 1, &b->ptr.pp_double[r][bj1], 1, ae_v_len(cj1,cj2), v);
}
}
ae_frame_leave(_state);
return;
}
/*
* A'*B'
*/
if( transa&&transb )
{
if( arows*acolsptr.pp_double[r][bj1+l-ai1];
k = cj1+r-bi1;
ae_v_addd(&work.ptr.p_double[1], 1, &a->ptr.pp_double[l][aj1], 1, ae_v_len(1,crows), v);
}
ae_v_add(&c->ptr.pp_double[ci1][k], c->stride, &work.ptr.p_double[1], 1, ae_v_len(ci1,ci2));
}
ae_frame_leave(_state);
return;
}
else
{
for(l=aj1; l<=aj2; l++)
{
k = ai2-ai1+1;
ae_v_move(&work.ptr.p_double[1], 1, &a->ptr.pp_double[ai1][l], a->stride, ae_v_len(1,k));
for(r=bi1; r<=bi2; r++)
{
v = ae_v_dotproduct(&work.ptr.p_double[1], 1, &b->ptr.pp_double[r][bj1], 1, ae_v_len(1,k));
c->ptr.pp_double[ci1+l-aj1][cj1+r-bi1] = c->ptr.pp_double[ci1+l-aj1][cj1+r-bi1]+alpha*v;
}
}
ae_frame_leave(_state);
return;
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Problem testing
*************************************************************************/
static void testortfacunit_testrqrproblem(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double threshold,
ae_bool* qrerrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_matrix b;
ae_vector taub;
ae_matrix q;
ae_matrix r;
ae_matrix q2;
double v;
ae_frame_make(_state, &_frame_block);
memset(&b, 0, sizeof(b));
memset(&taub, 0, sizeof(taub));
memset(&q, 0, sizeof(q));
memset(&r, 0, sizeof(r));
memset(&q2, 0, sizeof(q2));
ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&taub, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&r, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&q2, 0, 0, DT_REAL, _state, ae_true);
/*
* Test decompose-and-unpack error
*/
testortfacunit_rmatrixmakeacopy(a, m, n, &b, _state);
rmatrixqr(&b, m, n, &taub, _state);
rmatrixqrunpackq(&b, m, n, &taub, m, &q, _state);
rmatrixqrunpackr(&b, m, n, &r, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &r.ptr.pp_double[0][j], r.stride, ae_v_len(0,m-1));
*qrerrors = *qrerrors||ae_fp_greater(ae_fabs(v-a->ptr.pp_double[i][j], _state),threshold);
}
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=ae_minint(i, n-1, _state)-1; j++)
{
*qrerrors = *qrerrors||ae_fp_neq(r.ptr.pp_double[i][j],(double)(0));
}
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=m-1; j++)
{
v = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &q.ptr.pp_double[j][0], 1, ae_v_len(0,m-1));
if( i==j )
{
v = v-1;
}
*qrerrors = *qrerrors||ae_fp_greater_eq(ae_fabs(v, _state),threshold);
}
}
/*
* Test for other errors
*/
k = 1+ae_randominteger(m, _state);
rmatrixqrunpackq(&b, m, n, &taub, k, &q2, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=k-1; j++)
{
*qrerrors = *qrerrors||ae_fp_greater(ae_fabs(q2.ptr.pp_double[i][j]-q.ptr.pp_double[i][j], _state),10*ae_machineepsilon);
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Problem testing
*************************************************************************/
static void testortfacunit_testcqrproblem(/* Complex */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double threshold,
ae_bool* qrerrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_matrix b;
ae_vector taub;
ae_matrix q;
ae_matrix r;
ae_matrix q2;
ae_complex v;
ae_frame_make(_state, &_frame_block);
memset(&b, 0, sizeof(b));
memset(&taub, 0, sizeof(taub));
memset(&q, 0, sizeof(q));
memset(&r, 0, sizeof(r));
memset(&q2, 0, sizeof(q2));
ae_matrix_init(&b, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&taub, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&q, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&r, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&q2, 0, 0, DT_COMPLEX, _state, ae_true);
/*
* Test decompose-and-unpack error
*/
testortfacunit_cmatrixmakeacopy(a, m, n, &b, _state);
cmatrixqr(&b, m, n, &taub, _state);
cmatrixqrunpackq(&b, m, n, &taub, m, &q, _state);
cmatrixqrunpackr(&b, m, n, &r, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_cdotproduct(&q.ptr.pp_complex[i][0], 1, "N", &r.ptr.pp_complex[0][j], r.stride, "N", ae_v_len(0,m-1));
*qrerrors = *qrerrors||ae_fp_greater(ae_c_abs(ae_c_sub(v,a->ptr.pp_complex[i][j]), _state),threshold);
}
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=ae_minint(i, n-1, _state)-1; j++)
{
*qrerrors = *qrerrors||ae_c_neq_d(r.ptr.pp_complex[i][j],(double)(0));
}
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=m-1; j++)
{
v = ae_v_cdotproduct(&q.ptr.pp_complex[i][0], 1, "N", &q.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,m-1));
if( i==j )
{
v = ae_c_sub_d(v,1);
}
*qrerrors = *qrerrors||ae_fp_greater_eq(ae_c_abs(v, _state),threshold);
}
}
/*
* Test for other errors
*/
k = 1+ae_randominteger(m, _state);
cmatrixqrunpackq(&b, m, n, &taub, k, &q2, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=k-1; j++)
{
*qrerrors = *qrerrors||ae_fp_greater(ae_c_abs(ae_c_sub(q2.ptr.pp_complex[i][j],q.ptr.pp_complex[i][j]), _state),10*ae_machineepsilon);
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Problem testing
*************************************************************************/
static void testortfacunit_testrlqproblem(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double threshold,
ae_bool* lqerrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_matrix b;
ae_vector taub;
ae_matrix q;
ae_matrix l;
ae_matrix q2;
double v;
ae_frame_make(_state, &_frame_block);
memset(&b, 0, sizeof(b));
memset(&taub, 0, sizeof(taub));
memset(&q, 0, sizeof(q));
memset(&l, 0, sizeof(l));
memset(&q2, 0, sizeof(q2));
ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&taub, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&l, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&q2, 0, 0, DT_REAL, _state, ae_true);
/*
* Test decompose-and-unpack error
*/
testortfacunit_rmatrixmakeacopy(a, m, n, &b, _state);
rmatrixlq(&b, m, n, &taub, _state);
rmatrixlqunpackq(&b, m, n, &taub, n, &q, _state);
rmatrixlqunpackl(&b, m, n, &l, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&l.ptr.pp_double[i][0], 1, &q.ptr.pp_double[0][j], q.stride, ae_v_len(0,n-1));
*lqerrors = *lqerrors||ae_fp_greater_eq(ae_fabs(v-a->ptr.pp_double[i][j], _state),threshold);
}
}
for(i=0; i<=m-1; i++)
{
for(j=ae_minint(i, n-1, _state)+1; j<=n-1; j++)
{
*lqerrors = *lqerrors||ae_fp_neq(l.ptr.pp_double[i][j],(double)(0));
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &q.ptr.pp_double[j][0], 1, ae_v_len(0,n-1));
if( i==j )
{
v = v-1;
}
*lqerrors = *lqerrors||ae_fp_greater_eq(ae_fabs(v, _state),threshold);
}
}
/*
* Test for other errors
*/
k = 1+ae_randominteger(n, _state);
rmatrixlqunpackq(&b, m, n, &taub, k, &q2, _state);
for(i=0; i<=k-1; i++)
{
for(j=0; j<=n-1; j++)
{
*lqerrors = *lqerrors||ae_fp_greater(ae_fabs(q2.ptr.pp_double[i][j]-q.ptr.pp_double[i][j], _state),10*ae_machineepsilon);
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Problem testing
*************************************************************************/
static void testortfacunit_testclqproblem(/* Complex */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double threshold,
ae_bool* lqerrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_matrix b;
ae_vector taub;
ae_matrix q;
ae_matrix l;
ae_matrix q2;
ae_complex v;
ae_frame_make(_state, &_frame_block);
memset(&b, 0, sizeof(b));
memset(&taub, 0, sizeof(taub));
memset(&q, 0, sizeof(q));
memset(&l, 0, sizeof(l));
memset(&q2, 0, sizeof(q2));
ae_matrix_init(&b, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&taub, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&q, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&l, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&q2, 0, 0, DT_COMPLEX, _state, ae_true);
/*
* Test decompose-and-unpack error
*/
testortfacunit_cmatrixmakeacopy(a, m, n, &b, _state);
cmatrixlq(&b, m, n, &taub, _state);
cmatrixlqunpackq(&b, m, n, &taub, n, &q, _state);
cmatrixlqunpackl(&b, m, n, &l, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_cdotproduct(&l.ptr.pp_complex[i][0], 1, "N", &q.ptr.pp_complex[0][j], q.stride, "N", ae_v_len(0,n-1));
*lqerrors = *lqerrors||ae_fp_greater_eq(ae_c_abs(ae_c_sub(v,a->ptr.pp_complex[i][j]), _state),threshold);
}
}
for(i=0; i<=m-1; i++)
{
for(j=ae_minint(i, n-1, _state)+1; j<=n-1; j++)
{
*lqerrors = *lqerrors||ae_c_neq_d(l.ptr.pp_complex[i][j],(double)(0));
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_cdotproduct(&q.ptr.pp_complex[i][0], 1, "N", &q.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,n-1));
if( i==j )
{
v = ae_c_sub_d(v,1);
}
*lqerrors = *lqerrors||ae_fp_greater_eq(ae_c_abs(v, _state),threshold);
}
}
/*
* Test for other errors
*/
k = 1+ae_randominteger(n, _state);
cmatrixlqunpackq(&b, m, n, &taub, k, &q2, _state);
for(i=0; i<=k-1; i++)
{
for(j=0; j<=n-1; j++)
{
*lqerrors = *lqerrors||ae_fp_greater(ae_c_abs(ae_c_sub(q2.ptr.pp_complex[i][j],q.ptr.pp_complex[i][j]), _state),10*ae_machineepsilon);
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Problem testing
*************************************************************************/
static void testortfacunit_testrbdproblem(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double threshold,
ae_bool* bderrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_matrix t;
ae_matrix pt;
ae_matrix q;
ae_matrix r;
ae_matrix bd;
ae_matrix x;
ae_matrix r1;
ae_matrix r2;
ae_vector taup;
ae_vector tauq;
ae_vector d;
ae_vector e;
ae_bool up;
double v;
ae_int_t mtsize;
ae_frame_make(_state, &_frame_block);
memset(&t, 0, sizeof(t));
memset(&pt, 0, sizeof(pt));
memset(&q, 0, sizeof(q));
memset(&r, 0, sizeof(r));
memset(&bd, 0, sizeof(bd));
memset(&x, 0, sizeof(x));
memset(&r1, 0, sizeof(r1));
memset(&r2, 0, sizeof(r2));
memset(&taup, 0, sizeof(taup));
memset(&tauq, 0, sizeof(tauq));
memset(&d, 0, sizeof(d));
memset(&e, 0, sizeof(e));
ae_matrix_init(&t, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&pt, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&r, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&bd, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&x, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&r1, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&r2, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&taup, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tauq, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&e, 0, DT_REAL, _state, ae_true);
/*
* Bidiagonal decomposition error
*/
testortfacunit_rmatrixmakeacopy(a, m, n, &t, _state);
rmatrixbd(&t, m, n, &tauq, &taup, _state);
rmatrixbdunpackq(&t, m, n, &tauq, m, &q, _state);
rmatrixbdunpackpt(&t, m, n, &taup, n, &pt, _state);
rmatrixbdunpackdiagonals(&t, m, n, &up, &d, &e, _state);
ae_matrix_set_length(&bd, m, n, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
bd.ptr.pp_double[i][j] = (double)(0);
}
}
for(i=0; i<=ae_minint(m, n, _state)-1; i++)
{
bd.ptr.pp_double[i][i] = d.ptr.p_double[i];
}
if( up )
{
for(i=0; i<=ae_minint(m, n, _state)-2; i++)
{
bd.ptr.pp_double[i][i+1] = e.ptr.p_double[i];
}
}
else
{
for(i=0; i<=ae_minint(m, n, _state)-2; i++)
{
bd.ptr.pp_double[i+1][i] = e.ptr.p_double[i];
}
}
ae_matrix_set_length(&r, m, n, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &bd.ptr.pp_double[0][j], bd.stride, ae_v_len(0,m-1));
r.ptr.pp_double[i][j] = v;
}
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&r.ptr.pp_double[i][0], 1, &pt.ptr.pp_double[0][j], pt.stride, ae_v_len(0,n-1));
*bderrors = *bderrors||ae_fp_greater(ae_fabs(v-a->ptr.pp_double[i][j], _state),threshold);
}
}
/*
* Orthogonality test for Q/PT
*/
for(i=0; i<=m-1; i++)
{
for(j=0; j<=m-1; j++)
{
v = ae_v_dotproduct(&q.ptr.pp_double[0][i], q.stride, &q.ptr.pp_double[0][j], q.stride, ae_v_len(0,m-1));
if( i==j )
{
*bderrors = *bderrors||ae_fp_greater(ae_fabs(v-1, _state),threshold);
}
else
{
*bderrors = *bderrors||ae_fp_greater(ae_fabs(v, _state),threshold);
}
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&pt.ptr.pp_double[i][0], 1, &pt.ptr.pp_double[j][0], 1, ae_v_len(0,n-1));
if( i==j )
{
*bderrors = *bderrors||ae_fp_greater(ae_fabs(v-1, _state),threshold);
}
else
{
*bderrors = *bderrors||ae_fp_greater(ae_fabs(v, _state),threshold);
}
}
}
/*
* Partial unpacking test
*/
k = 1+ae_randominteger(m, _state);
rmatrixbdunpackq(&t, m, n, &tauq, k, &r, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=k-1; j++)
{
*bderrors = *bderrors||ae_fp_greater(ae_fabs(r.ptr.pp_double[i][j]-q.ptr.pp_double[i][j], _state),10*ae_machineepsilon);
}
}
k = 1+ae_randominteger(n, _state);
rmatrixbdunpackpt(&t, m, n, &taup, k, &r, _state);
for(i=0; i<=k-1; i++)
{
for(j=0; j<=n-1; j++)
{
*bderrors = *bderrors||ae_fp_greater(ae_fabs(r.ptr.pp_double[i][j]-pt.ptr.pp_double[i][j], _state),10*ae_machineepsilon);
}
}
/*
* Multiplication test
*/
ae_matrix_set_length(&x, ae_maxint(m, n, _state)-1+1, ae_maxint(m, n, _state)-1+1, _state);
ae_matrix_set_length(&r, ae_maxint(m, n, _state)-1+1, ae_maxint(m, n, _state)-1+1, _state);
ae_matrix_set_length(&r1, ae_maxint(m, n, _state)-1+1, ae_maxint(m, n, _state)-1+1, _state);
ae_matrix_set_length(&r2, ae_maxint(m, n, _state)-1+1, ae_maxint(m, n, _state)-1+1, _state);
for(i=0; i<=ae_maxint(m, n, _state)-1; i++)
{
for(j=0; j<=ae_maxint(m, n, _state)-1; j++)
{
x.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
mtsize = 1+ae_randominteger(ae_maxint(m, n, _state), _state);
testortfacunit_rmatrixmakeacopy(&x, mtsize, m, &r, _state);
testortfacunit_internalmatrixmatrixmultiply(&r, 0, mtsize-1, 0, m-1, ae_false, &q, 0, m-1, 0, m-1, ae_false, &r1, 0, mtsize-1, 0, m-1, _state);
testortfacunit_rmatrixmakeacopy(&x, mtsize, m, &r2, _state);
rmatrixbdmultiplybyq(&t, m, n, &tauq, &r2, mtsize, m, ae_true, ae_false, _state);
*bderrors = *bderrors||ae_fp_greater(testortfacunit_rmatrixdiff(&r1, &r2, mtsize, m, _state),threshold);
testortfacunit_rmatrixmakeacopy(&x, mtsize, m, &r, _state);
testortfacunit_internalmatrixmatrixmultiply(&r, 0, mtsize-1, 0, m-1, ae_false, &q, 0, m-1, 0, m-1, ae_true, &r1, 0, mtsize-1, 0, m-1, _state);
testortfacunit_rmatrixmakeacopy(&x, mtsize, m, &r2, _state);
rmatrixbdmultiplybyq(&t, m, n, &tauq, &r2, mtsize, m, ae_true, ae_true, _state);
*bderrors = *bderrors||ae_fp_greater(testortfacunit_rmatrixdiff(&r1, &r2, mtsize, m, _state),threshold);
testortfacunit_rmatrixmakeacopy(&x, m, mtsize, &r, _state);
testortfacunit_internalmatrixmatrixmultiply(&q, 0, m-1, 0, m-1, ae_false, &r, 0, m-1, 0, mtsize-1, ae_false, &r1, 0, m-1, 0, mtsize-1, _state);
testortfacunit_rmatrixmakeacopy(&x, m, mtsize, &r2, _state);
rmatrixbdmultiplybyq(&t, m, n, &tauq, &r2, m, mtsize, ae_false, ae_false, _state);
*bderrors = *bderrors||ae_fp_greater(testortfacunit_rmatrixdiff(&r1, &r2, m, mtsize, _state),threshold);
testortfacunit_rmatrixmakeacopy(&x, m, mtsize, &r, _state);
testortfacunit_internalmatrixmatrixmultiply(&q, 0, m-1, 0, m-1, ae_true, &r, 0, m-1, 0, mtsize-1, ae_false, &r1, 0, m-1, 0, mtsize-1, _state);
testortfacunit_rmatrixmakeacopy(&x, m, mtsize, &r2, _state);
rmatrixbdmultiplybyq(&t, m, n, &tauq, &r2, m, mtsize, ae_false, ae_true, _state);
*bderrors = *bderrors||ae_fp_greater(testortfacunit_rmatrixdiff(&r1, &r2, m, mtsize, _state),threshold);
testortfacunit_rmatrixmakeacopy(&x, mtsize, n, &r, _state);
testortfacunit_internalmatrixmatrixmultiply(&r, 0, mtsize-1, 0, n-1, ae_false, &pt, 0, n-1, 0, n-1, ae_true, &r1, 0, mtsize-1, 0, n-1, _state);
testortfacunit_rmatrixmakeacopy(&x, mtsize, n, &r2, _state);
rmatrixbdmultiplybyp(&t, m, n, &taup, &r2, mtsize, n, ae_true, ae_false, _state);
*bderrors = *bderrors||ae_fp_greater(testortfacunit_rmatrixdiff(&r1, &r2, mtsize, n, _state),threshold);
testortfacunit_rmatrixmakeacopy(&x, mtsize, n, &r, _state);
testortfacunit_internalmatrixmatrixmultiply(&r, 0, mtsize-1, 0, n-1, ae_false, &pt, 0, n-1, 0, n-1, ae_false, &r1, 0, mtsize-1, 0, n-1, _state);
testortfacunit_rmatrixmakeacopy(&x, mtsize, n, &r2, _state);
rmatrixbdmultiplybyp(&t, m, n, &taup, &r2, mtsize, n, ae_true, ae_true, _state);
*bderrors = *bderrors||ae_fp_greater(testortfacunit_rmatrixdiff(&r1, &r2, mtsize, n, _state),threshold);
testortfacunit_rmatrixmakeacopy(&x, n, mtsize, &r, _state);
testortfacunit_internalmatrixmatrixmultiply(&pt, 0, n-1, 0, n-1, ae_true, &r, 0, n-1, 0, mtsize-1, ae_false, &r1, 0, n-1, 0, mtsize-1, _state);
testortfacunit_rmatrixmakeacopy(&x, n, mtsize, &r2, _state);
rmatrixbdmultiplybyp(&t, m, n, &taup, &r2, n, mtsize, ae_false, ae_false, _state);
*bderrors = *bderrors||ae_fp_greater(testortfacunit_rmatrixdiff(&r1, &r2, n, mtsize, _state),threshold);
testortfacunit_rmatrixmakeacopy(&x, n, mtsize, &r, _state);
testortfacunit_internalmatrixmatrixmultiply(&pt, 0, n-1, 0, n-1, ae_false, &r, 0, n-1, 0, mtsize-1, ae_false, &r1, 0, n-1, 0, mtsize-1, _state);
testortfacunit_rmatrixmakeacopy(&x, n, mtsize, &r2, _state);
rmatrixbdmultiplybyp(&t, m, n, &taup, &r2, n, mtsize, ae_false, ae_true, _state);
*bderrors = *bderrors||ae_fp_greater(testortfacunit_rmatrixdiff(&r1, &r2, n, mtsize, _state),threshold);
ae_frame_leave(_state);
}
/*************************************************************************
Problem testing
*************************************************************************/
static void testortfacunit_testrhessproblem(/* Real */ ae_matrix* a,
ae_int_t n,
double threshold,
ae_bool* hesserrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix b;
ae_matrix h;
ae_matrix q;
ae_matrix t1;
ae_matrix t2;
ae_vector tau;
ae_int_t i;
ae_int_t j;
double v;
ae_frame_make(_state, &_frame_block);
memset(&b, 0, sizeof(b));
memset(&h, 0, sizeof(h));
memset(&q, 0, sizeof(q));
memset(&t1, 0, sizeof(t1));
memset(&t2, 0, sizeof(t2));
memset(&tau, 0, sizeof(tau));
ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&h, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&t1, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&t2, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tau, 0, DT_REAL, _state, ae_true);
testortfacunit_rmatrixmakeacopy(a, n, n, &b, _state);
/*
* Decomposition
*/
rmatrixhessenberg(&b, n, &tau, _state);
rmatrixhessenbergunpackq(&b, n, &tau, &q, _state);
rmatrixhessenbergunpackh(&b, n, &h, _state);
/*
* Matrix properties
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&q.ptr.pp_double[0][i], q.stride, &q.ptr.pp_double[0][j], q.stride, ae_v_len(0,n-1));
if( i==j )
{
v = v-1;
}
*hesserrors = *hesserrors||ae_fp_greater(ae_fabs(v, _state),threshold);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=i-2; j++)
{
*hesserrors = *hesserrors||ae_fp_neq(h.ptr.pp_double[i][j],(double)(0));
}
}
/*
* Decomposition error
*/
ae_matrix_set_length(&t1, n, n, _state);
ae_matrix_set_length(&t2, n, n, _state);
testortfacunit_internalmatrixmatrixmultiply(&q, 0, n-1, 0, n-1, ae_false, &h, 0, n-1, 0, n-1, ae_false, &t1, 0, n-1, 0, n-1, _state);
testortfacunit_internalmatrixmatrixmultiply(&t1, 0, n-1, 0, n-1, ae_false, &q, 0, n-1, 0, n-1, ae_true, &t2, 0, n-1, 0, n-1, _state);
*hesserrors = *hesserrors||ae_fp_greater(testortfacunit_rmatrixdiff(&t2, a, n, n, _state),threshold);
ae_frame_leave(_state);
}
/*************************************************************************
Tridiagonal tester
*************************************************************************/
static void testortfacunit_testrtdproblem(/* Real */ ae_matrix* a,
ae_int_t n,
double threshold,
ae_bool* tderrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_matrix ua;
ae_matrix la;
ae_matrix t;
ae_matrix q;
ae_matrix t2;
ae_matrix t3;
ae_vector tau;
ae_vector d;
ae_vector e;
double v;
ae_frame_make(_state, &_frame_block);
memset(&ua, 0, sizeof(ua));
memset(&la, 0, sizeof(la));
memset(&t, 0, sizeof(t));
memset(&q, 0, sizeof(q));
memset(&t2, 0, sizeof(t2));
memset(&t3, 0, sizeof(t3));
memset(&tau, 0, sizeof(tau));
memset(&d, 0, sizeof(d));
memset(&e, 0, sizeof(e));
ae_matrix_init(&ua, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&la, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&t, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&t2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&t3, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tau, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&e, 0, DT_REAL, _state, ae_true);
ae_matrix_set_length(&ua, n-1+1, n-1+1, _state);
ae_matrix_set_length(&la, n-1+1, n-1+1, _state);
ae_matrix_set_length(&t, n-1+1, n-1+1, _state);
ae_matrix_set_length(&q, n-1+1, n-1+1, _state);
ae_matrix_set_length(&t2, n-1+1, n-1+1, _state);
ae_matrix_set_length(&t3, n-1+1, n-1+1, _state);
/*
* fill
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
ua.ptr.pp_double[i][j] = (double)(0);
}
}
for(i=0; i<=n-1; i++)
{
for(j=i; j<=n-1; j++)
{
ua.ptr.pp_double[i][j] = a->ptr.pp_double[i][j];
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
la.ptr.pp_double[i][j] = (double)(0);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=i; j++)
{
la.ptr.pp_double[i][j] = a->ptr.pp_double[i][j];
}
}
/*
* Test 2tridiagonal: upper
*/
smatrixtd(&ua, n, ae_true, &tau, &d, &e, _state);
smatrixtdunpackq(&ua, n, ae_true, &tau, &q, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
t.ptr.pp_double[i][j] = (double)(0);
}
}
for(i=0; i<=n-1; i++)
{
t.ptr.pp_double[i][i] = d.ptr.p_double[i];
}
for(i=0; i<=n-2; i++)
{
t.ptr.pp_double[i][i+1] = e.ptr.p_double[i];
t.ptr.pp_double[i+1][i] = e.ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&q.ptr.pp_double[0][i], q.stride, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,n-1));
t2.ptr.pp_double[i][j] = v;
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&t2.ptr.pp_double[i][0], 1, &q.ptr.pp_double[0][j], q.stride, ae_v_len(0,n-1));
t3.ptr.pp_double[i][j] = v;
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
*tderrors = *tderrors||ae_fp_greater(ae_fabs(t3.ptr.pp_double[i][j]-t.ptr.pp_double[i][j], _state),threshold);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &q.ptr.pp_double[j][0], 1, ae_v_len(0,n-1));
if( i==j )
{
v = v-1;
}
*tderrors = *tderrors||ae_fp_greater(ae_fabs(v, _state),threshold);
}
}
/*
* Test 2tridiagonal: lower
*/
smatrixtd(&la, n, ae_false, &tau, &d, &e, _state);
smatrixtdunpackq(&la, n, ae_false, &tau, &q, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
t.ptr.pp_double[i][j] = (double)(0);
}
}
for(i=0; i<=n-1; i++)
{
t.ptr.pp_double[i][i] = d.ptr.p_double[i];
}
for(i=0; i<=n-2; i++)
{
t.ptr.pp_double[i][i+1] = e.ptr.p_double[i];
t.ptr.pp_double[i+1][i] = e.ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&q.ptr.pp_double[0][i], q.stride, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,n-1));
t2.ptr.pp_double[i][j] = v;
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&t2.ptr.pp_double[i][0], 1, &q.ptr.pp_double[0][j], q.stride, ae_v_len(0,n-1));
t3.ptr.pp_double[i][j] = v;
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
*tderrors = *tderrors||ae_fp_greater(ae_fabs(t3.ptr.pp_double[i][j]-t.ptr.pp_double[i][j], _state),threshold);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &q.ptr.pp_double[j][0], 1, ae_v_len(0,n-1));
if( i==j )
{
v = v-1;
}
*tderrors = *tderrors||ae_fp_greater(ae_fabs(v, _state),threshold);
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Hermitian problem tester
*************************************************************************/
static void testortfacunit_testctdproblem(/* Complex */ ae_matrix* a,
ae_int_t n,
double threshold,
ae_bool* tderrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_matrix ua;
ae_matrix la;
ae_matrix t;
ae_matrix q;
ae_matrix t2;
ae_matrix t3;
ae_vector tau;
ae_vector d;
ae_vector e;
ae_complex v;
ae_frame_make(_state, &_frame_block);
memset(&ua, 0, sizeof(ua));
memset(&la, 0, sizeof(la));
memset(&t, 0, sizeof(t));
memset(&q, 0, sizeof(q));
memset(&t2, 0, sizeof(t2));
memset(&t3, 0, sizeof(t3));
memset(&tau, 0, sizeof(tau));
memset(&d, 0, sizeof(d));
memset(&e, 0, sizeof(e));
ae_matrix_init(&ua, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&la, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&t, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&q, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&t2, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&t3, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&tau, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&e, 0, DT_REAL, _state, ae_true);
ae_matrix_set_length(&ua, n-1+1, n-1+1, _state);
ae_matrix_set_length(&la, n-1+1, n-1+1, _state);
ae_matrix_set_length(&t, n-1+1, n-1+1, _state);
ae_matrix_set_length(&q, n-1+1, n-1+1, _state);
ae_matrix_set_length(&t2, n-1+1, n-1+1, _state);
ae_matrix_set_length(&t3, n-1+1, n-1+1, _state);
/*
* fill
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
ua.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
for(i=0; i<=n-1; i++)
{
for(j=i; j<=n-1; j++)
{
ua.ptr.pp_complex[i][j] = a->ptr.pp_complex[i][j];
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
la.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=i; j++)
{
la.ptr.pp_complex[i][j] = a->ptr.pp_complex[i][j];
}
}
/*
* Test 2tridiagonal: upper
*/
hmatrixtd(&ua, n, ae_true, &tau, &d, &e, _state);
hmatrixtdunpackq(&ua, n, ae_true, &tau, &q, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
t.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
for(i=0; i<=n-1; i++)
{
t.ptr.pp_complex[i][i] = ae_complex_from_d(d.ptr.p_double[i]);
}
for(i=0; i<=n-2; i++)
{
t.ptr.pp_complex[i][i+1] = ae_complex_from_d(e.ptr.p_double[i]);
t.ptr.pp_complex[i+1][i] = ae_complex_from_d(e.ptr.p_double[i]);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_cdotproduct(&q.ptr.pp_complex[0][i], q.stride, "Conj", &a->ptr.pp_complex[0][j], a->stride, "N", ae_v_len(0,n-1));
t2.ptr.pp_complex[i][j] = v;
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_cdotproduct(&t2.ptr.pp_complex[i][0], 1, "N", &q.ptr.pp_complex[0][j], q.stride, "N", ae_v_len(0,n-1));
t3.ptr.pp_complex[i][j] = v;
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
*tderrors = *tderrors||ae_fp_greater(ae_c_abs(ae_c_sub(t3.ptr.pp_complex[i][j],t.ptr.pp_complex[i][j]), _state),threshold);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_cdotproduct(&q.ptr.pp_complex[i][0], 1, "N", &q.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,n-1));
if( i==j )
{
v = ae_c_sub_d(v,1);
}
*tderrors = *tderrors||ae_fp_greater(ae_c_abs(v, _state),threshold);
}
}
/*
* Test 2tridiagonal: lower
*/
hmatrixtd(&la, n, ae_false, &tau, &d, &e, _state);
hmatrixtdunpackq(&la, n, ae_false, &tau, &q, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
t.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
for(i=0; i<=n-1; i++)
{
t.ptr.pp_complex[i][i] = ae_complex_from_d(d.ptr.p_double[i]);
}
for(i=0; i<=n-2; i++)
{
t.ptr.pp_complex[i][i+1] = ae_complex_from_d(e.ptr.p_double[i]);
t.ptr.pp_complex[i+1][i] = ae_complex_from_d(e.ptr.p_double[i]);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_cdotproduct(&q.ptr.pp_complex[0][i], q.stride, "Conj", &a->ptr.pp_complex[0][j], a->stride, "N", ae_v_len(0,n-1));
t2.ptr.pp_complex[i][j] = v;
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_cdotproduct(&t2.ptr.pp_complex[i][0], 1, "N", &q.ptr.pp_complex[0][j], q.stride, "N", ae_v_len(0,n-1));
t3.ptr.pp_complex[i][j] = v;
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
*tderrors = *tderrors||ae_fp_greater(ae_c_abs(ae_c_sub(t3.ptr.pp_complex[i][j],t.ptr.pp_complex[i][j]), _state),threshold);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_cdotproduct(&q.ptr.pp_complex[i][0], 1, "N", &q.ptr.pp_complex[j][0], 1, "Conj", ae_v_len(0,n-1));
if( i==j )
{
v = ae_c_sub_d(v,1);
}
*tderrors = *tderrors||ae_fp_greater(ae_c_abs(v, _state),threshold);
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Testing
*************************************************************************/
ae_bool testfbls(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t m;
ae_int_t mx;
ae_int_t i;
ae_int_t j;
ae_bool waserrors;
ae_bool cgerrors;
ae_bool lserrors;
ae_bool cholerrors;
double eps;
double v;
double v1;
double v2;
ae_vector tmp0;
ae_vector tmp1;
ae_vector tmp2;
double scalea;
ae_bool uppera;
ae_matrix a;
ae_matrix ea;
ae_vector b;
ae_vector x;
ae_vector xe;
ae_vector buf;
double alpha;
double e1;
double e2;
fblslincgstate cgstate;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&tmp0, 0, sizeof(tmp0));
memset(&tmp1, 0, sizeof(tmp1));
memset(&tmp2, 0, sizeof(tmp2));
memset(&a, 0, sizeof(a));
memset(&ea, 0, sizeof(ea));
memset(&b, 0, sizeof(b));
memset(&x, 0, sizeof(x));
memset(&xe, 0, sizeof(xe));
memset(&buf, 0, sizeof(buf));
memset(&cgstate, 0, sizeof(cgstate));
ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp2, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ea, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xe, 0, DT_REAL, _state, ae_true);
ae_vector_init(&buf, 0, DT_REAL, _state, ae_true);
_fblslincgstate_init(&cgstate, _state, ae_true);
mx = 10;
waserrors = ae_false;
cgerrors = ae_false;
lserrors = ae_false;
cholerrors = ae_false;
/*
* Test CG solver:
* * generate problem (A, B, Alpha, XE - exact solution) and initial approximation X
* * E1 = ||A'A*x-b||
* * solve
* * E2 = ||A'A*x-b||
* * test that E2<0.001*E1
*/
for(n=1; n<=mx; n++)
{
for(m=1; m<=mx; m++)
{
ae_matrix_set_length(&a, m, n, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&xe, n, _state);
ae_vector_set_length(&tmp1, m, _state);
ae_vector_set_length(&tmp2, n, _state);
/*
* init A, alpha, B, X (initial approximation), XE (exact solution)
* X is initialized in such way that is has no chances to be equal to XE.
*/
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
alpha = ae_randomreal(_state)+0.1;
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
xe.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x.ptr.p_double[i] = (2*ae_randominteger(2, _state)-1)*(2+ae_randomreal(_state));
}
/*
* Test dense CG (which solves A'A*x=b and accepts dense A)
*/
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = (2*ae_randominteger(2, _state)-1)*(2+ae_randomreal(_state));
}
rmatrixmv(m, n, &a, 0, 0, 0, &x, 0, &tmp1, 0, _state);
rmatrixmv(n, m, &a, 0, 0, 1, &tmp1, 0, &tmp2, 0, _state);
ae_v_addd(&tmp2.ptr.p_double[0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1), alpha);
ae_v_sub(&tmp2.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = ae_v_dotproduct(&tmp2.ptr.p_double[0], 1, &tmp2.ptr.p_double[0], 1, ae_v_len(0,n-1));
e1 = ae_sqrt(v, _state);
fblssolvecgx(&a, m, n, alpha, &b, &x, &buf, _state);
rmatrixmv(m, n, &a, 0, 0, 0, &x, 0, &tmp1, 0, _state);
rmatrixmv(n, m, &a, 0, 0, 1, &tmp1, 0, &tmp2, 0, _state);
ae_v_addd(&tmp2.ptr.p_double[0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1), alpha);
ae_v_sub(&tmp2.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = ae_v_dotproduct(&tmp2.ptr.p_double[0], 1, &tmp2.ptr.p_double[0], 1, ae_v_len(0,n-1));
e2 = ae_sqrt(v, _state);
cgerrors = cgerrors||ae_fp_greater(e2,0.001*e1);
/*
* Test sparse CG (which relies on reverse communication)
*/
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = (2*ae_randominteger(2, _state)-1)*(2+ae_randomreal(_state));
}
rmatrixmv(m, n, &a, 0, 0, 0, &x, 0, &tmp1, 0, _state);
rmatrixmv(n, m, &a, 0, 0, 1, &tmp1, 0, &tmp2, 0, _state);
ae_v_addd(&tmp2.ptr.p_double[0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1), alpha);
ae_v_sub(&tmp2.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = ae_v_dotproduct(&tmp2.ptr.p_double[0], 1, &tmp2.ptr.p_double[0], 1, ae_v_len(0,n-1));
e1 = ae_sqrt(v, _state);
fblscgcreate(&x, &b, n, &cgstate, _state);
while(fblscgiteration(&cgstate, _state))
{
rmatrixmv(m, n, &a, 0, 0, 0, &cgstate.x, 0, &tmp1, 0, _state);
rmatrixmv(n, m, &a, 0, 0, 1, &tmp1, 0, &cgstate.ax, 0, _state);
ae_v_addd(&cgstate.ax.ptr.p_double[0], 1, &cgstate.x.ptr.p_double[0], 1, ae_v_len(0,n-1), alpha);
v1 = ae_v_dotproduct(&tmp1.ptr.p_double[0], 1, &tmp1.ptr.p_double[0], 1, ae_v_len(0,m-1));
v2 = ae_v_dotproduct(&cgstate.x.ptr.p_double[0], 1, &cgstate.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
cgstate.xax = v1+alpha*v2;
}
rmatrixmv(m, n, &a, 0, 0, 0, &cgstate.xk, 0, &tmp1, 0, _state);
rmatrixmv(n, m, &a, 0, 0, 1, &tmp1, 0, &tmp2, 0, _state);
ae_v_addd(&tmp2.ptr.p_double[0], 1, &cgstate.xk.ptr.p_double[0], 1, ae_v_len(0,n-1), alpha);
ae_v_sub(&tmp2.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = ae_v_dotproduct(&tmp2.ptr.p_double[0], 1, &tmp2.ptr.p_double[0], 1, ae_v_len(0,n-1));
e2 = ae_sqrt(v, _state);
cgerrors = cgerrors||ae_fp_greater(ae_fabs(e1-cgstate.e1, _state),100*ae_machineepsilon*e1);
cgerrors = cgerrors||ae_fp_greater(ae_fabs(e2-cgstate.e2, _state),100*ae_machineepsilon*e1);
cgerrors = cgerrors||ae_fp_greater(e2,0.001*e1);
}
}
/*
* Test linear least squares:
* * try N=1..5, M=N..2*N
* [ B ]
* * generate MxN matrix A = [ ], where (M-N)xN submatrix B contains
* [ C ]
* random values from [-1,+1], and NxN submatrix C is diagonally dominant
* (diagonal of C is equal to 1.0, and magnitude of off-diagonal elements
* is smaller than 0.01). Such matrix is guaranteed to be non-degenerate.
* * generate random known solution xe, set right part b=A*xe
* * check that results of FBLSSolveLS agree with xe
*/
eps = 1.0E-6;
for(n=1; n<=5; n++)
{
for(m=n; m<=2*n; m++)
{
ae_matrix_set_length(&a, m, n, _state);
for(i=0; i<=m-n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
for(i=m-n; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.01*(2*ae_randomreal(_state)-1);
}
a.ptr.pp_double[i][i-(m-n)] = 1.0;
}
ae_vector_set_length(&xe, n, _state);
for(i=0; i<=n-1; i++)
{
xe.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
ae_vector_set_length(&b, m, _state);
for(i=0; i<=m-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xe.ptr.p_double[0], 1, ae_v_len(0,n-1));
b.ptr.p_double[i] = v;
}
fblssolvels(&a, &b, m, n, &tmp0, &tmp1, &tmp2, _state);
for(i=0; i<=n-1; i++)
{
lserrors = lserrors||ae_fp_greater(ae_fabs(b.ptr.p_double[i]-xe.ptr.p_double[i], _state),eps);
}
}
}
/*
* Test Cholesky solver:
* * generate trial A, ScaleA, XS and corresponding right part B
*/
for(n=1; n<=30; n++)
{
/*
* Generate test problem
*/
ae_matrix_set_length(&a, n, n, _state);
ae_matrix_set_length(&ea, n, n, _state);
ae_vector_set_length(&xe, n, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&buf, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.01*(ae_randomreal(_state)-0.5);
}
a.ptr.pp_double[i][i] = 1+ae_randomreal(_state);
xe.ptr.p_double[i] = ae_randomreal(_state)-0.5;
}
scalea = ae_pow((double)(10), ae_randomreal(_state)*4-2, _state);
uppera = ae_fp_greater(ae_randomreal(_state),0.5);
for(i=0; i<=n-1; i++)
{
if( uppera )
{
for(j=0; j<=i-1; j++)
{
ea.ptr.pp_double[i][j] = (double)(0);
}
for(j=i; j<=n-1; j++)
{
ea.ptr.pp_double[i][j] = a.ptr.pp_double[i][j];
}
}
else
{
for(j=0; j<=i; j++)
{
ea.ptr.pp_double[i][j] = a.ptr.pp_double[i][j];
}
for(j=i+1; j<=n-1; j++)
{
ea.ptr.pp_double[i][j] = (double)(0);
}
}
}
if( uppera )
{
rmatrixgemv(n, n, 1.0, &ea, 0, 0, 0, &xe, 0, 0.0, &buf, 0, _state);
rmatrixgemv(n, n, 1.0, &ea, 0, 0, 1, &buf, 0, 0.0, &b, 0, _state);
}
else
{
rmatrixgemv(n, n, 1.0, &ea, 0, 0, 1, &xe, 0, 0.0, &buf, 0, _state);
rmatrixgemv(n, n, 1.0, &ea, 0, 0, 0, &buf, 0, 0.0, &b, 0, _state);
}
ae_v_muld(&b.ptr.p_double[0], 1, ae_v_len(0,n-1), scalea);
/*
* Test
*/
fblscholeskysolve(&a, ae_sqrt(scalea, _state), n, uppera, &b, &buf, _state);
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(&cholerrors, ae_fp_greater(ae_fabs(b.ptr.p_double[i]-xe.ptr.p_double[i], _state),1.0E3*ae_machineepsilon), __FILE__, __LINE__, "testfblsunit.ap:284");
}
}
/*
* report
*/
waserrors = (cgerrors||lserrors)||cholerrors;
if( !silent )
{
printf("TESTING FBLS\n");
printf("CG ERRORS: ");
if( cgerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("LS ERRORS: ");
if( lserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("CHOL ERRORS: ");
if( cholerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
ae_bool testcqmodels(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_bool eval0errors;
ae_bool eval1errors;
ae_bool eval2errors;
ae_bool newton0errors;
ae_bool newton1errors;
ae_bool newton2errors;
ae_bool waserrors;
convexquadraticmodel s;
ae_int_t nkind;
ae_int_t kmax;
ae_int_t n;
ae_int_t k;
ae_int_t i;
ae_int_t pass;
ae_int_t j;
double alpha;
double theta;
double tau;
double v;
double v2;
double h;
double f0;
double mkind;
double xtadx2;
double noise;
ae_matrix a;
ae_matrix q;
ae_vector b;
ae_vector r;
ae_vector x;
ae_vector x0;
ae_vector xc;
ae_vector d;
ae_vector ge;
ae_vector gt;
ae_vector tmp0;
ae_vector adx;
ae_vector adxe;
ae_vector activeset;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&a, 0, sizeof(a));
memset(&q, 0, sizeof(q));
memset(&b, 0, sizeof(b));
memset(&r, 0, sizeof(r));
memset(&x, 0, sizeof(x));
memset(&x0, 0, sizeof(x0));
memset(&xc, 0, sizeof(xc));
memset(&d, 0, sizeof(d));
memset(&ge, 0, sizeof(ge));
memset(>, 0, sizeof(gt));
memset(&tmp0, 0, sizeof(tmp0));
memset(&adx, 0, sizeof(adx));
memset(&adxe, 0, sizeof(adxe));
memset(&activeset, 0, sizeof(activeset));
_convexquadraticmodel_init(&s, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&r, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ge, 0, DT_REAL, _state, ae_true);
ae_vector_init(>, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&adx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&adxe, 0, DT_REAL, _state, ae_true);
ae_vector_init(&activeset, 0, DT_BOOL, _state, ae_true);
waserrors = ae_false;
/*
* Eval0 test: unconstrained model evaluation
*/
eval0errors = ae_false;
for(n=1; n<=5; n++)
{
for(k=0; k<=2*n; k++)
{
/*
* Allocate place
*/
ae_matrix_set_length(&a, n, n, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&d, n, _state);
ae_vector_set_length(&ge, n, _state);
ae_vector_set_length(>, n, _state);
ae_vector_set_length(&tmp0, n, _state);
if( k>0 )
{
ae_matrix_set_length(&q, k, n, _state);
ae_vector_set_length(&r, k, _state);
}
/*
* Generate problem
*/
alpha = ae_randomreal(_state)+1.0;
theta = ae_randomreal(_state)+1.0;
tau = ae_randomreal(_state)*ae_randominteger(2, _state);
for(i=0; i<=n-1; i++)
{
a.ptr.pp_double[i][i] = 10*(1+ae_randomreal(_state));
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
d.ptr.p_double[i] = ae_randomreal(_state)+1;
for(j=i+1; j<=n-1; j++)
{
v = 0.1*ae_randomreal(_state)-0.05;
a.ptr.pp_double[i][j] = v;
a.ptr.pp_double[j][i] = v;
}
for(j=0; j<=k-1; j++)
{
q.ptr.pp_double[j][i] = 2*ae_randomreal(_state)-1;
}
}
for(i=0; i<=k-1; i++)
{
r.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
/*
* Build model
*/
cqminit(n, &s, _state);
cqmseta(&s, &a, ae_fp_greater(ae_randomreal(_state),0.5), alpha, _state);
cqmsetb(&s, &b, _state);
cqmsetq(&s, &q, &r, k, theta, _state);
cqmsetd(&s, &d, tau, _state);
/*
* Evaluate and compare:
* * X - random point
* * GE - "exact" gradient
* * XTADX2 - x'*(alpha*A+tau*D)*x/2
* * ADXE - (alpha*A+tau*D)*x
* * V - model value at X
*/
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
ge.ptr.p_double[i] = 0.0;
}
v = 0.0;
xtadx2 = 0.0;
ae_vector_set_length(&adxe, n, _state);
for(i=0; i<=n-1; i++)
{
adxe.ptr.p_double[i] = (double)(0);
}
for(i=0; i<=n-1; i++)
{
v = v+x.ptr.p_double[i]*b.ptr.p_double[i];
ge.ptr.p_double[i] = ge.ptr.p_double[i]+b.ptr.p_double[i];
v = v+0.5*ae_sqr(x.ptr.p_double[i], _state)*tau*d.ptr.p_double[i];
ge.ptr.p_double[i] = ge.ptr.p_double[i]+x.ptr.p_double[i]*tau*d.ptr.p_double[i];
adxe.ptr.p_double[i] = adxe.ptr.p_double[i]+x.ptr.p_double[i]*tau*d.ptr.p_double[i];
xtadx2 = xtadx2+0.5*ae_sqr(x.ptr.p_double[i], _state)*tau*d.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
v = v+0.5*alpha*x.ptr.p_double[i]*a.ptr.pp_double[i][j]*x.ptr.p_double[j];
ge.ptr.p_double[i] = ge.ptr.p_double[i]+alpha*a.ptr.pp_double[i][j]*x.ptr.p_double[j];
adxe.ptr.p_double[i] = adxe.ptr.p_double[i]+alpha*a.ptr.pp_double[i][j]*x.ptr.p_double[j];
xtadx2 = xtadx2+0.5*alpha*x.ptr.p_double[i]*a.ptr.pp_double[i][j]*x.ptr.p_double[j];
}
}
for(i=0; i<=k-1; i++)
{
v2 = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = v+0.5*theta*ae_sqr(v2-r.ptr.p_double[i], _state);
for(j=0; j<=n-1; j++)
{
ge.ptr.p_double[j] = ge.ptr.p_double[j]+theta*(v2-r.ptr.p_double[i])*q.ptr.pp_double[i][j];
}
}
v2 = cqmeval(&s, &x, _state);
eval0errors = eval0errors||ae_fp_greater(ae_fabs(v-v2, _state),10000*ae_machineepsilon);
cqmevalx(&s, &x, &v2, &noise, _state);
eval0errors = eval0errors||ae_fp_greater(ae_fabs(v-v2, _state),10000*ae_machineepsilon);
eval0errors = (eval0errors||ae_fp_less(noise,(double)(0)))||ae_fp_greater(noise,10000*ae_machineepsilon);
v2 = cqmxtadx2(&s, &x, &tmp0, _state);
eval0errors = eval0errors||ae_fp_greater(ae_fabs(xtadx2-v2, _state),10000*ae_machineepsilon);
cqmgradunconstrained(&s, &x, >, _state);
for(i=0; i<=n-1; i++)
{
eval0errors = eval0errors||ae_fp_greater(ae_fabs(ge.ptr.p_double[i]-gt.ptr.p_double[i], _state),10000*ae_machineepsilon);
}
cqmadx(&s, &x, &adx, _state);
for(i=0; i<=n-1; i++)
{
eval0errors = eval0errors||ae_fp_greater(ae_fabs(adx.ptr.p_double[i]-adxe.ptr.p_double[i], _state),10000*ae_machineepsilon);
}
}
}
waserrors = waserrors||eval0errors;
/*
* Eval1 test: constrained model evaluation
*/
eval1errors = ae_false;
for(n=1; n<=5; n++)
{
for(k=0; k<=2*n; k++)
{
/*
* Allocate place
*/
ae_matrix_set_length(&a, n, n, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&xc, n, _state);
ae_vector_set_length(&activeset, n, _state);
if( k>0 )
{
ae_matrix_set_length(&q, k, n, _state);
ae_vector_set_length(&r, k, _state);
}
/*
* Generate problem
*/
alpha = ae_randomreal(_state)+1.0;
theta = ae_randomreal(_state)+1.0;
for(i=0; i<=n-1; i++)
{
a.ptr.pp_double[i][i] = 10*(1+ae_randomreal(_state));
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
activeset.ptr.p_bool[i] = ae_fp_greater(ae_randomreal(_state),0.5);
for(j=i+1; j<=n-1; j++)
{
v = 0.1*ae_randomreal(_state)-0.05;
a.ptr.pp_double[i][j] = v;
a.ptr.pp_double[j][i] = v;
}
for(j=0; j<=k-1; j++)
{
q.ptr.pp_double[j][i] = 2*ae_randomreal(_state)-1;
}
}
for(i=0; i<=k-1; i++)
{
r.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
/*
* Build model, evaluate at random point X, compare
*/
cqminit(n, &s, _state);
cqmseta(&s, &a, ae_fp_greater(ae_randomreal(_state),0.5), alpha, _state);
cqmsetb(&s, &b, _state);
cqmsetq(&s, &q, &r, k, theta, _state);
cqmsetactiveset(&s, &xc, &activeset, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
if( !activeset.ptr.p_bool[i] )
{
xc.ptr.p_double[i] = x.ptr.p_double[i];
}
}
v = 0.0;
for(i=0; i<=n-1; i++)
{
v = v+xc.ptr.p_double[i]*b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
v = v+0.5*alpha*xc.ptr.p_double[i]*a.ptr.pp_double[i][j]*xc.ptr.p_double[j];
}
}
for(i=0; i<=k-1; i++)
{
v2 = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &xc.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = v+0.5*theta*ae_sqr(v2-r.ptr.p_double[i], _state);
}
eval1errors = eval1errors||ae_fp_greater(ae_fabs(v-cqmeval(&s, &xc, _state), _state),10000*ae_machineepsilon);
eval1errors = eval1errors||ae_fp_greater(ae_fabs(v-cqmdebugconstrainedevalt(&s, &x, _state), _state),10000*ae_machineepsilon);
eval1errors = eval1errors||ae_fp_greater(ae_fabs(v-cqmdebugconstrainedevale(&s, &x, _state), _state),10000*ae_machineepsilon);
}
}
waserrors = waserrors||eval1errors;
/*
* Eval2 test: we generate empty problem and apply sequence of random transformations,
* re-evaluating and re-checking model after each modification.
*
* The purpose of such test is to ensure that our caching strategy works correctly.
*/
eval2errors = ae_false;
for(n=1; n<=5; n++)
{
kmax = 2*n;
ae_matrix_set_length(&a, n, n, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&d, n, _state);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&xc, n, _state);
ae_matrix_set_length(&q, kmax, n, _state);
ae_vector_set_length(&r, kmax, _state);
ae_vector_set_length(&activeset, n, _state);
ae_vector_set_length(&tmp0, n, _state);
alpha = 0.0;
theta = 0.0;
k = 0;
tau = 1.0+ae_randomreal(_state);
for(i=0; i<=n-1; i++)
{
activeset.ptr.p_bool[i] = ae_false;
d.ptr.p_double[i] = 1.0;
b.ptr.p_double[i] = 0.0;
xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
cqminit(n, &s, _state);
cqmsetd(&s, &d, tau, _state);
for(pass=1; pass<=100; pass++)
{
/*
* Select random modification type, apply modification.
*
* MKind is a random integer in [0,7] - number of specific
* modification to apply.
*/
mkind = (double)(ae_randominteger(8, _state));
if( ae_fp_eq(mkind,(double)(0)) )
{
/*
* Set non-zero D
*/
tau = 1.0+ae_randomreal(_state);
for(i=0; i<=n-1; i++)
{
d.ptr.p_double[i] = 2*ae_randomreal(_state)+1;
}
cqmsetd(&s, &d, tau, _state);
}
else
{
if( ae_fp_eq(mkind,(double)(1)) )
{
/*
* Set zero D.
* In case Alpha=0, set non-zero A.
*/
if( ae_fp_eq(alpha,(double)(0)) )
{
alpha = 1.0+ae_randomreal(_state);
for(i=0; i<=n-1; i++)
{
for(j=i+1; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.2*ae_randomreal(_state)-0.1;
a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j];
}
}
for(i=0; i<=n-1; i++)
{
a.ptr.pp_double[i][i] = 4+2*ae_randomreal(_state);
}
cqmseta(&s, &a, ae_fp_greater(ae_randomreal(_state),0.5), alpha, _state);
}
tau = 0.0;
for(i=0; i<=n-1; i++)
{
d.ptr.p_double[i] = (double)(0);
}
cqmsetd(&s, &d, 0.0, _state);
}
else
{
if( ae_fp_eq(mkind,(double)(2)) )
{
/*
* Set non-zero A
*/
alpha = 1.0+ae_randomreal(_state);
for(i=0; i<=n-1; i++)
{
for(j=i+1; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.2*ae_randomreal(_state)-0.1;
a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j];
}
}
for(i=0; i<=n-1; i++)
{
a.ptr.pp_double[i][i] = 4+2*ae_randomreal(_state);
}
cqmseta(&s, &a, ae_fp_greater(ae_randomreal(_state),0.5), alpha, _state);
}
else
{
if( ae_fp_eq(mkind,(double)(3)) )
{
/*
* Set zero A.
* In case Tau=0, set non-zero D.
*/
if( ae_fp_eq(tau,(double)(0)) )
{
tau = 1.0+ae_randomreal(_state);
for(i=0; i<=n-1; i++)
{
d.ptr.p_double[i] = 2*ae_randomreal(_state)+1;
}
cqmsetd(&s, &d, tau, _state);
}
alpha = 0.0;
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
cqmseta(&s, &a, ae_fp_greater(ae_randomreal(_state),0.5), alpha, _state);
}
else
{
if( ae_fp_eq(mkind,(double)(4)) )
{
/*
* Set B.
*/
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
cqmsetb(&s, &b, _state);
}
else
{
if( ae_fp_eq(mkind,(double)(5)) )
{
/*
* Set Q.
*/
k = ae_randominteger(kmax+1, _state);
theta = 1.0+ae_randomreal(_state);
for(i=0; i<=k-1; i++)
{
r.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
for(j=0; j<=n-1; j++)
{
q.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
cqmsetq(&s, &q, &r, k, theta, _state);
}
else
{
if( ae_fp_eq(mkind,(double)(6)) )
{
/*
* Set active set
*/
for(i=0; i<=n-1; i++)
{
activeset.ptr.p_bool[i] = ae_fp_greater(ae_randomreal(_state),0.5);
xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
cqmsetactiveset(&s, &xc, &activeset, _state);
}
else
{
if( ae_fp_eq(mkind,(double)(7)) )
{
/*
* Rewrite main diagonal
*/
if( ae_fp_eq(alpha,(double)(0)) )
{
alpha = 1.0;
}
for(i=0; i<=n-1; i++)
{
tmp0.ptr.p_double[i] = 1+ae_randomreal(_state);
a.ptr.pp_double[i][i] = tmp0.ptr.p_double[i]/alpha;
}
cqmrewritedensediagonal(&s, &tmp0, _state);
}
}
}
}
}
}
}
}
/*
* generate random point with respect to constraints,
* test model at this point
*/
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
if( activeset.ptr.p_bool[i] )
{
x.ptr.p_double[i] = xc.ptr.p_double[i];
}
}
v = 0.0;
for(i=0; i<=n-1; i++)
{
v = v+x.ptr.p_double[i]*b.ptr.p_double[i];
}
if( ae_fp_greater(tau,(double)(0)) )
{
for(i=0; i<=n-1; i++)
{
v = v+0.5*tau*d.ptr.p_double[i]*ae_sqr(x.ptr.p_double[i], _state);
}
}
if( ae_fp_greater(alpha,(double)(0)) )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = v+0.5*alpha*x.ptr.p_double[i]*a.ptr.pp_double[i][j]*x.ptr.p_double[j];
}
}
}
if( ae_fp_greater(theta,(double)(0)) )
{
for(i=0; i<=k-1; i++)
{
v2 = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = v+0.5*theta*ae_sqr(v2-r.ptr.p_double[i], _state);
}
}
v2 = cqmeval(&s, &x, _state);
eval2errors = eval2errors||ae_fp_greater(ae_fabs(v-v2, _state),10000*ae_machineepsilon);
v2 = cqmdebugconstrainedevalt(&s, &x, _state);
eval2errors = eval2errors||ae_fp_greater(ae_fabs(v-v2, _state),10000*ae_machineepsilon);
v2 = cqmdebugconstrainedevale(&s, &x, _state);
eval2errors = eval2errors||ae_fp_greater(ae_fabs(v-v2, _state),10000*ae_machineepsilon);
}
}
waserrors = waserrors||eval2errors;
/*
* Newton0 test: unconstrained optimization
*/
newton0errors = ae_false;
for(n=1; n<=5; n++)
{
for(k=0; k<=2*n; k++)
{
/*
* Allocate place
*/
ae_matrix_set_length(&a, n, n, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&x0, n, _state);
if( k>0 )
{
ae_matrix_set_length(&q, k, n, _state);
ae_vector_set_length(&r, k, _state);
}
/*
* Generate problem with known solution x0:
* min f(x),
* f(x) = 0.5*(x-x0)'*A*(x-x0)
* = 0.5*x'*A*x + (-x0'*A)*x + 0.5*x0'*A*x0'
*/
alpha = ae_randomreal(_state)+1.0;
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
a.ptr.pp_double[i][i] = 10*(1+ae_randomreal(_state));
for(j=i+1; j<=n-1; j++)
{
v = 0.1*ae_randomreal(_state)-0.05;
a.ptr.pp_double[i][j] = v;
a.ptr.pp_double[j][i] = v;
}
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1));
b.ptr.p_double[i] = -alpha*v;
}
theta = ae_randomreal(_state)+1.0;
for(i=0; i<=k-1; i++)
{
for(j=0; j<=n-1; j++)
{
q.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
v = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1));
r.ptr.p_double[i] = v;
}
/*
* Build model, evaluate at random point X, compare
*/
cqminit(n, &s, _state);
cqmseta(&s, &a, ae_fp_greater(ae_randomreal(_state),0.5), alpha, _state);
cqmsetb(&s, &b, _state);
cqmsetq(&s, &q, &r, k, theta, _state);
cqmconstrainedoptimum(&s, &x, _state);
for(i=0; i<=n-1; i++)
{
newton0errors = newton0errors||ae_fp_greater(ae_fabs(x.ptr.p_double[i]-x0.ptr.p_double[i], _state),1.0E6*ae_machineepsilon);
}
}
}
waserrors = waserrors||newton0errors;
/*
* Newton1 test: constrained optimization
*/
newton1errors = ae_false;
h = 1.0E-3;
for(n=1; n<=5; n++)
{
for(k=0; k<=2*n; k++)
{
/*
* Allocate place
*/
ae_matrix_set_length(&a, n, n, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&xc, n, _state);
ae_vector_set_length(&activeset, n, _state);
if( k>0 )
{
ae_matrix_set_length(&q, k, n, _state);
ae_vector_set_length(&r, k, _state);
}
/*
* Generate test problem with unknown solution.
*/
alpha = ae_randomreal(_state)+1.0;
for(i=0; i<=n-1; i++)
{
a.ptr.pp_double[i][i] = 10*(1+ae_randomreal(_state));
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
activeset.ptr.p_bool[i] = ae_fp_greater(ae_randomreal(_state),0.5);
for(j=i+1; j<=n-1; j++)
{
v = 0.1*ae_randomreal(_state)-0.05;
a.ptr.pp_double[i][j] = v;
a.ptr.pp_double[j][i] = v;
}
}
theta = ae_randomreal(_state)+1.0;
for(i=0; i<=k-1; i++)
{
for(j=0; j<=n-1; j++)
{
q.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
r.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
/*
* Build model, find solution
*/
cqminit(n, &s, _state);
cqmseta(&s, &a, ae_fp_greater(ae_randomreal(_state),0.5), alpha, _state);
cqmsetb(&s, &b, _state);
cqmsetq(&s, &q, &r, k, theta, _state);
cqmsetactiveset(&s, &xc, &activeset, _state);
if( cqmconstrainedoptimum(&s, &x, _state) )
{
/*
* Check that constraints are satisfied,
* and that solution is true optimum
*/
f0 = cqmeval(&s, &x, _state);
for(i=0; i<=n-1; i++)
{
newton1errors = newton1errors||(activeset.ptr.p_bool[i]&&ae_fp_neq(x.ptr.p_double[i],xc.ptr.p_double[i]));
if( !activeset.ptr.p_bool[i] )
{
v = x.ptr.p_double[i];
x.ptr.p_double[i] = v+h;
v2 = cqmeval(&s, &x, _state);
newton1errors = newton1errors||ae_fp_less(v2,f0);
x.ptr.p_double[i] = v-h;
v2 = cqmeval(&s, &x, _state);
newton1errors = newton1errors||ae_fp_less(v2,f0);
x.ptr.p_double[i] = v;
}
}
}
else
{
newton1errors = ae_true;
}
}
}
waserrors = waserrors||newton1errors;
/*
* Newton2 test: we test ability to work with diagonal matrices, including
* very large ones (up to 100.000 elements). This test checks that:
* a) we can work with Alpha=0, i.e. when we have strictly diagonal A
* b) diagonal problems are handled efficiently, i.e. algorithm will
* successfully solve problem with N=100.000
*
* Test problem:
* * diagonal term D and rank-K term Q
* * known solution X0,
* * about 50% of constraints are active and equal to components of X0
*/
newton2errors = ae_false;
for(nkind=0; nkind<=5; nkind++)
{
for(k=0; k<=5; k++)
{
n = ae_round(ae_pow((double)(n), (double)(nkind), _state), _state);
/*
* generate problem
*/
ae_vector_set_length(&d, n, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&activeset, n, _state);
if( k>0 )
{
ae_matrix_set_length(&q, k, n, _state);
ae_vector_set_length(&r, k, _state);
}
tau = 1+ae_randomreal(_state);
theta = 1+ae_randomreal(_state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
d.ptr.p_double[i] = 1+ae_randomreal(_state);
b.ptr.p_double[i] = -x0.ptr.p_double[i]*tau*d.ptr.p_double[i];
activeset.ptr.p_bool[i] = ae_fp_greater(ae_randomreal(_state),0.5);
}
for(i=0; i<=k-1; i++)
{
v = 0.0;
for(j=0; j<=n-1; j++)
{
q.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
v = v+q.ptr.pp_double[i][j]*x0.ptr.p_double[j];
}
r.ptr.p_double[i] = v;
}
/*
* Solve, test
*/
cqminit(n, &s, _state);
cqmsetb(&s, &b, _state);
cqmsetd(&s, &d, tau, _state);
cqmsetq(&s, &q, &r, k, theta, _state);
cqmsetactiveset(&s, &x0, &activeset, _state);
if( cqmconstrainedoptimum(&s, &x, _state) )
{
/*
* Check that constraints are satisfied,
* and that solution is true optimum
*/
f0 = cqmeval(&s, &x, _state);
for(i=0; i<=n-1; i++)
{
newton2errors = newton2errors||(activeset.ptr.p_bool[i]&&ae_fp_neq(x.ptr.p_double[i],x0.ptr.p_double[i]));
newton2errors = newton2errors||(!activeset.ptr.p_bool[i]&&ae_fp_greater(ae_fabs(x.ptr.p_double[i]-x0.ptr.p_double[i], _state),1000*ae_machineepsilon));
}
/*
* Check that constrained evaluation at some point gives correct results
*/
for(i=0; i<=n-1; i++)
{
if( activeset.ptr.p_bool[i] )
{
x.ptr.p_double[i] = x0.ptr.p_double[i];
}
else
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
}
v = 0.0;
for(i=0; i<=n-1; i++)
{
v = v+0.5*tau*d.ptr.p_double[i]*ae_sqr(x.ptr.p_double[i], _state)+x.ptr.p_double[i]*b.ptr.p_double[i];
}
for(i=0; i<=k-1; i++)
{
v2 = ae_v_dotproduct(&q.ptr.pp_double[i][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = v+0.5*theta*ae_sqr(v2-r.ptr.p_double[i], _state);
}
v2 = cqmeval(&s, &x, _state);
newton2errors = (newton2errors||!ae_isfinite(v2, _state))||ae_fp_greater(ae_fabs(v-v2, _state),10000*ae_machineepsilon);
v2 = cqmdebugconstrainedevalt(&s, &x, _state);
newton2errors = (newton2errors||!ae_isfinite(v2, _state))||ae_fp_greater(ae_fabs(v-v2, _state),10000*ae_machineepsilon);
v2 = cqmdebugconstrainedevale(&s, &x, _state);
newton2errors = (newton2errors||!ae_isfinite(v2, _state))||ae_fp_greater(ae_fabs(v-v2, _state),10000*ae_machineepsilon);
}
else
{
newton2errors = ae_true;
}
}
}
waserrors = waserrors||newton2errors;
/*
* report
*/
if( !silent )
{
printf("TESTING CONVEX QUADRATIC MODELS\n");
printf("Eval0 test: ");
if( eval0errors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("Eval1 test: ");
if( eval1errors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("Eval2 test: ");
if( eval2errors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("Newton0 test: ");
if( newton0errors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("Newton1 test: ");
if( newton1errors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("Newton2 test: ");
if( newton2errors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
static void testbdsvdunit_fillidentity(/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state);
static void testbdsvdunit_fillsparsede(/* Real */ ae_vector* d,
/* Real */ ae_vector* e,
ae_int_t n,
double sparcity,
ae_state *_state);
static void testbdsvdunit_getbdsvderror(/* Real */ ae_vector* d,
/* Real */ ae_vector* e,
ae_int_t n,
ae_bool isupper,
/* Real */ ae_matrix* u,
/* Real */ ae_matrix* c,
/* Real */ ae_vector* w,
/* Real */ ae_matrix* vt,
double* materr,
double* orterr,
ae_bool* wsorted,
ae_state *_state);
static void testbdsvdunit_checksvdmultiplication(/* Real */ ae_vector* d,
/* Real */ ae_vector* e,
ae_int_t n,
ae_bool isupper,
/* Real */ ae_matrix* u,
/* Real */ ae_matrix* c,
/* Real */ ae_vector* w,
/* Real */ ae_matrix* vt,
double* err,
ae_state *_state);
static void testbdsvdunit_testbdsvdproblem(/* Real */ ae_vector* d,
/* Real */ ae_vector* e,
ae_int_t n,
double* materr,
double* orterr,
ae_bool* wsorted,
ae_bool* wfailed,
ae_int_t* failcount,
ae_int_t* succcount,
ae_state *_state);
/*************************************************************************
Testing bidiagonal SVD decomposition subroutine
*************************************************************************/
ae_bool testbdsvd(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_vector d;
ae_vector e;
ae_matrix mempty;
ae_int_t n;
ae_int_t maxn;
ae_int_t i;
ae_int_t pass;
ae_bool waserrors;
ae_bool wsorted;
ae_bool wfailed;
double materr;
double orterr;
double threshold;
double failr;
ae_int_t failcount;
ae_int_t succcount;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&d, 0, sizeof(d));
memset(&e, 0, sizeof(e));
memset(&mempty, 0, sizeof(mempty));
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&e, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&mempty, 0, 0, DT_REAL, _state, ae_true);
failcount = 0;
succcount = 0;
materr = (double)(0);
orterr = (double)(0);
wsorted = ae_true;
wfailed = ae_false;
waserrors = ae_false;
maxn = 15;
threshold = 5*100*ae_machineepsilon;
ae_vector_set_length(&d, maxn-1+1, _state);
ae_vector_set_length(&e, maxn-2+1, _state);
/*
* special case: zero divide matrix
* unfixed LAPACK routine should fail on this problem
*/
n = 7;
d.ptr.p_double[0] = -6.96462904751731892700e-01;
d.ptr.p_double[1] = 0.00000000000000000000e+00;
d.ptr.p_double[2] = -5.73827770385971991400e-01;
d.ptr.p_double[3] = -6.62562624399371191700e-01;
d.ptr.p_double[4] = 5.82737148001782223600e-01;
d.ptr.p_double[5] = 3.84825263580925003300e-01;
d.ptr.p_double[6] = 9.84087420830525472200e-01;
e.ptr.p_double[0] = -7.30307931760612871800e-02;
e.ptr.p_double[1] = -2.30079042939542843800e-01;
e.ptr.p_double[2] = -6.87824621739351216300e-01;
e.ptr.p_double[3] = -1.77306437707837570600e-02;
e.ptr.p_double[4] = 1.78285126526551632000e-15;
e.ptr.p_double[5] = -4.89434737751289969400e-02;
rmatrixbdsvd(&d, &e, n, ae_true, ae_false, &mempty, 0, &mempty, 0, &mempty, 0, _state);
/*
* zero matrix, several cases
*/
for(i=0; i<=maxn-1; i++)
{
d.ptr.p_double[i] = (double)(0);
}
for(i=0; i<=maxn-2; i++)
{
e.ptr.p_double[i] = (double)(0);
}
for(n=1; n<=maxn; n++)
{
testbdsvdunit_testbdsvdproblem(&d, &e, n, &materr, &orterr, &wsorted, &wfailed, &failcount, &succcount, _state);
}
/*
* Dense matrix
*/
for(n=1; n<=maxn; n++)
{
for(pass=1; pass<=10; pass++)
{
for(i=0; i<=maxn-1; i++)
{
d.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=maxn-2; i++)
{
e.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
testbdsvdunit_testbdsvdproblem(&d, &e, n, &materr, &orterr, &wsorted, &wfailed, &failcount, &succcount, _state);
}
}
/*
* Sparse matrices, very sparse matrices, incredible sparse matrices
*/
for(n=1; n<=maxn; n++)
{
for(pass=1; pass<=10; pass++)
{
testbdsvdunit_fillsparsede(&d, &e, n, 0.5, _state);
testbdsvdunit_testbdsvdproblem(&d, &e, n, &materr, &orterr, &wsorted, &wfailed, &failcount, &succcount, _state);
testbdsvdunit_fillsparsede(&d, &e, n, 0.8, _state);
testbdsvdunit_testbdsvdproblem(&d, &e, n, &materr, &orterr, &wsorted, &wfailed, &failcount, &succcount, _state);
testbdsvdunit_fillsparsede(&d, &e, n, 0.9, _state);
testbdsvdunit_testbdsvdproblem(&d, &e, n, &materr, &orterr, &wsorted, &wfailed, &failcount, &succcount, _state);
testbdsvdunit_fillsparsede(&d, &e, n, 0.95, _state);
testbdsvdunit_testbdsvdproblem(&d, &e, n, &materr, &orterr, &wsorted, &wfailed, &failcount, &succcount, _state);
}
}
/*
* report
*/
failr = (double)failcount/(double)(succcount+failcount);
waserrors = ((wfailed||ae_fp_greater(materr,threshold))||ae_fp_greater(orterr,threshold))||!wsorted;
if( !silent )
{
printf("TESTING BIDIAGONAL SVD DECOMPOSITION\n");
printf("SVD decomposition error: %5.3e\n",
(double)(materr));
printf("SVD orthogonality error: %5.3e\n",
(double)(orterr));
printf("Singular values order: ");
if( wsorted )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("Always converged: ");
if( !wfailed )
{
printf("YES\n");
}
else
{
printf("NO\n");
printf("Fail ratio: %5.3f\n",
(double)(failr));
}
printf("Threshold: %5.3e\n",
(double)(threshold));
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
static void testbdsvdunit_fillidentity(/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_matrix_set_length(a, n-1+1, n-1+1, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( i==j )
{
a->ptr.pp_double[i][j] = (double)(1);
}
else
{
a->ptr.pp_double[i][j] = (double)(0);
}
}
}
}
static void testbdsvdunit_fillsparsede(/* Real */ ae_vector* d,
/* Real */ ae_vector* e,
ae_int_t n,
double sparcity,
ae_state *_state)
{
ae_int_t i;
ae_vector_set_length(d, n-1+1, _state);
ae_vector_set_length(e, ae_maxint(0, n-2, _state)+1, _state);
for(i=0; i<=n-1; i++)
{
if( ae_fp_greater_eq(ae_randomreal(_state),sparcity) )
{
d->ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
else
{
d->ptr.p_double[i] = (double)(0);
}
}
for(i=0; i<=n-2; i++)
{
if( ae_fp_greater_eq(ae_randomreal(_state),sparcity) )
{
e->ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
else
{
e->ptr.p_double[i] = (double)(0);
}
}
}
static void testbdsvdunit_getbdsvderror(/* Real */ ae_vector* d,
/* Real */ ae_vector* e,
ae_int_t n,
ae_bool isupper,
/* Real */ ae_matrix* u,
/* Real */ ae_matrix* c,
/* Real */ ae_vector* w,
/* Real */ ae_matrix* vt,
double* materr,
double* orterr,
ae_bool* wsorted,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_int_t k;
double locerr;
double sm;
/*
* decomposition error
*/
locerr = (double)(0);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
sm = (double)(0);
for(k=0; k<=n-1; k++)
{
sm = sm+w->ptr.p_double[k]*u->ptr.pp_double[i][k]*vt->ptr.pp_double[k][j];
}
if( isupper )
{
if( i==j )
{
locerr = ae_maxreal(locerr, ae_fabs(d->ptr.p_double[i]-sm, _state), _state);
}
else
{
if( i==j-1 )
{
locerr = ae_maxreal(locerr, ae_fabs(e->ptr.p_double[i]-sm, _state), _state);
}
else
{
locerr = ae_maxreal(locerr, ae_fabs(sm, _state), _state);
}
}
}
else
{
if( i==j )
{
locerr = ae_maxreal(locerr, ae_fabs(d->ptr.p_double[i]-sm, _state), _state);
}
else
{
if( i-1==j )
{
locerr = ae_maxreal(locerr, ae_fabs(e->ptr.p_double[j]-sm, _state), _state);
}
else
{
locerr = ae_maxreal(locerr, ae_fabs(sm, _state), _state);
}
}
}
}
}
*materr = ae_maxreal(*materr, locerr, _state);
/*
* check for C = U'
* we consider it as decomposition error
*/
locerr = (double)(0);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
locerr = ae_maxreal(locerr, ae_fabs(u->ptr.pp_double[i][j]-c->ptr.pp_double[j][i], _state), _state);
}
}
*materr = ae_maxreal(*materr, locerr, _state);
/*
* orthogonality error
*/
locerr = (double)(0);
for(i=0; i<=n-1; i++)
{
for(j=i; j<=n-1; j++)
{
sm = ae_v_dotproduct(&u->ptr.pp_double[0][i], u->stride, &u->ptr.pp_double[0][j], u->stride, ae_v_len(0,n-1));
if( i!=j )
{
locerr = ae_maxreal(locerr, ae_fabs(sm, _state), _state);
}
else
{
locerr = ae_maxreal(locerr, ae_fabs(sm-1, _state), _state);
}
sm = ae_v_dotproduct(&vt->ptr.pp_double[i][0], 1, &vt->ptr.pp_double[j][0], 1, ae_v_len(0,n-1));
if( i!=j )
{
locerr = ae_maxreal(locerr, ae_fabs(sm, _state), _state);
}
else
{
locerr = ae_maxreal(locerr, ae_fabs(sm-1, _state), _state);
}
}
}
*orterr = ae_maxreal(*orterr, locerr, _state);
/*
* values order error
*/
for(i=1; i<=n-1; i++)
{
if( ae_fp_greater(w->ptr.p_double[i],w->ptr.p_double[i-1]) )
{
*wsorted = ae_false;
}
}
}
static void testbdsvdunit_checksvdmultiplication(/* Real */ ae_vector* d,
/* Real */ ae_vector* e,
ae_int_t n,
ae_bool isupper,
/* Real */ ae_matrix* u,
/* Real */ ae_matrix* c,
/* Real */ ae_vector* w,
/* Real */ ae_matrix* vt,
double* err,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_vector wt;
ae_matrix u2;
ae_matrix c2;
ae_matrix vt2;
ae_matrix u1;
ae_matrix c1;
ae_matrix vt1;
ae_int_t nru;
ae_int_t ncc;
ae_int_t ncvt;
ae_int_t pass;
hqrndstate rs;
double v;
ae_frame_make(_state, &_frame_block);
memset(&wt, 0, sizeof(wt));
memset(&u2, 0, sizeof(u2));
memset(&c2, 0, sizeof(c2));
memset(&vt2, 0, sizeof(vt2));
memset(&u1, 0, sizeof(u1));
memset(&c1, 0, sizeof(c1));
memset(&vt1, 0, sizeof(vt1));
memset(&rs, 0, sizeof(rs));
ae_vector_init(&wt, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&u2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&vt2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&u1, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c1, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&vt1, 0, 0, DT_REAL, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
ae_vector_set_length(&wt, n, _state);
/*
* Perform nonsquare SVD
*/
for(pass=1; pass<=20; pass++)
{
/*
* Problem size
*/
nru = hqrnduniformi(&rs, 2*n, _state);
ncc = hqrnduniformi(&rs, 2*n, _state);
ncvt = hqrnduniformi(&rs, 2*n, _state);
/*
* Reference matrices (copy 1) and working matrices (copy 2)
*/
for(i=0; i<=n-1; i++)
{
wt.ptr.p_double[i] = d->ptr.p_double[i];
}
if( nru>0 )
{
/*
* init U1/U2
*/
ae_matrix_set_length(&u1, nru, n, _state);
ae_matrix_set_length(&u2, nru, n, _state);
for(i=0; i<=u1.rows-1; i++)
{
for(j=0; j<=u1.cols-1; j++)
{
u1.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5;
u2.ptr.pp_double[i][j] = u1.ptr.pp_double[i][j];
}
}
}
else
{
/*
* Set U1/U2 to 1x1 matrices; working with 1x1 matrices allows
* to test correctness of code which passes them to MKL.
*/
ae_matrix_set_length(&u1, 1, 1, _state);
ae_matrix_set_length(&u2, 1, 1, _state);
}
if( ncc>0 )
{
ae_matrix_set_length(&c1, n, ncc, _state);
ae_matrix_set_length(&c2, n, ncc, _state);
for(i=0; i<=c1.rows-1; i++)
{
for(j=0; j<=c1.cols-1; j++)
{
c1.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5;
c2.ptr.pp_double[i][j] = c1.ptr.pp_double[i][j];
}
}
}
else
{
/*
* Set C1/C1 to 1x1 matrices; working with 1x1 matrices allows
* to test correctness of code which passes them to MKL.
*/
ae_matrix_set_length(&c1, 1, 1, _state);
ae_matrix_set_length(&c2, 1, 1, _state);
}
if( ncvt>0 )
{
ae_matrix_set_length(&vt1, n, ncvt, _state);
ae_matrix_set_length(&vt2, n, ncvt, _state);
for(i=0; i<=vt1.rows-1; i++)
{
for(j=0; j<=vt1.cols-1; j++)
{
vt1.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5;
vt2.ptr.pp_double[i][j] = vt1.ptr.pp_double[i][j];
}
}
}
else
{
/*
* Set VT1/VT1 to 1x1 matrices; working with 1x1 matrices allows
* to test correctness of code which passes them to MKL.
*/
ae_matrix_set_length(&vt1, 1, 1, _state);
ae_matrix_set_length(&vt2, 1, 1, _state);
}
/*
* SVD with non-square U/C/VT
*/
if( !rmatrixbdsvd(&wt, e, n, isupper, ae_fp_greater(hqrnduniformr(&rs, _state),(double)(0)), &u2, nru, &c2, ncc, &vt2, ncvt, _state) )
{
*err = 1.0;
ae_frame_leave(_state);
return;
}
for(i=0; i<=nru-1; i++)
{
for(j=0; j<=u2.cols-1; j++)
{
v = ae_v_dotproduct(&u1.ptr.pp_double[i][0], 1, &u->ptr.pp_double[0][j], u->stride, ae_v_len(0,n-1));
*err = ae_maxreal(*err, ae_fabs(v-u2.ptr.pp_double[i][j], _state), _state);
}
}
for(i=0; i<=c2.rows-1; i++)
{
for(j=0; j<=ncc-1; j++)
{
v = ae_v_dotproduct(&c->ptr.pp_double[i][0], 1, &c1.ptr.pp_double[0][j], c1.stride, ae_v_len(0,n-1));
*err = ae_maxreal(*err, ae_fabs(v-c2.ptr.pp_double[i][j], _state), _state);
}
}
for(i=0; i<=vt2.rows-1; i++)
{
for(j=0; j<=ncvt-1; j++)
{
v = ae_v_dotproduct(&vt->ptr.pp_double[i][0], 1, &vt1.ptr.pp_double[0][j], vt1.stride, ae_v_len(0,n-1));
*err = ae_maxreal(*err, ae_fabs(v-vt2.ptr.pp_double[i][j], _state), _state);
}
}
}
ae_frame_leave(_state);
}
static void testbdsvdunit_testbdsvdproblem(/* Real */ ae_vector* d,
/* Real */ ae_vector* e,
ae_int_t n,
double* materr,
double* orterr,
ae_bool* wsorted,
ae_bool* wfailed,
ae_int_t* failcount,
ae_int_t* succcount,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix u;
ae_matrix vt;
ae_matrix c;
ae_vector w;
ae_int_t i;
double mx;
ae_frame_make(_state, &_frame_block);
memset(&u, 0, sizeof(u));
memset(&vt, 0, sizeof(vt));
memset(&c, 0, sizeof(c));
memset(&w, 0, sizeof(w));
ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&vt, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
mx = (double)(0);
for(i=0; i<=n-1; i++)
{
if( ae_fp_greater(ae_fabs(d->ptr.p_double[i], _state),mx) )
{
mx = ae_fabs(d->ptr.p_double[i], _state);
}
}
for(i=0; i<=n-2; i++)
{
if( ae_fp_greater(ae_fabs(e->ptr.p_double[i], _state),mx) )
{
mx = ae_fabs(e->ptr.p_double[i], _state);
}
}
if( ae_fp_eq(mx,(double)(0)) )
{
mx = (double)(1);
}
/*
* Upper BDSVD tests
*/
ae_vector_set_length(&w, n-1+1, _state);
testbdsvdunit_fillidentity(&u, n, _state);
testbdsvdunit_fillidentity(&vt, n, _state);
testbdsvdunit_fillidentity(&c, n, _state);
for(i=0; i<=n-1; i++)
{
w.ptr.p_double[i] = d->ptr.p_double[i];
}
if( !rmatrixbdsvd(&w, e, n, ae_true, ae_false, &u, n, &c, n, &vt, n, _state) )
{
*failcount = *failcount+1;
*wfailed = ae_true;
ae_frame_leave(_state);
return;
}
testbdsvdunit_getbdsvderror(d, e, n, ae_true, &u, &c, &w, &vt, materr, orterr, wsorted, _state);
testbdsvdunit_checksvdmultiplication(d, e, n, ae_true, &u, &c, &w, &vt, materr, _state);
testbdsvdunit_fillidentity(&u, n, _state);
testbdsvdunit_fillidentity(&vt, n, _state);
testbdsvdunit_fillidentity(&c, n, _state);
for(i=0; i<=n-1; i++)
{
w.ptr.p_double[i] = d->ptr.p_double[i];
}
if( !rmatrixbdsvd(&w, e, n, ae_true, ae_true, &u, n, &c, n, &vt, n, _state) )
{
*failcount = *failcount+1;
*wfailed = ae_true;
ae_frame_leave(_state);
return;
}
testbdsvdunit_getbdsvderror(d, e, n, ae_true, &u, &c, &w, &vt, materr, orterr, wsorted, _state);
testbdsvdunit_checksvdmultiplication(d, e, n, ae_true, &u, &c, &w, &vt, materr, _state);
/*
* Lower BDSVD tests
*/
ae_vector_set_length(&w, n-1+1, _state);
testbdsvdunit_fillidentity(&u, n, _state);
testbdsvdunit_fillidentity(&vt, n, _state);
testbdsvdunit_fillidentity(&c, n, _state);
for(i=0; i<=n-1; i++)
{
w.ptr.p_double[i] = d->ptr.p_double[i];
}
if( !rmatrixbdsvd(&w, e, n, ae_false, ae_false, &u, n, &c, n, &vt, n, _state) )
{
*failcount = *failcount+1;
*wfailed = ae_true;
ae_frame_leave(_state);
return;
}
testbdsvdunit_getbdsvderror(d, e, n, ae_false, &u, &c, &w, &vt, materr, orterr, wsorted, _state);
testbdsvdunit_checksvdmultiplication(d, e, n, ae_false, &u, &c, &w, &vt, materr, _state);
testbdsvdunit_fillidentity(&u, n, _state);
testbdsvdunit_fillidentity(&vt, n, _state);
testbdsvdunit_fillidentity(&c, n, _state);
for(i=0; i<=n-1; i++)
{
w.ptr.p_double[i] = d->ptr.p_double[i];
}
if( !rmatrixbdsvd(&w, e, n, ae_false, ae_true, &u, n, &c, n, &vt, n, _state) )
{
*failcount = *failcount+1;
*wfailed = ae_true;
ae_frame_leave(_state);
return;
}
testbdsvdunit_getbdsvderror(d, e, n, ae_false, &u, &c, &w, &vt, materr, orterr, wsorted, _state);
testbdsvdunit_checksvdmultiplication(d, e, n, ae_false, &u, &c, &w, &vt, materr, _state);
/*
* update counter
*/
*succcount = *succcount+1;
ae_frame_leave(_state);
}
static void testblasunit_naivematrixmatrixmultiply(/* Real */ ae_matrix* a,
ae_int_t ai1,
ae_int_t ai2,
ae_int_t aj1,
ae_int_t aj2,
ae_bool transa,
/* Real */ ae_matrix* b,
ae_int_t bi1,
ae_int_t bi2,
ae_int_t bj1,
ae_int_t bj2,
ae_bool transb,
double alpha,
/* Real */ ae_matrix* c,
ae_int_t ci1,
ae_int_t ci2,
ae_int_t cj1,
ae_int_t cj2,
double beta,
ae_state *_state);
ae_bool testblas(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t pass;
ae_int_t passcount;
ae_int_t n;
ae_int_t i;
ae_int_t i1;
ae_int_t i2;
ae_int_t j;
ae_int_t j1;
ae_int_t j2;
ae_int_t l;
ae_int_t k;
ae_int_t r;
ae_int_t i3;
ae_int_t j3;
ae_int_t col1;
ae_int_t col2;
ae_int_t row1;
ae_int_t row2;
ae_vector x1;
ae_vector x2;
ae_matrix a;
ae_matrix b;
ae_matrix c1;
ae_matrix c2;
double err;
double e1;
double e2;
double e3;
double v;
double scl1;
double scl2;
double scl3;
ae_bool was1;
ae_bool was2;
ae_bool trans1;
ae_bool trans2;
double threshold;
ae_bool n2errors;
ae_bool hsnerrors;
ae_bool amaxerrors;
ae_bool mverrors;
ae_bool iterrors;
ae_bool cterrors;
ae_bool mmerrors;
ae_bool waserrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&x1, 0, sizeof(x1));
memset(&x2, 0, sizeof(x2));
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
memset(&c1, 0, sizeof(c1));
memset(&c2, 0, sizeof(c2));
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c1, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c2, 0, 0, DT_REAL, _state, ae_true);
n2errors = ae_false;
amaxerrors = ae_false;
hsnerrors = ae_false;
mverrors = ae_false;
iterrors = ae_false;
cterrors = ae_false;
mmerrors = ae_false;
waserrors = ae_false;
threshold = 10000*ae_machineepsilon;
/*
* Test Norm2
*/
passcount = 1000;
e1 = (double)(0);
e2 = (double)(0);
e3 = (double)(0);
scl2 = 0.5*ae_maxrealnumber;
scl3 = 2*ae_minrealnumber;
for(pass=1; pass<=passcount; pass++)
{
n = 1+ae_randominteger(1000, _state);
i1 = ae_randominteger(10, _state);
i2 = n+i1-1;
ae_vector_set_length(&x1, i2+1, _state);
ae_vector_set_length(&x2, i2+1, _state);
for(i=i1; i<=i2; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
v = (double)(0);
for(i=i1; i<=i2; i++)
{
v = v+ae_sqr(x1.ptr.p_double[i], _state);
}
v = ae_sqrt(v, _state);
e1 = ae_maxreal(e1, ae_fabs(v-vectornorm2(&x1, i1, i2, _state), _state), _state);
for(i=i1; i<=i2; i++)
{
x2.ptr.p_double[i] = scl2*x1.ptr.p_double[i];
}
e2 = ae_maxreal(e2, ae_fabs(v*scl2-vectornorm2(&x2, i1, i2, _state), _state), _state);
for(i=i1; i<=i2; i++)
{
x2.ptr.p_double[i] = scl3*x1.ptr.p_double[i];
}
e3 = ae_maxreal(e3, ae_fabs(v*scl3-vectornorm2(&x2, i1, i2, _state), _state), _state);
}
e2 = e2/scl2;
e3 = e3/scl3;
n2errors = (ae_fp_greater_eq(e1,threshold)||ae_fp_greater_eq(e2,threshold))||ae_fp_greater_eq(e3,threshold);
/*
* Testing VectorAbsMax, Column/Row AbsMax
*/
ae_vector_set_length(&x1, 5+1, _state);
x1.ptr.p_double[1] = 2.0;
x1.ptr.p_double[2] = 0.2;
x1.ptr.p_double[3] = -1.3;
x1.ptr.p_double[4] = 0.7;
x1.ptr.p_double[5] = -3.0;
amaxerrors = (vectoridxabsmax(&x1, 1, 5, _state)!=5||vectoridxabsmax(&x1, 1, 4, _state)!=1)||vectoridxabsmax(&x1, 2, 4, _state)!=3;
n = 30;
ae_vector_set_length(&x1, n+1, _state);
ae_matrix_set_length(&a, n+1, n+1, _state);
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
was1 = ae_false;
was2 = ae_false;
for(pass=1; pass<=1000; pass++)
{
j = 1+ae_randominteger(n, _state);
i1 = 1+ae_randominteger(n, _state);
i2 = i1+ae_randominteger(n+1-i1, _state);
ae_v_move(&x1.ptr.p_double[i1], 1, &a.ptr.pp_double[i1][j], a.stride, ae_v_len(i1,i2));
if( vectoridxabsmax(&x1, i1, i2, _state)!=columnidxabsmax(&a, i1, i2, j, _state) )
{
was1 = ae_true;
}
i = 1+ae_randominteger(n, _state);
j1 = 1+ae_randominteger(n, _state);
j2 = j1+ae_randominteger(n+1-j1, _state);
ae_v_move(&x1.ptr.p_double[j1], 1, &a.ptr.pp_double[i][j1], 1, ae_v_len(j1,j2));
if( vectoridxabsmax(&x1, j1, j2, _state)!=rowidxabsmax(&a, j1, j2, i, _state) )
{
was2 = ae_true;
}
}
amaxerrors = (amaxerrors||was1)||was2;
/*
* Testing upper Hessenberg 1-norm
*/
ae_matrix_set_length(&a, 3+1, 3+1, _state);
ae_vector_set_length(&x1, 3+1, _state);
a.ptr.pp_double[1][1] = (double)(2);
a.ptr.pp_double[1][2] = (double)(3);
a.ptr.pp_double[1][3] = (double)(1);
a.ptr.pp_double[2][1] = (double)(4);
a.ptr.pp_double[2][2] = (double)(-5);
a.ptr.pp_double[2][3] = (double)(8);
a.ptr.pp_double[3][1] = (double)(99);
a.ptr.pp_double[3][2] = (double)(3);
a.ptr.pp_double[3][3] = (double)(1);
hsnerrors = ae_fp_greater(ae_fabs(upperhessenberg1norm(&a, 1, 3, 1, 3, &x1, _state)-11, _state),threshold);
/*
* Testing MatrixVectorMultiply
*/
ae_matrix_set_length(&a, 3+1, 5+1, _state);
ae_vector_set_length(&x1, 3+1, _state);
ae_vector_set_length(&x2, 2+1, _state);
a.ptr.pp_double[2][3] = (double)(2);
a.ptr.pp_double[2][4] = (double)(-1);
a.ptr.pp_double[2][5] = (double)(-1);
a.ptr.pp_double[3][3] = (double)(1);
a.ptr.pp_double[3][4] = (double)(-2);
a.ptr.pp_double[3][5] = (double)(2);
x1.ptr.p_double[1] = (double)(1);
x1.ptr.p_double[2] = (double)(2);
x1.ptr.p_double[3] = (double)(1);
x2.ptr.p_double[1] = (double)(-1);
x2.ptr.p_double[2] = (double)(-1);
matrixvectormultiply(&a, 2, 3, 3, 5, ae_false, &x1, 1, 3, 1.0, &x2, 1, 2, 1.0, _state);
matrixvectormultiply(&a, 2, 3, 3, 5, ae_true, &x2, 1, 2, 1.0, &x1, 1, 3, 1.0, _state);
e1 = ae_fabs(x1.ptr.p_double[1]+5, _state)+ae_fabs(x1.ptr.p_double[2]-8, _state)+ae_fabs(x1.ptr.p_double[3]+1, _state)+ae_fabs(x2.ptr.p_double[1]+2, _state)+ae_fabs(x2.ptr.p_double[2]+2, _state);
x1.ptr.p_double[1] = (double)(1);
x1.ptr.p_double[2] = (double)(2);
x1.ptr.p_double[3] = (double)(1);
x2.ptr.p_double[1] = (double)(-1);
x2.ptr.p_double[2] = (double)(-1);
matrixvectormultiply(&a, 2, 3, 3, 5, ae_false, &x1, 1, 3, 1.0, &x2, 1, 2, 0.0, _state);
matrixvectormultiply(&a, 2, 3, 3, 5, ae_true, &x2, 1, 2, 1.0, &x1, 1, 3, 0.0, _state);
e2 = ae_fabs(x1.ptr.p_double[1]+3, _state)+ae_fabs(x1.ptr.p_double[2]-3, _state)+ae_fabs(x1.ptr.p_double[3]+1, _state)+ae_fabs(x2.ptr.p_double[1]+1, _state)+ae_fabs(x2.ptr.p_double[2]+1, _state);
mverrors = ae_fp_greater_eq(e1+e2,threshold);
/*
* testing inplace transpose
*/
n = 10;
ae_matrix_set_length(&a, n+1, n+1, _state);
ae_matrix_set_length(&b, n+1, n+1, _state);
ae_vector_set_length(&x1, n-1+1, _state);
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
a.ptr.pp_double[i][j] = ae_randomreal(_state);
}
}
passcount = 10000;
was1 = ae_false;
for(pass=1; pass<=passcount; pass++)
{
i1 = 1+ae_randominteger(n, _state);
i2 = i1+ae_randominteger(n-i1+1, _state);
j1 = 1+ae_randominteger(n-(i2-i1), _state);
j2 = j1+(i2-i1);
copymatrix(&a, i1, i2, j1, j2, &b, i1, i2, j1, j2, _state);
inplacetranspose(&b, i1, i2, j1, j2, &x1, _state);
for(i=i1; i<=i2; i++)
{
for(j=j1; j<=j2; j++)
{
if( ae_fp_neq(a.ptr.pp_double[i][j],b.ptr.pp_double[i1+(j-j1)][j1+(i-i1)]) )
{
was1 = ae_true;
}
}
}
}
iterrors = was1;
/*
* testing copy and transpose
*/
n = 10;
ae_matrix_set_length(&a, n+1, n+1, _state);
ae_matrix_set_length(&b, n+1, n+1, _state);
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
a.ptr.pp_double[i][j] = ae_randomreal(_state);
}
}
passcount = 10000;
was1 = ae_false;
for(pass=1; pass<=passcount; pass++)
{
i1 = 1+ae_randominteger(n, _state);
i2 = i1+ae_randominteger(n-i1+1, _state);
j1 = 1+ae_randominteger(n, _state);
j2 = j1+ae_randominteger(n-j1+1, _state);
copyandtranspose(&a, i1, i2, j1, j2, &b, j1, j2, i1, i2, _state);
for(i=i1; i<=i2; i++)
{
for(j=j1; j<=j2; j++)
{
if( ae_fp_neq(a.ptr.pp_double[i][j],b.ptr.pp_double[j][i]) )
{
was1 = ae_true;
}
}
}
}
cterrors = was1;
/*
* Testing MatrixMatrixMultiply
*/
n = 10;
ae_matrix_set_length(&a, 2*n+1, 2*n+1, _state);
ae_matrix_set_length(&b, 2*n+1, 2*n+1, _state);
ae_matrix_set_length(&c1, 2*n+1, 2*n+1, _state);
ae_matrix_set_length(&c2, 2*n+1, 2*n+1, _state);
ae_vector_set_length(&x1, n+1, _state);
ae_vector_set_length(&x2, n+1, _state);
for(i=1; i<=2*n; i++)
{
for(j=1; j<=2*n; j++)
{
a.ptr.pp_double[i][j] = ae_randomreal(_state);
b.ptr.pp_double[i][j] = ae_randomreal(_state);
}
}
passcount = 1000;
was1 = ae_false;
for(pass=1; pass<=passcount; pass++)
{
for(i=1; i<=2*n; i++)
{
for(j=1; j<=2*n; j++)
{
c1.ptr.pp_double[i][j] = 2.1*i+3.1*j;
c2.ptr.pp_double[i][j] = c1.ptr.pp_double[i][j];
}
}
l = 1+ae_randominteger(n, _state);
k = 1+ae_randominteger(n, _state);
r = 1+ae_randominteger(n, _state);
i1 = 1+ae_randominteger(n, _state);
j1 = 1+ae_randominteger(n, _state);
i2 = 1+ae_randominteger(n, _state);
j2 = 1+ae_randominteger(n, _state);
i3 = 1+ae_randominteger(n, _state);
j3 = 1+ae_randominteger(n, _state);
trans1 = ae_fp_greater(ae_randomreal(_state),0.5);
trans2 = ae_fp_greater(ae_randomreal(_state),0.5);
if( trans1 )
{
col1 = l;
row1 = k;
}
else
{
col1 = k;
row1 = l;
}
if( trans2 )
{
col2 = k;
row2 = r;
}
else
{
col2 = r;
row2 = k;
}
scl1 = ae_randomreal(_state);
scl2 = ae_randomreal(_state);
matrixmatrixmultiply(&a, i1, i1+row1-1, j1, j1+col1-1, trans1, &b, i2, i2+row2-1, j2, j2+col2-1, trans2, scl1, &c1, i3, i3+l-1, j3, j3+r-1, scl2, &x1, _state);
testblasunit_naivematrixmatrixmultiply(&a, i1, i1+row1-1, j1, j1+col1-1, trans1, &b, i2, i2+row2-1, j2, j2+col2-1, trans2, scl1, &c2, i3, i3+l-1, j3, j3+r-1, scl2, _state);
err = (double)(0);
for(i=1; i<=l; i++)
{
for(j=1; j<=r; j++)
{
err = ae_maxreal(err, ae_fabs(c1.ptr.pp_double[i3+i-1][j3+j-1]-c2.ptr.pp_double[i3+i-1][j3+j-1], _state), _state);
}
}
if( ae_fp_greater(err,threshold) )
{
was1 = ae_true;
break;
}
}
mmerrors = was1;
/*
* report
*/
waserrors = (((((n2errors||amaxerrors)||hsnerrors)||mverrors)||iterrors)||cterrors)||mmerrors;
if( !silent )
{
printf("TESTING BLAS\n");
printf("VectorNorm2: ");
if( n2errors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("AbsMax (vector/row/column): ");
if( amaxerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("UpperHessenberg1Norm: ");
if( hsnerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("MatrixVectorMultiply: ");
if( mverrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("InplaceTranspose: ");
if( iterrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("CopyAndTranspose: ");
if( cterrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("MatrixMatrixMultiply: ");
if( mmerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
static void testblasunit_naivematrixmatrixmultiply(/* Real */ ae_matrix* a,
ae_int_t ai1,
ae_int_t ai2,
ae_int_t aj1,
ae_int_t aj2,
ae_bool transa,
/* Real */ ae_matrix* b,
ae_int_t bi1,
ae_int_t bi2,
ae_int_t bj1,
ae_int_t bj2,
ae_bool transb,
double alpha,
/* Real */ ae_matrix* c,
ae_int_t ci1,
ae_int_t ci2,
ae_int_t cj1,
ae_int_t cj2,
double beta,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t arows;
ae_int_t acols;
ae_int_t brows;
ae_int_t bcols;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t l;
ae_int_t r;
double v;
ae_vector x1;
ae_vector x2;
ae_frame_make(_state, &_frame_block);
memset(&x1, 0, sizeof(x1));
memset(&x2, 0, sizeof(x2));
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
/*
* Setup
*/
if( !transa )
{
arows = ai2-ai1+1;
acols = aj2-aj1+1;
}
else
{
arows = aj2-aj1+1;
acols = ai2-ai1+1;
}
if( !transb )
{
brows = bi2-bi1+1;
bcols = bj2-bj1+1;
}
else
{
brows = bj2-bj1+1;
bcols = bi2-bi1+1;
}
ae_assert(acols==brows, "NaiveMatrixMatrixMultiply: incorrect matrix sizes!", _state);
if( ((arows<=0||acols<=0)||brows<=0)||bcols<=0 )
{
ae_frame_leave(_state);
return;
}
l = arows;
r = bcols;
k = acols;
ae_vector_set_length(&x1, k+1, _state);
ae_vector_set_length(&x2, k+1, _state);
for(i=1; i<=l; i++)
{
for(j=1; j<=r; j++)
{
if( !transa )
{
if( !transb )
{
v = ae_v_dotproduct(&b->ptr.pp_double[bi1][bj1+j-1], b->stride, &a->ptr.pp_double[ai1+i-1][aj1], 1, ae_v_len(bi1,bi2));
}
else
{
v = ae_v_dotproduct(&b->ptr.pp_double[bi1+j-1][bj1], 1, &a->ptr.pp_double[ai1+i-1][aj1], 1, ae_v_len(bj1,bj2));
}
}
else
{
if( !transb )
{
v = ae_v_dotproduct(&b->ptr.pp_double[bi1][bj1+j-1], b->stride, &a->ptr.pp_double[ai1][aj1+i-1], a->stride, ae_v_len(bi1,bi2));
}
else
{
v = ae_v_dotproduct(&b->ptr.pp_double[bi1+j-1][bj1], 1, &a->ptr.pp_double[ai1][aj1+i-1], a->stride, ae_v_len(bj1,bj2));
}
}
if( ae_fp_eq(beta,(double)(0)) )
{
c->ptr.pp_double[ci1+i-1][cj1+j-1] = alpha*v;
}
else
{
c->ptr.pp_double[ci1+i-1][cj1+j-1] = beta*c->ptr.pp_double[ci1+i-1][cj1+j-1]+alpha*v;
}
}
}
ae_frame_leave(_state);
}
static void testsvdunit_fillsparsea(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double sparcity,
ae_state *_state);
static void testsvdunit_getsvderror(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Real */ ae_matrix* u,
/* Real */ ae_vector* w,
/* Real */ ae_matrix* vt,
double* materr,
double* orterr,
ae_bool* wsorted,
ae_state *_state);
static void testsvdunit_testsvdproblem(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double* materr,
double* orterr,
double* othererr,
ae_bool* wsorted,
ae_bool* wfailed,
ae_int_t* failcount,
ae_int_t* succcount,
ae_state *_state);
/*************************************************************************
Testing SVD decomposition subroutine
*************************************************************************/
ae_bool testsvd(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_int_t m;
ae_int_t n;
ae_int_t maxmn;
ae_int_t i;
ae_int_t j;
ae_int_t gpass;
ae_int_t pass;
ae_bool waserrors;
ae_bool wsorted;
ae_bool wfailed;
double materr;
double orterr;
double othererr;
double threshold;
double failr;
ae_int_t failcount;
ae_int_t succcount;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
failcount = 0;
succcount = 0;
materr = (double)(0);
orterr = (double)(0);
othererr = (double)(0);
wsorted = ae_true;
wfailed = ae_false;
waserrors = ae_false;
maxmn = 30;
threshold = 5*100*ae_machineepsilon;
ae_matrix_set_length(&a, maxmn-1+1, maxmn-1+1, _state);
/*
* TODO: div by zero fail, convergence fail
*/
for(gpass=1; gpass<=1; gpass++)
{
/*
* zero matrix, several cases
*/
for(i=0; i<=maxmn-1; i++)
{
for(j=0; j<=maxmn-1; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
for(i=1; i<=ae_minint(5, maxmn, _state); i++)
{
for(j=1; j<=ae_minint(5, maxmn, _state); j++)
{
testsvdunit_testsvdproblem(&a, i, j, &materr, &orterr, &othererr, &wsorted, &wfailed, &failcount, &succcount, _state);
}
}
/*
* Long dense matrix
*/
for(i=0; i<=maxmn-1; i++)
{
for(j=0; j<=ae_minint(5, maxmn, _state)-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
for(i=1; i<=maxmn; i++)
{
for(j=1; j<=ae_minint(5, maxmn, _state); j++)
{
testsvdunit_testsvdproblem(&a, i, j, &materr, &orterr, &othererr, &wsorted, &wfailed, &failcount, &succcount, _state);
}
}
for(i=0; i<=ae_minint(5, maxmn, _state)-1; i++)
{
for(j=0; j<=maxmn-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
for(i=1; i<=ae_minint(5, maxmn, _state); i++)
{
for(j=1; j<=maxmn; j++)
{
testsvdunit_testsvdproblem(&a, i, j, &materr, &orterr, &othererr, &wsorted, &wfailed, &failcount, &succcount, _state);
}
}
/*
* Dense matrices
*/
for(m=1; m<=ae_minint(10, maxmn, _state); m++)
{
for(n=1; n<=ae_minint(10, maxmn, _state); n++)
{
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
testsvdunit_testsvdproblem(&a, m, n, &materr, &orterr, &othererr, &wsorted, &wfailed, &failcount, &succcount, _state);
}
}
/*
* Sparse matrices, very sparse matrices, incredible sparse matrices
*/
for(m=1; m<=10; m++)
{
for(n=1; n<=10; n++)
{
for(pass=1; pass<=2; pass++)
{
testsvdunit_fillsparsea(&a, m, n, 0.8, _state);
testsvdunit_testsvdproblem(&a, m, n, &materr, &orterr, &othererr, &wsorted, &wfailed, &failcount, &succcount, _state);
testsvdunit_fillsparsea(&a, m, n, 0.9, _state);
testsvdunit_testsvdproblem(&a, m, n, &materr, &orterr, &othererr, &wsorted, &wfailed, &failcount, &succcount, _state);
testsvdunit_fillsparsea(&a, m, n, 0.95, _state);
testsvdunit_testsvdproblem(&a, m, n, &materr, &orterr, &othererr, &wsorted, &wfailed, &failcount, &succcount, _state);
}
}
}
}
/*
* report
*/
failr = (double)failcount/(double)(succcount+failcount);
waserrors = (((wfailed||ae_fp_greater(materr,threshold))||ae_fp_greater(orterr,threshold))||ae_fp_greater(othererr,threshold))||!wsorted;
if( !silent )
{
printf("TESTING SVD DECOMPOSITION\n");
printf("SVD decomposition error: %5.3e\n",
(double)(materr));
printf("SVD orthogonality error: %5.3e\n",
(double)(orterr));
printf("SVD with different parameters error: %5.3e\n",
(double)(othererr));
printf("Singular values order: ");
if( wsorted )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("Always converged: ");
if( !wfailed )
{
printf("YES\n");
}
else
{
printf("NO\n");
printf("Fail ratio: %5.3f\n",
(double)(failr));
}
printf("Threshold: %5.3e\n",
(double)(threshold));
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
static void testsvdunit_fillsparsea(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double sparcity,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_greater_eq(ae_randomreal(_state),sparcity) )
{
a->ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
else
{
a->ptr.pp_double[i][j] = (double)(0);
}
}
}
}
static void testsvdunit_getsvderror(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Real */ ae_matrix* u,
/* Real */ ae_vector* w,
/* Real */ ae_matrix* vt,
double* materr,
double* orterr,
ae_bool* wsorted,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t minmn;
double locerr;
double sm;
minmn = ae_minint(m, n, _state);
/*
* decomposition error
*/
locerr = (double)(0);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
sm = (double)(0);
for(k=0; k<=minmn-1; k++)
{
sm = sm+w->ptr.p_double[k]*u->ptr.pp_double[i][k]*vt->ptr.pp_double[k][j];
}
locerr = ae_maxreal(locerr, ae_fabs(a->ptr.pp_double[i][j]-sm, _state), _state);
}
}
*materr = ae_maxreal(*materr, locerr, _state);
/*
* orthogonality error
*/
locerr = (double)(0);
for(i=0; i<=minmn-1; i++)
{
for(j=i; j<=minmn-1; j++)
{
sm = ae_v_dotproduct(&u->ptr.pp_double[0][i], u->stride, &u->ptr.pp_double[0][j], u->stride, ae_v_len(0,m-1));
if( i!=j )
{
locerr = ae_maxreal(locerr, ae_fabs(sm, _state), _state);
}
else
{
locerr = ae_maxreal(locerr, ae_fabs(sm-1, _state), _state);
}
sm = ae_v_dotproduct(&vt->ptr.pp_double[i][0], 1, &vt->ptr.pp_double[j][0], 1, ae_v_len(0,n-1));
if( i!=j )
{
locerr = ae_maxreal(locerr, ae_fabs(sm, _state), _state);
}
else
{
locerr = ae_maxreal(locerr, ae_fabs(sm-1, _state), _state);
}
}
}
*orterr = ae_maxreal(*orterr, locerr, _state);
/*
* values order error
*/
for(i=1; i<=minmn-1; i++)
{
if( ae_fp_greater(w->ptr.p_double[i],w->ptr.p_double[i-1]) )
{
*wsorted = ae_false;
}
}
}
static void testsvdunit_testsvdproblem(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double* materr,
double* orterr,
double* othererr,
ae_bool* wsorted,
ae_bool* wfailed,
ae_int_t* failcount,
ae_int_t* succcount,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix u;
ae_matrix vt;
ae_matrix u2;
ae_matrix vt2;
ae_vector w;
ae_vector w2;
ae_int_t i;
ae_int_t j;
ae_int_t ujob;
ae_int_t vtjob;
ae_int_t memjob;
ae_int_t ucheck;
ae_int_t vtcheck;
ae_frame_make(_state, &_frame_block);
memset(&u, 0, sizeof(u));
memset(&vt, 0, sizeof(vt));
memset(&u2, 0, sizeof(u2));
memset(&vt2, 0, sizeof(vt2));
memset(&w, 0, sizeof(w));
memset(&w2, 0, sizeof(w2));
ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&vt, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&u2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&vt2, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
/*
* Main SVD test
*/
if( !rmatrixsvd(a, m, n, 2, 2, 2, &w, &u, &vt, _state) )
{
*failcount = *failcount+1;
*wfailed = ae_true;
ae_frame_leave(_state);
return;
}
testsvdunit_getsvderror(a, m, n, &u, &w, &vt, materr, orterr, wsorted, _state);
/*
* Additional SVD tests
*/
for(ujob=0; ujob<=2; ujob++)
{
for(vtjob=0; vtjob<=2; vtjob++)
{
for(memjob=0; memjob<=2; memjob++)
{
if( !rmatrixsvd(a, m, n, ujob, vtjob, memjob, &w2, &u2, &vt2, _state) )
{
*failcount = *failcount+1;
*wfailed = ae_true;
ae_frame_leave(_state);
return;
}
ucheck = 0;
if( ujob==1 )
{
ucheck = ae_minint(m, n, _state);
}
if( ujob==2 )
{
ucheck = m;
}
vtcheck = 0;
if( vtjob==1 )
{
vtcheck = ae_minint(m, n, _state);
}
if( vtjob==2 )
{
vtcheck = n;
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=ucheck-1; j++)
{
*othererr = ae_maxreal(*othererr, ae_fabs(u.ptr.pp_double[i][j]-u2.ptr.pp_double[i][j], _state), _state);
}
}
for(i=0; i<=vtcheck-1; i++)
{
for(j=0; j<=n-1; j++)
{
*othererr = ae_maxreal(*othererr, ae_fabs(vt.ptr.pp_double[i][j]-vt2.ptr.pp_double[i][j], _state), _state);
}
}
for(i=0; i<=ae_minint(m, n, _state)-1; i++)
{
*othererr = ae_maxreal(*othererr, ae_fabs(w.ptr.p_double[i]-w2.ptr.p_double[i], _state), _state);
}
}
}
}
/*
* update counter
*/
*succcount = *succcount+1;
ae_frame_leave(_state);
}
static void testoptservunit_testprec(ae_bool* wereerrors,
ae_state *_state);
ae_bool testoptserv(ae_bool silent, ae_state *_state)
{
ae_bool precerrors;
ae_bool wereerrors;
ae_bool result;
precerrors = ae_false;
testoptservunit_testprec(&precerrors, _state);
/*
* report
*/
wereerrors = precerrors;
if( !silent )
{
printf("TESTING OPTSERV\n");
printf("TESTS: \n");
printf("* PRECONDITIONERS ");
if( precerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( wereerrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !wereerrors;
return result;
}
/*************************************************************************
This function checks preconditioning functions
On failure sets error flag.
*************************************************************************/
static void testoptservunit_testprec(ae_bool* wereerrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t k;
ae_int_t i;
ae_int_t j;
ae_int_t i0;
ae_int_t j0;
ae_int_t j1;
double v;
double rho;
double theta;
double tolg;
ae_matrix va;
ae_vector vc;
ae_vector vd;
ae_vector vb;
ae_vector s0;
ae_vector s1;
ae_vector s2;
ae_vector g;
precbuflbfgs buf;
precbuflowrank lowrankbuf;
ae_vector norms;
ae_matrix sk;
ae_matrix yk;
ae_matrix bk;
ae_vector bksk;
ae_vector tmp;
matinvreport rep;
hqrndstate rs;
ae_frame_make(_state, &_frame_block);
memset(&va, 0, sizeof(va));
memset(&vc, 0, sizeof(vc));
memset(&vd, 0, sizeof(vd));
memset(&vb, 0, sizeof(vb));
memset(&s0, 0, sizeof(s0));
memset(&s1, 0, sizeof(s1));
memset(&s2, 0, sizeof(s2));
memset(&g, 0, sizeof(g));
memset(&buf, 0, sizeof(buf));
memset(&lowrankbuf, 0, sizeof(lowrankbuf));
memset(&norms, 0, sizeof(norms));
memset(&sk, 0, sizeof(sk));
memset(&yk, 0, sizeof(yk));
memset(&bk, 0, sizeof(bk));
memset(&bksk, 0, sizeof(bksk));
memset(&tmp, 0, sizeof(tmp));
memset(&rep, 0, sizeof(rep));
memset(&rs, 0, sizeof(rs));
ae_matrix_init(&va, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&vc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&vd, 0, DT_REAL, _state, ae_true);
ae_vector_init(&vb, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&g, 0, DT_REAL, _state, ae_true);
_precbuflbfgs_init(&buf, _state, ae_true);
_precbuflowrank_init(&lowrankbuf, _state, ae_true);
ae_vector_init(&norms, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&sk, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&yk, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&bk, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bksk, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
_matinvreport_init(&rep, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Test for inexact L-BFGS preconditioner.
*
* We generate QP problem 0.5*x'*H*x, with random H=D+V'*C*V.
* Different K's, from 0 to N, are tried. We test preconditioner
* code which uses compact L-BFGS update against reference implementation
* which uses non-compact BFGS scheme.
*
* For each K we perform two tests: first for KxN non-zero matrix V,
* second one for NxN matrix V with last N-K rows set to zero. Last test
* checks algorithm's ability to handle zero updates.
*/
tolg = 1.0E-9;
for(n=1; n<=10; n++)
{
for(k=0; k<=n; k++)
{
/*
* Prepare problem:
* * VD, VC, VA, with VC/VA reordered by ascending of VC[i]*norm(VA[i,...])^2
* * trial vector S (copies are stored to S0,S1,S2)
*/
ae_vector_set_length(&vd, n, _state);
ae_vector_set_length(&s0, n, _state);
ae_vector_set_length(&s1, n, _state);
ae_vector_set_length(&s2, n, _state);
for(i=0; i<=n-1; i++)
{
vd.ptr.p_double[i] = ae_exp(hqrndnormal(&rs, _state), _state);
s0.ptr.p_double[i] = hqrndnormal(&rs, _state);
s1.ptr.p_double[i] = s0.ptr.p_double[i];
s2.ptr.p_double[i] = s0.ptr.p_double[i];
}
rmatrixrndcond(n, 1.0E2, &va, _state);
rvectorsetlengthatleast(&vc, n, _state);
for(i=0; i<=k-1; i++)
{
vc.ptr.p_double[i] = ae_exp(hqrndnormal(&rs, _state), _state);
}
for(i=k; i<=n-1; i++)
{
vc.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
va.ptr.pp_double[i][j] = 0.0;
}
}
ae_vector_set_length(&norms, k, _state);
for(i=0; i<=k-1; i++)
{
v = ae_v_dotproduct(&va.ptr.pp_double[i][0], 1, &va.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
norms.ptr.p_double[i] = v*vc.ptr.p_double[i];
}
for(i=0; i<=k-1; i++)
{
for(j=0; j<=k-2; j++)
{
if( ae_fp_greater(norms.ptr.p_double[j],norms.ptr.p_double[j+1]) )
{
/*
* Swap elements J and J+1
*/
v = norms.ptr.p_double[j];
norms.ptr.p_double[j] = norms.ptr.p_double[j+1];
norms.ptr.p_double[j+1] = v;
v = vc.ptr.p_double[j];
vc.ptr.p_double[j] = vc.ptr.p_double[j+1];
vc.ptr.p_double[j+1] = v;
for(j0=0; j0<=n-1; j0++)
{
v = va.ptr.pp_double[j][j0];
va.ptr.pp_double[j][j0] = va.ptr.pp_double[j+1][j0];
va.ptr.pp_double[j+1][j0] = v;
}
}
}
}
/*
* Generate reference model and apply it to S2:
* * generate approximate Hessian Bk
* * calculate inv(Bk)
* * calculate inv(Bk)*S2, store to S2
*/
rmatrixsetlengthatleast(&sk, k, n, _state);
rmatrixsetlengthatleast(&yk, k, n, _state);
ae_matrix_set_length(&bk, n, n, _state);
ae_vector_set_length(&bksk, n, _state);
ae_vector_set_length(&tmp, n, _state);
for(i=0; i<=k-1; i++)
{
ae_v_move(&sk.ptr.pp_double[i][0], 1, &va.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
v = ae_v_dotproduct(&va.ptr.pp_double[i][0], 1, &sk.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
v = v*vc.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
yk.ptr.pp_double[i][j] = vd.ptr.p_double[j]*sk.ptr.pp_double[i][j]+va.ptr.pp_double[i][j]*v;
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( i==j )
{
bk.ptr.pp_double[i][i] = vd.ptr.p_double[i];
}
else
{
bk.ptr.pp_double[i][j] = 0.0;
}
}
}
for(i=0; i<=k-1; i++)
{
theta = 0.0;
for(j0=0; j0<=n-1; j0++)
{
bksk.ptr.p_double[j0] = (double)(0);
for(j1=0; j1<=n-1; j1++)
{
theta = theta+sk.ptr.pp_double[i][j0]*bk.ptr.pp_double[j0][j1]*sk.ptr.pp_double[i][j1];
bksk.ptr.p_double[j0] = bksk.ptr.p_double[j0]+bk.ptr.pp_double[j0][j1]*sk.ptr.pp_double[i][j1];
}
}
theta = 1/theta;
rho = ae_v_dotproduct(&sk.ptr.pp_double[i][0], 1, &yk.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
rho = 1/rho;
for(j0=0; j0<=n-1; j0++)
{
for(j1=0; j1<=n-1; j1++)
{
bk.ptr.pp_double[j0][j1] = bk.ptr.pp_double[j0][j1]+rho*yk.ptr.pp_double[i][j0]*yk.ptr.pp_double[i][j1];
}
}
for(j0=0; j0<=n-1; j0++)
{
for(j1=0; j1<=n-1; j1++)
{
bk.ptr.pp_double[j0][j1] = bk.ptr.pp_double[j0][j1]-theta*bksk.ptr.p_double[j0]*bksk.ptr.p_double[j1];
}
}
}
rmatrixinverse(&bk, n, &j0, &rep, _state);
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&bk.ptr.pp_double[i][0], 1, &s2.ptr.p_double[0], 1, ae_v_len(0,n-1));
tmp.ptr.p_double[i] = v;
}
for(i=0; i<=n-1; i++)
{
s2.ptr.p_double[i] = tmp.ptr.p_double[i];
}
/*
* First test for non-zero V:
* * apply preconditioner to X0
* * compare reference model against implementation being tested
*/
inexactlbfgspreconditioner(&s0, n, &vd, &vc, &va, k, &buf, _state);
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(s2.ptr.p_double[i]-s0.ptr.p_double[i], _state),tolg), __FILE__, __LINE__, "testoptservunit.ap:236");
}
/*
* Second test - N-K zero rows appended to V and rows are
* randomly reordered. Doing so should not change result,
* algorithm must be able to order rows according to second derivative
* and skip zero updates.
*/
for(i=0; i<=n-1; i++)
{
i0 = i+hqrnduniformi(&rs, n-i, _state);
v = vc.ptr.p_double[i];
vc.ptr.p_double[i] = vc.ptr.p_double[i0];
vc.ptr.p_double[i0] = v;
for(j=0; j<=n-1; j++)
{
v = va.ptr.pp_double[i][j];
va.ptr.pp_double[i][j] = va.ptr.pp_double[i0][j];
va.ptr.pp_double[i0][j] = v;
}
}
inexactlbfgspreconditioner(&s1, n, &vd, &vc, &va, n, &buf, _state);
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(s2.ptr.p_double[i]-s1.ptr.p_double[i], _state),tolg), __FILE__, __LINE__, "testoptservunit.ap:259");
}
}
}
/*
* Test for exact low-rank preconditioner.
*
* We generate QP problem 0.5*x'*H*x, with random H=D+V'*C*V.
* Different K's, from 0 to N, are tried. We test preconditioner
* code which uses Woodbury update against reference implementation
* which performs straightforward matrix inversion.
*
* For each K we perform two tests: first for KxN non-zero matrix V,
* second one for NxN matrix V with randomly appended N-K zero rows.
* Last test checks algorithm's ability to handle zero updates.
*/
tolg = 1.0E-9;
for(n=1; n<=10; n++)
{
for(k=0; k<=n; k++)
{
/*
* Prepare problem:
* * VD, VC, VA
* * trial vector S (copies are stored to S0,S1,S2)
*/
ae_vector_set_length(&vd, n, _state);
ae_vector_set_length(&s0, n, _state);
ae_vector_set_length(&s1, n, _state);
ae_vector_set_length(&s2, n, _state);
for(i=0; i<=n-1; i++)
{
vd.ptr.p_double[i] = ae_exp(hqrndnormal(&rs, _state), _state);
s0.ptr.p_double[i] = hqrndnormal(&rs, _state);
s1.ptr.p_double[i] = s0.ptr.p_double[i];
s2.ptr.p_double[i] = s0.ptr.p_double[i];
}
rmatrixrndcond(n, 1.0E2, &va, _state);
rvectorsetlengthatleast(&vc, n, _state);
for(i=0; i<=k-1; i++)
{
vc.ptr.p_double[i] = ae_exp(hqrndnormal(&rs, _state), _state);
}
for(i=k; i<=n-1; i++)
{
vc.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
va.ptr.pp_double[i][j] = 0.0;
}
}
/*
* Generate reference model and apply it to S2
*/
ae_matrix_set_length(&bk, n, n, _state);
ae_vector_set_length(&tmp, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( i==j )
{
v = vd.ptr.p_double[i];
}
else
{
v = 0.0;
}
for(j1=0; j1<=k-1; j1++)
{
v = v+va.ptr.pp_double[j1][i]*vc.ptr.p_double[j1]*va.ptr.pp_double[j1][j];
}
bk.ptr.pp_double[i][j] = v;
}
}
rmatrixinverse(&bk, n, &j, &rep, _state);
ae_assert(j>0, "Assertion failed", _state);
for(i=0; i<=n-1; i++)
{
v = 0.0;
for(j=0; j<=n-1; j++)
{
v = v+bk.ptr.pp_double[i][j]*s2.ptr.p_double[j];
}
tmp.ptr.p_double[i] = v;
}
for(i=0; i<=n-1; i++)
{
s2.ptr.p_double[i] = tmp.ptr.p_double[i];
}
/*
* First test for non-zero V:
* * apply preconditioner to X0
* * compare reference model against implementation being tested
*/
preparelowrankpreconditioner(&vd, &vc, &va, n, k, &lowrankbuf, _state);
applylowrankpreconditioner(&s0, &lowrankbuf, _state);
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(s2.ptr.p_double[i]-s0.ptr.p_double[i], _state),tolg), __FILE__, __LINE__, "testoptservunit.ap:341");
}
/*
* Second test - N-K zero rows appended to V and rows are
* randomly reordered. Doing so should not change result,
* algorithm must be able to order rows according to second derivative
* and skip zero updates.
*/
for(i=0; i<=n-1; i++)
{
i0 = i+hqrnduniformi(&rs, n-i, _state);
v = vc.ptr.p_double[i];
vc.ptr.p_double[i] = vc.ptr.p_double[i0];
vc.ptr.p_double[i0] = v;
for(j=0; j<=n-1; j++)
{
v = va.ptr.pp_double[i][j];
va.ptr.pp_double[i][j] = va.ptr.pp_double[i0][j];
va.ptr.pp_double[i0][j] = v;
}
}
preparelowrankpreconditioner(&vd, &vc, &va, n, n, &lowrankbuf, _state);
applylowrankpreconditioner(&s1, &lowrankbuf, _state);
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(s2.ptr.p_double[i]-s1.ptr.p_double[i], _state),tolg), __FILE__, __LINE__, "testoptservunit.ap:365");
}
}
}
ae_frame_leave(_state);
}
ae_bool testsnnls(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_bool test0errors;
ae_bool test1errors;
ae_bool test2errors;
ae_bool testnewtonerrors;
ae_bool waserrors;
double eps;
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
ae_int_t ns;
ae_int_t nd;
ae_int_t nr;
ae_matrix densea;
ae_matrix effectivea;
ae_vector isconstrained;
ae_vector g;
ae_vector b;
ae_vector x;
ae_vector xs;
snnlssolver s;
hqrndstate rs;
double rho;
double xtol;
ae_int_t nmax;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&densea, 0, sizeof(densea));
memset(&effectivea, 0, sizeof(effectivea));
memset(&isconstrained, 0, sizeof(isconstrained));
memset(&g, 0, sizeof(g));
memset(&b, 0, sizeof(b));
memset(&x, 0, sizeof(x));
memset(&xs, 0, sizeof(xs));
memset(&s, 0, sizeof(s));
memset(&rs, 0, sizeof(rs));
ae_matrix_init(&densea, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&effectivea, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&isconstrained, 0, DT_BOOL, _state, ae_true);
ae_vector_init(&g, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xs, 0, DT_REAL, _state, ae_true);
_snnlssolver_init(&s, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
test0errors = ae_false;
test1errors = ae_false;
test2errors = ae_false;
testnewtonerrors = ae_false;
waserrors = ae_false;
hqrndrandomize(&rs, _state);
nmax = 10;
/*
* Test 2 (comes first because it is very basic):
* * NS=0
* * ND in [1,NMAX]
* * NR=ND
* * DenseA is diagonal with positive entries
* * B is random
* * random constraints
* Exact solution is known and can be tested
*/
eps = 1.0E-12;
for(nd=1; nd<=nmax; nd++)
{
/*
* Generate problem
*/
ns = 0;
nr = nd;
ae_matrix_set_length(&densea, nd, nd, _state);
ae_vector_set_length(&b, nd, _state);
ae_vector_set_length(&isconstrained, nd, _state);
for(i=0; i<=nd-1; i++)
{
for(j=0; j<=nd-1; j++)
{
densea.ptr.pp_double[i][j] = (double)(0);
}
densea.ptr.pp_double[i][i] = (double)(1+hqrnduniformi(&rs, 2, _state));
b.ptr.p_double[i] = (double)((1+hqrnduniformi(&rs, 2, _state))*(2*hqrnduniformi(&rs, 2, _state)-1));
isconstrained.ptr.p_bool[i] = ae_fp_greater(hqrnduniformr(&rs, _state),0.5);
}
/*
* Solve with SNNLS solver
*/
snnlsinit(0, 0, 0, &s, _state);
snnlssetproblem(&s, &densea, &b, 0, nd, nd, _state);
for(i=0; i<=nd-1; i++)
{
if( !isconstrained.ptr.p_bool[i] )
{
snnlsdropnnc(&s, i, _state);
}
}
snnlssolve(&s, &x, _state);
/*
* Check
*/
for(i=0; i<=nd-1; i++)
{
if( isconstrained.ptr.p_bool[i] )
{
ae_set_error_flag(&test2errors, ae_fp_greater(ae_fabs(x.ptr.p_double[i]-ae_maxreal(b.ptr.p_double[i]/densea.ptr.pp_double[i][i], 0.0, _state), _state),eps), __FILE__, __LINE__, "testsnnlsunit.ap:86");
ae_set_error_flag(&test2errors, ae_fp_less(x.ptr.p_double[i],0.0), __FILE__, __LINE__, "testsnnlsunit.ap:87");
}
else
{
ae_set_error_flag(&test2errors, ae_fp_greater(ae_fabs(x.ptr.p_double[i]-b.ptr.p_double[i]/densea.ptr.pp_double[i][i], _state),eps), __FILE__, __LINE__, "testsnnlsunit.ap:90");
}
}
}
/*
* Test 0:
* * NS in [0,NMAX]
* * ND in [0,NMAX]
* * NR in [NS,NS+ND+NMAX]
* * NS+ND>0, NR>0
* * about 50% of variables are constrained
* * we check that constrained gradient is small at the solution
*/
eps = 1.0E-5;
for(ns=0; ns<=nmax; ns++)
{
for(nd=0; nd<=nmax; nd++)
{
for(nr=ns; nr<=ns+nd+nmax; nr++)
{
/*
* Skip NS+ND=0, NR=0
*/
if( ns+nd==0 )
{
continue;
}
if( nr==0 )
{
continue;
}
/*
* Generate problem:
* * DenseA, array[NR,ND]
* * EffectiveA, array[NR,NS+ND]
* * B, array[NR]
* * IsConstrained, array[NS+ND]
*/
if( nd>0 )
{
ae_matrix_set_length(&densea, nr, nd, _state);
for(i=0; i<=nr-1; i++)
{
for(j=0; j<=nd-1; j++)
{
densea.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
}
ae_matrix_set_length(&effectivea, nr, ns+nd, _state);
for(i=0; i<=nr-1; i++)
{
for(j=0; j<=ns+nd-1; j++)
{
effectivea.ptr.pp_double[i][j] = 0.0;
}
}
for(i=0; i<=ns-1; i++)
{
effectivea.ptr.pp_double[i][i] = 1.0;
}
for(i=0; i<=nr-1; i++)
{
for(j=0; j<=nd-1; j++)
{
effectivea.ptr.pp_double[i][ns+j] = densea.ptr.pp_double[i][j];
}
}
ae_vector_set_length(&b, nr, _state);
for(i=0; i<=nr-1; i++)
{
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
ae_vector_set_length(&isconstrained, ns+nd, _state);
for(i=0; i<=ns+nd-1; i++)
{
isconstrained.ptr.p_bool[i] = ae_fp_greater(ae_randomreal(_state),0.5);
}
/*
* Solve with SNNLS solver
*/
snnlsinit(0, 0, 0, &s, _state);
snnlssetproblem(&s, &densea, &b, ns, nd, nr, _state);
for(i=0; i<=ns+nd-1; i++)
{
if( !isconstrained.ptr.p_bool[i] )
{
snnlsdropnnc(&s, i, _state);
}
}
snnlssolve(&s, &x, _state);
/*
* Check non-negativity
*/
for(i=0; i<=ns+nd-1; i++)
{
ae_set_error_flag(&test0errors, isconstrained.ptr.p_bool[i]&&ae_fp_less(x.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testsnnlsunit.ap:160");
}
/*
* Calculate gradient A'*A*x-b'*A.
* Check projected gradient (each component must be less than Eps).
*/
ae_vector_set_length(&g, ns+nd, _state);
for(i=0; i<=ns+nd-1; i++)
{
v = ae_v_dotproduct(&b.ptr.p_double[0], 1, &effectivea.ptr.pp_double[0][i], effectivea.stride, ae_v_len(0,nr-1));
g.ptr.p_double[i] = -v;
}
for(i=0; i<=nr-1; i++)
{
v = ae_v_dotproduct(&effectivea.ptr.pp_double[i][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,ns+nd-1));
ae_v_addd(&g.ptr.p_double[0], 1, &effectivea.ptr.pp_double[i][0], 1, ae_v_len(0,ns+nd-1), v);
}
for(i=0; i<=ns+nd-1; i++)
{
if( !isconstrained.ptr.p_bool[i]||ae_fp_greater(x.ptr.p_double[i],(double)(0)) )
{
ae_set_error_flag(&test0errors, ae_fp_greater(ae_fabs(g.ptr.p_double[i], _state),eps), __FILE__, __LINE__, "testsnnlsunit.ap:179");
}
else
{
ae_set_error_flag(&test0errors, ae_fp_less(g.ptr.p_double[i],-eps), __FILE__, __LINE__, "testsnnlsunit.ap:181");
}
}
}
}
}
/*
* Test 1: ability of the solver to take very short steps.
*
* We solve problem similar to one solver in test 0, but with
* progressively decreased magnitude of variables. We generate
* problem with already-known solution and compare results against it.
*/
xtol = 1.0E-7;
for(ns=0; ns<=nmax; ns++)
{
for(nd=0; nd<=nmax; nd++)
{
for(nr=ns; nr<=ns+nd+nmax; nr++)
{
for(k=0; k<=20; k++)
{
/*
* Skip NS+ND=0, NR=0
*
* Skip degenerate problems (NR0 )
{
ae_matrix_set_length(&densea, nr, nd, _state);
for(i=0; i<=nr-1; i++)
{
for(j=0; j<=nd-1; j++)
{
densea.ptr.pp_double[i][j] = 2*hqrnduniformr(&rs, _state)-1;
}
}
}
ae_matrix_set_length(&effectivea, nr, ns+nd, _state);
for(i=0; i<=nr-1; i++)
{
for(j=0; j<=ns+nd-1; j++)
{
effectivea.ptr.pp_double[i][j] = 0.0;
}
}
for(i=0; i<=ns-1; i++)
{
effectivea.ptr.pp_double[i][i] = 1.0;
}
for(i=0; i<=nr-1; i++)
{
for(j=0; j<=nd-1; j++)
{
effectivea.ptr.pp_double[i][ns+j] = densea.ptr.pp_double[i][j];
}
}
ae_vector_set_length(&xs, ns+nd, _state);
ae_vector_set_length(&isconstrained, ns+nd, _state);
for(i=0; i<=ns+nd-1; i++)
{
xs.ptr.p_double[i] = rho*(hqrnduniformr(&rs, _state)-0.5);
isconstrained.ptr.p_bool[i] = ae_fp_greater(xs.ptr.p_double[i],0.0);
}
ae_vector_set_length(&b, nr, _state);
for(i=0; i<=nr-1; i++)
{
v = 0.0;
for(j=0; j<=ns+nd-1; j++)
{
v = v+effectivea.ptr.pp_double[i][j]*xs.ptr.p_double[j];
}
b.ptr.p_double[i] = v;
}
/*
* Solve with SNNLS solver
*/
snnlsinit(0, 0, 0, &s, _state);
snnlssetproblem(&s, &densea, &b, ns, nd, nr, _state);
for(i=0; i<=ns+nd-1; i++)
{
if( !isconstrained.ptr.p_bool[i] )
{
snnlsdropnnc(&s, i, _state);
}
}
snnlssolve(&s, &x, _state);
/*
* Check non-negativity
*/
for(i=0; i<=ns+nd-1; i++)
{
ae_set_error_flag(&test1errors, isconstrained.ptr.p_bool[i]&&ae_fp_less(x.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testsnnlsunit.ap:263");
}
/*
* Compare with true solution
*/
for(i=0; i<=ns+nd-1; i++)
{
ae_set_error_flag(&test1errors, ae_fp_greater(ae_fabs(xs.ptr.p_double[i]-x.ptr.p_double[i], _state),rho*xtol), __FILE__, __LINE__, "testsnnlsunit.ap:269");
}
}
}
}
}
/*
* Test for Newton phase:
* * NS in [0,NMAX]
* * ND in [0,NMAX]
* * NR in [NS,NS+ND+NMAX]
* * NS+ND>0, NR>0
* * all variables are unconstrained
* * S.DebugMaxNewton is set to 1, S.RefinementIts is set to 1,
* i.e. algorithm is terminated after one Newton iteration, and no
* iterative refinement is used.
* * we test that gradient is small at solution, i.e. one Newton iteration
* on unconstrained problem is enough to find solution. In case of buggy
* Newton solver one iteration won't move us to the solution - it may
* decrease function value, but won't find exact solution.
*
* This test is intended to catch subtle bugs in the Newton solver which
* do NOT prevent algorithm from converging to the solution, but slow it
* down (convergence becomes linear or even slower).
*/
eps = 1.0E-4;
for(ns=0; ns<=nmax; ns++)
{
for(nd=0; nd<=nmax; nd++)
{
for(nr=ns; nr<=ns+nd+nmax; nr++)
{
/*
* Skip NS+ND=0, NR=0
*/
if( ns+nd==0 )
{
continue;
}
if( nr==0 )
{
continue;
}
/*
* Generate problem:
* * DenseA, array[NR,ND]
* * EffectiveA, array[NR,NS+ND]
* * B, array[NR]
* * IsConstrained, array[NS+ND]
*/
if( nd>0 )
{
ae_matrix_set_length(&densea, nr, nd, _state);
for(i=0; i<=nr-1; i++)
{
for(j=0; j<=nd-1; j++)
{
densea.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
}
ae_matrix_set_length(&effectivea, nr, ns+nd, _state);
for(i=0; i<=nr-1; i++)
{
for(j=0; j<=ns+nd-1; j++)
{
effectivea.ptr.pp_double[i][j] = 0.0;
}
}
for(i=0; i<=ns-1; i++)
{
effectivea.ptr.pp_double[i][i] = 1.0;
}
for(i=0; i<=nr-1; i++)
{
for(j=0; j<=nd-1; j++)
{
effectivea.ptr.pp_double[i][ns+j] = densea.ptr.pp_double[i][j];
}
}
ae_vector_set_length(&b, nr, _state);
for(i=0; i<=nr-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
/*
* Solve with SNNLS solver
*/
snnlsinit(0, 0, 0, &s, _state);
snnlssetproblem(&s, &densea, &b, ns, nd, nr, _state);
for(i=0; i<=ns+nd-1; i++)
{
snnlsdropnnc(&s, i, _state);
}
s.debugmaxinnerits = 1;
snnlssolve(&s, &x, _state);
/*
* Calculate gradient A'*A*x-b'*A.
* Check projected gradient (each component must be less than Eps).
*/
ae_vector_set_length(&g, ns+nd, _state);
for(i=0; i<=ns+nd-1; i++)
{
v = ae_v_dotproduct(&b.ptr.p_double[0], 1, &effectivea.ptr.pp_double[0][i], effectivea.stride, ae_v_len(0,nr-1));
g.ptr.p_double[i] = -v;
}
for(i=0; i<=nr-1; i++)
{
v = ae_v_dotproduct(&effectivea.ptr.pp_double[i][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,ns+nd-1));
ae_v_addd(&g.ptr.p_double[0], 1, &effectivea.ptr.pp_double[i][0], 1, ae_v_len(0,ns+nd-1), v);
}
for(i=0; i<=ns+nd-1; i++)
{
ae_set_error_flag(&testnewtonerrors, ae_fp_greater(ae_fabs(g.ptr.p_double[i], _state),eps), __FILE__, __LINE__, "testsnnlsunit.ap:358");
}
}
}
}
/*
* report
*/
waserrors = ((test0errors||test1errors)||test2errors)||testnewtonerrors;
if( !silent )
{
printf("TESTING SPECIAL NNLS SOLVER\n");
printf("TEST 0: ");
if( test0errors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("TEST 1: ");
if( test1errors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("TEST 2: ");
if( test2errors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("NEWTON PHASE: ");
if( testnewtonerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
static void testsactivesetsunit_testspecproperties(ae_bool* err,
ae_state *_state);
ae_bool testsactivesets(ae_bool silent, ae_state *_state)
{
ae_bool waserrors;
ae_bool specerr;
ae_bool result;
specerr = ae_false;
testsactivesetsunit_testspecproperties(&specerr, _state);
/*
* report
*/
waserrors = specerr;
if( !silent )
{
printf("TESTING ACTIVE SETS\n");
printf("* SPECIAL PROPERTIES ");
if( specerr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
return result;
}
/*************************************************************************
This function tests special properties.
On failure sets Err to True (leaves it unchanged otherwise)
*************************************************************************/
static void testsactivesetsunit_testspecproperties(ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_int_t n;
ae_int_t nec;
ae_int_t nic;
double v;
double vv;
sactiveset state;
hqrndstate rs;
ae_vector bl;
ae_vector bu;
ae_vector x;
ae_vector s;
ae_matrix c;
ae_vector ct;
ae_int_t scaletype;
ae_int_t pass;
ae_int_t distortidx;
double distortmag;
ae_frame_make(_state, &_frame_block);
memset(&state, 0, sizeof(state));
memset(&rs, 0, sizeof(rs));
memset(&bl, 0, sizeof(bl));
memset(&bu, 0, sizeof(bu));
memset(&x, 0, sizeof(x));
memset(&s, 0, sizeof(s));
memset(&c, 0, sizeof(c));
memset(&ct, 0, sizeof(ct));
_sactiveset_init(&state, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
ae_vector_init(&bl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* N-dimensional problem with Ne equality and Ni inequality constraints.
*
* Check that SActiveSet object uses efficient algorithm
* to determine initial point: it avoids expensive (N+Ni)-dimensional
* QP subproblem when initial point is feasible w.r.t. constraints.
*
* In order to do so we try to find initial point for a problem with
* 2 equality constraints and 1000000 inequality constraints (+box
* constraints). Inefficient algorithm will simply fail to allocate
* enough memory, so we do not have to perform any checks here.
*/
n = 5;
nec = 2;
nic = 1000000;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
for(scaletype=0; scaletype<=1; scaletype++)
{
/*
* Generate problem
*/
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = hqrnduniformr(&rs, _state);
bl.ptr.p_double[i] = x.ptr.p_double[i]-hqrnduniformr(&rs, _state)*hqrnduniformi(&rs, 2, _state);
bu.ptr.p_double[i] = x.ptr.p_double[i]+hqrnduniformr(&rs, _state)*hqrnduniformi(&rs, 2, _state);
}
ae_matrix_set_length(&c, nec+nic, n+1, _state);
ae_vector_set_length(&ct, nec+nic, _state);
for(i=0; i<=nec+nic-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
v = v+c.ptr.pp_double[i][j]*x.ptr.p_double[j];
}
c.ptr.pp_double[i][n] = v;
if( i1 )
{
s = ae_maxrealnumber;
}
ry.ptr.p_double[0] = (2*ae_randomreal(_state)-1)*s*ae_sqrt(2*ae_randomreal(_state), _state);
for(i=1; i<=n-1; i++)
{
ry.ptr.p_double[i] = ry.ptr.p_double[0];
}
for(i=0; i<=n/2-1; i++)
{
rx.ptr.p_double[i] = (double)(1);
}
for(i=n/2; i<=n-2; i++)
{
rx.ptr.p_double[i] = (double)(-1);
}
rx.ptr.p_double[n-1] = (double)(0);
xdot(&rx, &ry, n, &temp, &rv2, &rv2err, _state);
exactnesserrors = exactnesserrors||ae_fp_less(rv2err,(double)(0));
exactnesserrors = exactnesserrors||ae_fp_greater(rv2err,4*ae_machineepsilon*ae_fabs(ry.ptr.p_double[0], _state));
exactnesserrors = exactnesserrors||ae_fp_greater(ae_fabs(rv2-ry.ptr.p_double[0], _state),rv2err);
/*
* First test: X + X + ... + X = N*X
*/
s = ae_exp((double)(ae_maxint(pass, 50, _state)), _state);
if( pass==passcount-1&&pass>1 )
{
s = ae_maxrealnumber;
}
ry.ptr.p_double[0] = (2*ae_randomreal(_state)-1)*s*ae_sqrt(2*ae_randomreal(_state), _state);
for(i=1; i<=n-1; i++)
{
ry.ptr.p_double[i] = ry.ptr.p_double[0];
}
for(i=0; i<=n-1; i++)
{
rx.ptr.p_double[i] = (double)(1);
}
xdot(&rx, &ry, n, &temp, &rv2, &rv2err, _state);
exactnesserrors = exactnesserrors||ae_fp_less(rv2err,(double)(0));
exactnesserrors = exactnesserrors||ae_fp_greater(rv2err,4*ae_machineepsilon*ae_fabs(ry.ptr.p_double[0], _state)*n);
exactnesserrors = exactnesserrors||ae_fp_greater(ae_fabs(rv2-n*ry.ptr.p_double[0], _state),rv2err);
}
/*
* test of precision: complex
*/
n = 50000;
ae_vector_set_length(&cx, n, _state);
ae_vector_set_length(&cy, n, _state);
ae_vector_set_length(&temp, 2*n, _state);
for(pass=0; pass<=passcount-1; pass++)
{
ae_assert(n%2==0, "Assertion failed", _state);
/*
* First test: X + X + ... + X - X - X - ... - X = 1*X
*/
s = ae_exp((double)(ae_maxint(pass, 50, _state)), _state);
if( pass==passcount-1&&pass>1 )
{
s = ae_maxrealnumber;
}
cy.ptr.p_complex[0].x = (2*ae_randomreal(_state)-1)*s*ae_sqrt(2*ae_randomreal(_state), _state);
cy.ptr.p_complex[0].y = (2*ae_randomreal(_state)-1)*s*ae_sqrt(2*ae_randomreal(_state), _state);
for(i=1; i<=n-1; i++)
{
cy.ptr.p_complex[i] = cy.ptr.p_complex[0];
}
for(i=0; i<=n/2-1; i++)
{
cx.ptr.p_complex[i] = ae_complex_from_i(1);
}
for(i=n/2; i<=n-2; i++)
{
cx.ptr.p_complex[i] = ae_complex_from_i(-1);
}
cx.ptr.p_complex[n-1] = ae_complex_from_i(0);
xcdot(&cx, &cy, n, &temp, &cv2, &cv2err, _state);
exactnesserrors = exactnesserrors||ae_fp_less(cv2err,(double)(0));
exactnesserrors = exactnesserrors||ae_fp_greater(cv2err,4*ae_machineepsilon*ae_c_abs(cy.ptr.p_complex[0], _state));
exactnesserrors = exactnesserrors||ae_fp_greater(ae_c_abs(ae_c_sub(cv2,cy.ptr.p_complex[0]), _state),cv2err);
/*
* First test: X + X + ... + X = N*X
*/
s = ae_exp((double)(ae_maxint(pass, 50, _state)), _state);
if( pass==passcount-1&&pass>1 )
{
s = ae_maxrealnumber;
}
cy.ptr.p_complex[0] = ae_complex_from_d((2*ae_randomreal(_state)-1)*s*ae_sqrt(2*ae_randomreal(_state), _state));
for(i=1; i<=n-1; i++)
{
cy.ptr.p_complex[i] = cy.ptr.p_complex[0];
}
for(i=0; i<=n-1; i++)
{
cx.ptr.p_complex[i] = ae_complex_from_i(1);
}
xcdot(&cx, &cy, n, &temp, &cv2, &cv2err, _state);
exactnesserrors = exactnesserrors||ae_fp_less(cv2err,(double)(0));
exactnesserrors = exactnesserrors||ae_fp_greater(cv2err,4*ae_machineepsilon*ae_c_abs(cy.ptr.p_complex[0], _state)*n);
exactnesserrors = exactnesserrors||ae_fp_greater(ae_c_abs(ae_c_sub(cv2,ae_c_mul_d(cy.ptr.p_complex[0],1.0*n)), _state),cv2err);
}
/*
* report
*/
waserrors = approxerrors||exactnesserrors;
if( !silent )
{
printf("TESTING XBLAS\n");
printf("APPROX.TESTS: ");
if( approxerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("EXACT TESTS: ");
if( exactnesserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
/*
* end
*/
result = !waserrors;
ae_frame_leave(_state);
return result;
}
static ae_bool testdirectdensesolversunit_rmatrixchecksolutionm(/* Real */ ae_matrix* xe,
ae_int_t n,
ae_int_t m,
double threshold,
ae_int_t info,
densesolverreport* rep,
/* Real */ ae_matrix* xs,
ae_state *_state);
static ae_bool testdirectdensesolversunit_rmatrixchecksolutionmfast(/* Real */ ae_matrix* xe,
ae_int_t n,
ae_int_t m,
double threshold,
ae_int_t info,
/* Real */ ae_matrix* xs,
ae_state *_state);
static ae_bool testdirectdensesolversunit_rmatrixchecksolution(/* Real */ ae_matrix* xe,
ae_int_t n,
double threshold,
ae_int_t info,
densesolverreport* rep,
/* Real */ ae_vector* xs,
ae_state *_state);
static ae_bool testdirectdensesolversunit_rmatrixchecksolutionfast(/* Real */ ae_matrix* xe,
ae_int_t n,
double threshold,
ae_int_t info,
/* Real */ ae_vector* xs,
ae_state *_state);
static ae_bool testdirectdensesolversunit_rmatrixchecksingularm(ae_int_t n,
ae_int_t m,
ae_int_t info,
densesolverreport* rep,
/* Real */ ae_matrix* xs,
ae_state *_state);
static ae_bool testdirectdensesolversunit_rmatrixchecksingularmfast(ae_int_t n,
ae_int_t m,
ae_int_t info,
/* Real */ ae_matrix* xs,
ae_state *_state);
static ae_bool testdirectdensesolversunit_rmatrixchecksingular(ae_int_t n,
ae_int_t info,
densesolverreport* rep,
/* Real */ ae_vector* xs,
ae_state *_state);
static ae_bool testdirectdensesolversunit_rmatrixchecksingularfast(ae_int_t n,
ae_int_t info,
/* Real */ ae_vector* xs,
ae_state *_state);
static ae_bool testdirectdensesolversunit_cmatrixchecksolutionm(/* Complex */ ae_matrix* xe,
ae_int_t n,
ae_int_t m,
double threshold,
ae_int_t info,
densesolverreport* rep,
/* Complex */ ae_matrix* xs,
ae_state *_state);
static ae_bool testdirectdensesolversunit_cmatrixchecksolutionmfast(/* Complex */ ae_matrix* xe,
ae_int_t n,
ae_int_t m,
double threshold,
ae_int_t info,
/* Complex */ ae_matrix* xs,
ae_state *_state);
static ae_bool testdirectdensesolversunit_cmatrixchecksolution(/* Complex */ ae_matrix* xe,
ae_int_t n,
double threshold,
ae_int_t info,
densesolverreport* rep,
/* Complex */ ae_vector* xs,
ae_state *_state);
static ae_bool testdirectdensesolversunit_cmatrixchecksolutionfast(/* Complex */ ae_matrix* xe,
ae_int_t n,
double threshold,
ae_int_t info,
/* Complex */ ae_vector* xs,
ae_state *_state);
static ae_bool testdirectdensesolversunit_cmatrixchecksingularm(ae_int_t n,
ae_int_t m,
ae_int_t info,
densesolverreport* rep,
/* Complex */ ae_matrix* xs,
ae_state *_state);
static ae_bool testdirectdensesolversunit_cmatrixchecksingularmfast(ae_int_t n,
ae_int_t m,
ae_int_t info,
/* Complex */ ae_matrix* xs,
ae_state *_state);
static ae_bool testdirectdensesolversunit_cmatrixchecksingular(ae_int_t n,
ae_int_t info,
densesolverreport* rep,
/* Complex */ ae_vector* xs,
ae_state *_state);
static ae_bool testdirectdensesolversunit_cmatrixchecksingularfast(ae_int_t n,
ae_int_t info,
/* Complex */ ae_vector* xs,
ae_state *_state);
static void testdirectdensesolversunit_rmatrixmakeacopy(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Real */ ae_matrix* b,
ae_state *_state);
static void testdirectdensesolversunit_cmatrixmakeacopy(/* Complex */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Complex */ ae_matrix* b,
ae_state *_state);
static void testdirectdensesolversunit_rmatrixdrophalf(/* Real */ ae_matrix* a,
ae_int_t n,
ae_bool droplower,
ae_state *_state);
static void testdirectdensesolversunit_cmatrixdrophalf(/* Complex */ ae_matrix* a,
ae_int_t n,
ae_bool droplower,
ae_state *_state);
static void testdirectdensesolversunit_testrsolver(ae_int_t maxn,
ae_int_t maxm,
ae_int_t passcount,
double threshold,
ae_bool* rerrors,
ae_bool* rfserrors,
ae_state *_state);
static void testdirectdensesolversunit_testspdsolver(ae_int_t maxn,
ae_int_t maxm,
ae_int_t passcount,
double threshold,
ae_bool* spderrors,
ae_bool* rfserrors,
ae_state *_state);
static void testdirectdensesolversunit_testcsolver(ae_int_t maxn,
ae_int_t maxm,
ae_int_t passcount,
double threshold,
ae_bool* cerrors,
ae_bool* rfserrors,
ae_state *_state);
static void testdirectdensesolversunit_testhpdsolver(ae_int_t maxn,
ae_int_t maxm,
ae_int_t passcount,
double threshold,
ae_bool* hpderrors,
ae_bool* rfserrors,
ae_state *_state);
static void testdirectdensesolversunit_unset2d(/* Real */ ae_matrix* x,
ae_state *_state);
static void testdirectdensesolversunit_unset1d(/* Real */ ae_vector* x,
ae_state *_state);
static void testdirectdensesolversunit_cunset2d(/* Complex */ ae_matrix* x,
ae_state *_state);
static void testdirectdensesolversunit_cunset1d(/* Complex */ ae_vector* x,
ae_state *_state);
static void testdirectdensesolversunit_unsetrep(densesolverreport* r,
ae_state *_state);
static void testdirectdensesolversunit_unsetlsrep(densesolverlsreport* r,
ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testdirectdensesolvers(ae_bool silent, ae_state *_state)
{
ae_int_t maxn;
ae_int_t maxm;
ae_int_t passcount;
double threshold;
ae_bool rerrors;
ae_bool cerrors;
ae_bool spderrors;
ae_bool hpderrors;
ae_bool rfserrors;
ae_bool waserrors;
ae_bool result;
maxn = 10;
maxm = 5;
passcount = 5;
threshold = 10000*ae_machineepsilon;
rfserrors = ae_false;
rerrors = ae_false;
cerrors = ae_false;
spderrors = ae_false;
hpderrors = ae_false;
testdirectdensesolversunit_testrsolver(maxn, maxm, passcount, threshold, &rerrors, &rfserrors, _state);
testdirectdensesolversunit_testspdsolver(maxn, maxm, passcount, threshold, &spderrors, &rfserrors, _state);
testdirectdensesolversunit_testcsolver(maxn, maxm, passcount, threshold, &cerrors, &rfserrors, _state);
testdirectdensesolversunit_testhpdsolver(maxn, maxm, passcount, threshold, &hpderrors, &rfserrors, _state);
waserrors = (((rerrors||cerrors)||spderrors)||hpderrors)||rfserrors;
if( !silent )
{
printf("TESTING DENSE SOLVER\n");
printf("* REAL: ");
if( rerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* COMPLEX: ");
if( cerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* SPD: ");
if( spderrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* HPD: ");
if( hpderrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* ITERATIVE IMPROVEMENT: ");
if( rfserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
}
result = !waserrors;
return result;
}
/*************************************************************************
Checks whether solver results are correct solution.
Returns True on success.
*************************************************************************/
static ae_bool testdirectdensesolversunit_rmatrixchecksolutionm(/* Real */ ae_matrix* xe,
ae_int_t n,
ae_int_t m,
double threshold,
ae_int_t info,
densesolverreport* rep,
/* Real */ ae_matrix* xs,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_bool result;
result = ae_true;
if( info<=0 )
{
result = ae_false;
}
else
{
result = result&&!(ae_fp_less(rep->r1,100*ae_machineepsilon)||ae_fp_greater(rep->r1,1+1000*ae_machineepsilon));
result = result&&!(ae_fp_less(rep->rinf,100*ae_machineepsilon)||ae_fp_greater(rep->rinf,1+1000*ae_machineepsilon));
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
result = result&&ae_fp_less_eq(ae_fabs(xe->ptr.pp_double[i][j]-xs->ptr.pp_double[i][j], _state),threshold);
}
}
}
return result;
}
/*************************************************************************
Checks whether solver results are correct solution.
Returns True on success.
*************************************************************************/
static ae_bool testdirectdensesolversunit_rmatrixchecksolutionmfast(/* Real */ ae_matrix* xe,
ae_int_t n,
ae_int_t m,
double threshold,
ae_int_t info,
/* Real */ ae_matrix* xs,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_bool result;
result = ae_true;
if( info<=0 )
{
result = ae_false;
}
else
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
result = result&&ae_fp_less_eq(ae_fabs(xe->ptr.pp_double[i][j]-xs->ptr.pp_double[i][j], _state),threshold);
}
}
}
return result;
}
/*************************************************************************
Checks whether solver results are correct solution.
Returns True on success.
*************************************************************************/
static ae_bool testdirectdensesolversunit_rmatrixchecksolution(/* Real */ ae_matrix* xe,
ae_int_t n,
double threshold,
ae_int_t info,
densesolverreport* rep,
/* Real */ ae_vector* xs,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix xsm;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&xsm, 0, sizeof(xsm));
ae_matrix_init(&xsm, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_set_length(&xsm, n, 1, _state);
ae_v_move(&xsm.ptr.pp_double[0][0], xsm.stride, &xs->ptr.p_double[0], 1, ae_v_len(0,n-1));
result = testdirectdensesolversunit_rmatrixchecksolutionm(xe, n, 1, threshold, info, rep, &xsm, _state);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Checks whether solver results are correct solution.
Returns True on success.
*************************************************************************/
static ae_bool testdirectdensesolversunit_rmatrixchecksolutionfast(/* Real */ ae_matrix* xe,
ae_int_t n,
double threshold,
ae_int_t info,
/* Real */ ae_vector* xs,
ae_state *_state)
{
ae_int_t i;
ae_bool result;
result = ae_true;
if( info<=0 )
{
result = ae_false;
}
else
{
for(i=0; i<=n-1; i++)
{
result = result&&ae_fp_less_eq(ae_fabs(xe->ptr.pp_double[i][0]-xs->ptr.p_double[i], _state),threshold);
}
}
return result;
}
/*************************************************************************
Checks whether solver results indicate singular matrix.
Returns True on success.
*************************************************************************/
static ae_bool testdirectdensesolversunit_rmatrixchecksingularm(ae_int_t n,
ae_int_t m,
ae_int_t info,
densesolverreport* rep,
/* Real */ ae_matrix* xs,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_bool result;
result = ae_true;
if( info!=-3&&info!=1 )
{
result = ae_false;
}
else
{
result = result&&!(ae_fp_less(rep->r1,(double)(0))||ae_fp_greater(rep->r1,1000*ae_machineepsilon));
result = result&&!(ae_fp_less(rep->rinf,(double)(0))||ae_fp_greater(rep->rinf,1000*ae_machineepsilon));
if( info==-3 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
result = result&&ae_fp_eq(xs->ptr.pp_double[i][j],(double)(0));
}
}
}
}
return result;
}
/*************************************************************************
Checks whether solver results indicate singular matrix.
Returns True on success.
*************************************************************************/
static ae_bool testdirectdensesolversunit_rmatrixchecksingularmfast(ae_int_t n,
ae_int_t m,
ae_int_t info,
/* Real */ ae_matrix* xs,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_bool result;
result = ae_true;
if( info!=-3 )
{
result = ae_false;
}
else
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
result = result&&ae_fp_eq(xs->ptr.pp_double[i][j],(double)(0));
}
}
}
return result;
}
/*************************************************************************
Checks whether solver results indicate singular matrix.
Returns True on success.
*************************************************************************/
static ae_bool testdirectdensesolversunit_rmatrixchecksingular(ae_int_t n,
ae_int_t info,
densesolverreport* rep,
/* Real */ ae_vector* xs,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix xsm;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&xsm, 0, sizeof(xsm));
ae_matrix_init(&xsm, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_set_length(&xsm, n, 1, _state);
ae_v_move(&xsm.ptr.pp_double[0][0], xsm.stride, &xs->ptr.p_double[0], 1, ae_v_len(0,n-1));
result = testdirectdensesolversunit_rmatrixchecksingularm(n, 1, info, rep, &xsm, _state);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Checks whether solver results indicate singular matrix.
Returns True on success.
*************************************************************************/
static ae_bool testdirectdensesolversunit_rmatrixchecksingularfast(ae_int_t n,
ae_int_t info,
/* Real */ ae_vector* xs,
ae_state *_state)
{
ae_int_t i;
ae_bool result;
result = ae_true;
if( info!=-3 )
{
result = ae_false;
}
else
{
for(i=0; i<=n-1; i++)
{
result = result&&ae_fp_eq(xs->ptr.p_double[i],(double)(0));
}
}
return result;
}
/*************************************************************************
Checks whether solver results are correct solution.
Returns True on success.
*************************************************************************/
static ae_bool testdirectdensesolversunit_cmatrixchecksolutionm(/* Complex */ ae_matrix* xe,
ae_int_t n,
ae_int_t m,
double threshold,
ae_int_t info,
densesolverreport* rep,
/* Complex */ ae_matrix* xs,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_bool result;
result = ae_true;
if( info<=0 )
{
result = ae_false;
}
else
{
result = result&&!(ae_fp_less(rep->r1,100*ae_machineepsilon)||ae_fp_greater(rep->r1,1+1000*ae_machineepsilon));
result = result&&!(ae_fp_less(rep->rinf,100*ae_machineepsilon)||ae_fp_greater(rep->rinf,1+1000*ae_machineepsilon));
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
result = result&&ae_fp_less_eq(ae_c_abs(ae_c_sub(xe->ptr.pp_complex[i][j],xs->ptr.pp_complex[i][j]), _state),threshold);
}
}
}
return result;
}
/*************************************************************************
Checks whether solver results are correct solution.
Returns True on success.
*************************************************************************/
static ae_bool testdirectdensesolversunit_cmatrixchecksolutionmfast(/* Complex */ ae_matrix* xe,
ae_int_t n,
ae_int_t m,
double threshold,
ae_int_t info,
/* Complex */ ae_matrix* xs,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_bool result;
result = ae_true;
if( info<=0 )
{
result = ae_false;
return result;
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
result = result&&ae_fp_less_eq(ae_c_abs(ae_c_sub(xe->ptr.pp_complex[i][j],xs->ptr.pp_complex[i][j]), _state),threshold);
}
}
return result;
}
/*************************************************************************
Checks whether solver results are correct solution.
Returns True on success.
*************************************************************************/
static ae_bool testdirectdensesolversunit_cmatrixchecksolution(/* Complex */ ae_matrix* xe,
ae_int_t n,
double threshold,
ae_int_t info,
densesolverreport* rep,
/* Complex */ ae_vector* xs,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix xsm;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&xsm, 0, sizeof(xsm));
ae_matrix_init(&xsm, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_set_length(&xsm, n, 1, _state);
ae_v_cmove(&xsm.ptr.pp_complex[0][0], xsm.stride, &xs->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1));
result = testdirectdensesolversunit_cmatrixchecksolutionm(xe, n, 1, threshold, info, rep, &xsm, _state);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Checks whether solver results are correct solution.
Returns True on success.
*************************************************************************/
static ae_bool testdirectdensesolversunit_cmatrixchecksolutionfast(/* Complex */ ae_matrix* xe,
ae_int_t n,
double threshold,
ae_int_t info,
/* Complex */ ae_vector* xs,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix xsm;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&xsm, 0, sizeof(xsm));
ae_matrix_init(&xsm, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_set_length(&xsm, n, 1, _state);
ae_v_cmove(&xsm.ptr.pp_complex[0][0], xsm.stride, &xs->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1));
result = testdirectdensesolversunit_cmatrixchecksolutionmfast(xe, n, 1, threshold, info, &xsm, _state);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Checks whether solver results indicate singular matrix.
Returns True on success.
*************************************************************************/
static ae_bool testdirectdensesolversunit_cmatrixchecksingularm(ae_int_t n,
ae_int_t m,
ae_int_t info,
densesolverreport* rep,
/* Complex */ ae_matrix* xs,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_bool result;
result = ae_true;
if( info!=-3&&info!=1 )
{
result = ae_false;
return result;
}
result = result&&!(ae_fp_less(rep->r1,(double)(0))||ae_fp_greater(rep->r1,1000*ae_machineepsilon));
result = result&&!(ae_fp_less(rep->rinf,(double)(0))||ae_fp_greater(rep->rinf,1000*ae_machineepsilon));
if( info==-3 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
result = result&&ae_c_eq_d(xs->ptr.pp_complex[i][j],(double)(0));
}
}
}
return result;
}
/*************************************************************************
Checks whether solver results indicate singular matrix.
Returns True on success.
*************************************************************************/
static ae_bool testdirectdensesolversunit_cmatrixchecksingularmfast(ae_int_t n,
ae_int_t m,
ae_int_t info,
/* Complex */ ae_matrix* xs,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_bool result;
result = ae_true;
if( info!=-3 )
{
result = ae_false;
return result;
}
if( info==-3 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
result = result&&ae_c_eq_d(xs->ptr.pp_complex[i][j],(double)(0));
}
}
}
return result;
}
/*************************************************************************
Checks whether solver results indicate singular matrix.
Returns True on success.
*************************************************************************/
static ae_bool testdirectdensesolversunit_cmatrixchecksingular(ae_int_t n,
ae_int_t info,
densesolverreport* rep,
/* Complex */ ae_vector* xs,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix xsm;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&xsm, 0, sizeof(xsm));
ae_matrix_init(&xsm, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_set_length(&xsm, n, 1, _state);
ae_v_cmove(&xsm.ptr.pp_complex[0][0], xsm.stride, &xs->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1));
result = testdirectdensesolversunit_cmatrixchecksingularm(n, 1, info, rep, &xsm, _state);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Checks whether solver results indicate singular matrix.
Returns True on success.
*************************************************************************/
static ae_bool testdirectdensesolversunit_cmatrixchecksingularfast(ae_int_t n,
ae_int_t info,
/* Complex */ ae_vector* xs,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix xsm;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&xsm, 0, sizeof(xsm));
ae_matrix_init(&xsm, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_set_length(&xsm, n, 1, _state);
ae_v_cmove(&xsm.ptr.pp_complex[0][0], xsm.stride, &xs->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1));
result = testdirectdensesolversunit_cmatrixchecksingularmfast(n, 1, info, &xsm, _state);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Copy
*************************************************************************/
static void testdirectdensesolversunit_rmatrixmakeacopy(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Real */ ae_matrix* b,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_matrix_clear(b);
ae_matrix_set_length(b, m-1+1, n-1+1, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
b->ptr.pp_double[i][j] = a->ptr.pp_double[i][j];
}
}
}
/*************************************************************************
Copy
*************************************************************************/
static void testdirectdensesolversunit_cmatrixmakeacopy(/* Complex */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Complex */ ae_matrix* b,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_matrix_clear(b);
ae_matrix_set_length(b, m-1+1, n-1+1, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
b->ptr.pp_complex[i][j] = a->ptr.pp_complex[i][j];
}
}
}
/*************************************************************************
Drops upper or lower half of the matrix - fills it by special pattern
which may be used later to ensure that this part wasn't changed
*************************************************************************/
static void testdirectdensesolversunit_rmatrixdrophalf(/* Real */ ae_matrix* a,
ae_int_t n,
ae_bool droplower,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (droplower&&i>j)||(!droplower&&iptr.pp_double[i][j] = (double)(1+2*i+3*j);
}
}
}
}
/*************************************************************************
Drops upper or lower half of the matrix - fills it by special pattern
which may be used later to ensure that this part wasn't changed
*************************************************************************/
static void testdirectdensesolversunit_cmatrixdrophalf(/* Complex */ ae_matrix* a,
ae_int_t n,
ae_bool droplower,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (droplower&&i>j)||(!droplower&&iptr.pp_complex[i][j] = ae_complex_from_i(1+2*i+3*j);
}
}
}
}
/*************************************************************************
Real test
*************************************************************************/
static void testdirectdensesolversunit_testrsolver(ae_int_t maxn,
ae_int_t maxm,
ae_int_t passcount,
double threshold,
ae_bool* rerrors,
ae_bool* rfserrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix lua;
ae_matrix atmp;
ae_vector p;
ae_matrix xe;
ae_matrix b;
ae_vector bv;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t n;
ae_int_t m;
ae_int_t pass;
ae_int_t taskkind;
double v;
double verr;
ae_int_t info;
densesolverreport rep;
densesolverlsreport repls;
ae_matrix x;
ae_vector xv;
ae_vector y;
ae_vector tx;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&lua, 0, sizeof(lua));
memset(&atmp, 0, sizeof(atmp));
memset(&p, 0, sizeof(p));
memset(&xe, 0, sizeof(xe));
memset(&b, 0, sizeof(b));
memset(&bv, 0, sizeof(bv));
memset(&rep, 0, sizeof(rep));
memset(&repls, 0, sizeof(repls));
memset(&x, 0, sizeof(x));
memset(&xv, 0, sizeof(xv));
memset(&y, 0, sizeof(y));
memset(&tx, 0, sizeof(tx));
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&lua, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&atmp, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&p, 0, DT_INT, _state, ae_true);
ae_matrix_init(&xe, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bv, 0, DT_REAL, _state, ae_true);
_densesolverreport_init(&rep, _state, ae_true);
_densesolverlsreport_init(&repls, _state, ae_true);
ae_matrix_init(&x, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xv, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tx, 0, DT_REAL, _state, ae_true);
/*
* General square matrices:
* * test general solvers
* * test least squares solver
*/
for(pass=1; pass<=passcount; pass++)
{
for(n=1; n<=maxn; n++)
{
for(m=1; m<=maxm; m++)
{
/*
* ********************************************************
* WELL CONDITIONED TASKS
* ability to find correct solution is tested
* ********************************************************
*
* 1. generate random well conditioned matrix A.
* 2. generate random solution vector xe
* 3. generate right part b=A*xe
* 4. test different methods on original A
*/
rmatrixrndcond(n, (double)(1000), &a, _state);
testdirectdensesolversunit_rmatrixmakeacopy(&a, n, n, &lua, _state);
rmatrixlu(&lua, n, n, &p, _state);
ae_matrix_set_length(&xe, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
xe.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
ae_matrix_set_length(&b, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xe.ptr.pp_double[0][j], xe.stride, ae_v_len(0,n-1));
b.ptr.pp_double[i][j] = v;
}
}
/*
* Test solvers
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_unset2d(&x, _state);
rmatrixsolvem(&a, n, &b, m, ae_fp_greater(ae_randomreal(_state),0.5), &info, &rep, &x, _state);
*rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksolutionm(&xe, n, m, threshold, info, &rep, &x, _state);
info = 0;
ae_matrix_set_length(&x, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_double[i][j] = b.ptr.pp_double[i][j];
}
}
rmatrixsolvemfast(&a, n, &x, m, &info, _state);
*rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksolutionmfast(&xe, n, m, threshold, info, &x, _state);
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_unset1d(&xv, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
rmatrixsolve(&a, n, &bv, &info, &rep, &xv, _state);
*rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksolution(&xe, n, threshold, info, &rep, &xv, _state);
info = 0;
ae_vector_set_length(&bv, n, _state);
ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
rmatrixsolvefast(&a, n, &bv, &info, _state);
*rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksolutionfast(&xe, n, threshold, info, &bv, _state);
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_unset2d(&x, _state);
rmatrixlusolvem(&lua, &p, n, &b, m, &info, &rep, &x, _state);
*rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksolutionm(&xe, n, m, threshold, info, &rep, &x, _state);
info = 0;
ae_matrix_set_length(&x, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_double[i][j] = b.ptr.pp_double[i][j];
}
}
rmatrixlusolvemfast(&lua, &p, n, &x, m, &info, _state);
ae_set_error_flag(rerrors, !testdirectdensesolversunit_rmatrixchecksolutionmfast(&xe, n, m, threshold, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:552");
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_unset1d(&xv, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
rmatrixlusolve(&lua, &p, n, &bv, &info, &rep, &xv, _state);
*rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksolution(&xe, n, threshold, info, &rep, &xv, _state);
info = 0;
ae_vector_set_length(&bv, n, _state);
ae_v_move(&xv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
rmatrixlusolvefast(&lua, &p, n, &xv, &info, _state);
ae_set_error_flag(rerrors, !testdirectdensesolversunit_rmatrixchecksolutionfast(&xe, n, threshold, info, &xv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:566");
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_unset2d(&x, _state);
rmatrixmixedsolvem(&a, &lua, &p, n, &b, m, &info, &rep, &x, _state);
*rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksolutionm(&xe, n, m, threshold, info, &rep, &x, _state);
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_unset1d(&xv, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
rmatrixmixedsolve(&a, &lua, &p, n, &bv, &info, &rep, &xv, _state);
*rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksolution(&xe, n, threshold, info, &rep, &xv, _state);
/*
* Test DenseSolverRLS():
* * test on original system A*x = b
* * test on overdetermined system with the same solution: (A' A')'*x = (b' b')'
* * test on underdetermined system with the same solution: (A 0 0 0 ) * z = b
*/
info = 0;
testdirectdensesolversunit_unsetlsrep(&repls, _state);
testdirectdensesolversunit_unset1d(&xv, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
rmatrixsolvels(&a, n, n, &bv, 0.0, &info, &repls, &xv, _state);
if( info<=0 )
{
*rerrors = ae_true;
}
else
{
*rerrors = (*rerrors||ae_fp_less(repls.r2,100*ae_machineepsilon))||ae_fp_greater(repls.r2,1+1000*ae_machineepsilon);
*rerrors = (*rerrors||repls.n!=n)||repls.k!=0;
for(i=0; i<=n-1; i++)
{
*rerrors = *rerrors||ae_fp_greater(ae_fabs(xe.ptr.pp_double[i][0]-xv.ptr.p_double[i], _state),threshold);
}
}
info = 0;
testdirectdensesolversunit_unsetlsrep(&repls, _state);
testdirectdensesolversunit_unset1d(&xv, _state);
ae_vector_set_length(&bv, 2*n, _state);
ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
ae_v_move(&bv.ptr.p_double[n], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(n,2*n-1));
ae_matrix_set_length(&atmp, 2*n, n, _state);
copymatrix(&a, 0, n-1, 0, n-1, &atmp, 0, n-1, 0, n-1, _state);
copymatrix(&a, 0, n-1, 0, n-1, &atmp, n, 2*n-1, 0, n-1, _state);
rmatrixsolvels(&atmp, 2*n, n, &bv, 0.0, &info, &repls, &xv, _state);
if( info<=0 )
{
*rerrors = ae_true;
}
else
{
*rerrors = (*rerrors||ae_fp_less(repls.r2,100*ae_machineepsilon))||ae_fp_greater(repls.r2,1+1000*ae_machineepsilon);
*rerrors = (*rerrors||repls.n!=n)||repls.k!=0;
for(i=0; i<=n-1; i++)
{
*rerrors = *rerrors||ae_fp_greater(ae_fabs(xe.ptr.pp_double[i][0]-xv.ptr.p_double[i], _state),threshold);
}
}
info = 0;
testdirectdensesolversunit_unsetlsrep(&repls, _state);
testdirectdensesolversunit_unset1d(&xv, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
ae_matrix_set_length(&atmp, n, 2*n, _state);
copymatrix(&a, 0, n-1, 0, n-1, &atmp, 0, n-1, 0, n-1, _state);
for(i=0; i<=n-1; i++)
{
for(j=n; j<=2*n-1; j++)
{
atmp.ptr.pp_double[i][j] = (double)(0);
}
}
rmatrixsolvels(&atmp, n, 2*n, &bv, 0.0, &info, &repls, &xv, _state);
if( info<=0 )
{
*rerrors = ae_true;
}
else
{
*rerrors = *rerrors||ae_fp_neq(repls.r2,(double)(0));
*rerrors = (*rerrors||repls.n!=2*n)||repls.k!=n;
for(i=0; i<=n-1; i++)
{
*rerrors = *rerrors||ae_fp_greater(ae_fabs(xe.ptr.pp_double[i][0]-xv.ptr.p_double[i], _state),threshold);
}
for(i=n; i<=2*n-1; i++)
{
*rerrors = *rerrors||ae_fp_greater(ae_fabs(xv.ptr.p_double[i], _state),threshold);
}
}
/*
* ********************************************************
* EXACTLY SINGULAR MATRICES
* ability to detect singularity is tested
* ********************************************************
*
* 1. generate different types of singular matrices:
* * zero (TaskKind=0)
* * with zero columns (TaskKind=1)
* * with zero rows (TaskKind=2)
* * with equal rows/columns (TaskKind=2 or 3)
* 2. generate random solution vector xe
* 3. generate right part b=A*xe
* 4. test different methods
*/
for(taskkind=0; taskkind<=4; taskkind++)
{
testdirectdensesolversunit_unset2d(&a, _state);
if( taskkind==0 )
{
/*
* all zeros
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
}
if( taskkind==1 )
{
/*
* there is zero column
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
k = ae_randominteger(n, _state);
ae_v_muld(&a.ptr.pp_double[0][k], a.stride, ae_v_len(0,n-1), 0);
}
if( taskkind==2 )
{
/*
* there is zero row
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
k = ae_randominteger(n, _state);
ae_v_muld(&a.ptr.pp_double[k][0], 1, ae_v_len(0,n-1), 0);
}
if( taskkind==3 )
{
/*
* equal columns
*/
if( n<2 )
{
continue;
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
k = 1+ae_randominteger(n-1, _state);
ae_v_move(&a.ptr.pp_double[0][0], a.stride, &a.ptr.pp_double[0][k], a.stride, ae_v_len(0,n-1));
}
if( taskkind==4 )
{
/*
* equal rows
*/
if( n<2 )
{
continue;
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
k = 1+ae_randominteger(n-1, _state);
ae_v_move(&a.ptr.pp_double[0][0], 1, &a.ptr.pp_double[k][0], 1, ae_v_len(0,n-1));
}
ae_matrix_set_length(&xe, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
xe.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
ae_matrix_set_length(&b, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xe.ptr.pp_double[0][j], xe.stride, ae_v_len(0,n-1));
b.ptr.pp_double[i][j] = v;
}
}
testdirectdensesolversunit_rmatrixmakeacopy(&a, n, n, &lua, _state);
rmatrixlu(&lua, n, n, &p, _state);
/*
* Test RMatrixSolveM()
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_unset2d(&x, _state);
rmatrixsolvem(&a, n, &b, m, ae_fp_greater(ae_randomreal(_state),0.5), &info, &rep, &x, _state);
*rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksingularm(n, m, info, &rep, &x, _state);
/*
* Test RMatrixSolveMFast(); performed only for matrices
* with zero rows or columns
*/
if( (taskkind==0||taskkind==1)||taskkind==2 )
{
info = 0;
ae_matrix_set_length(&x, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_double[i][j] = b.ptr.pp_double[i][j];
}
}
rmatrixsolvemfast(&a, n, &x, m, &info, _state);
*rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksingularmfast(n, m, info, &x, _state);
}
/*
* Test RMatrixSolve()
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_unset2d(&x, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
rmatrixsolve(&a, n, &bv, &info, &rep, &xv, _state);
*rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksingular(n, info, &rep, &xv, _state);
/*
* Test RMatrixSolveFast(); performed only for matrices
* with zero rows or columns
*/
if( (taskkind==0||taskkind==1)||taskkind==2 )
{
info = 0;
ae_vector_set_length(&bv, n, _state);
ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
rmatrixsolvefast(&a, n, &bv, &info, _state);
ae_set_error_flag(rerrors, !testdirectdensesolversunit_rmatrixchecksingularfast(n, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:784");
}
/*
* Test RMatrixLUSolveM()
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_unset2d(&x, _state);
rmatrixlusolvem(&lua, &p, n, &b, m, &info, &rep, &x, _state);
*rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksingularm(n, m, info, &rep, &x, _state);
/*
* Test RMatrixLUSolveMFast(); performed only for matrices
* with zero rows or columns
*/
if( (taskkind==0||taskkind==1)||taskkind==2 )
{
info = 0;
ae_matrix_set_length(&x, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_double[i][j] = b.ptr.pp_double[i][j];
}
}
rmatrixlusolvemfast(&lua, &p, n, &x, m, &info, _state);
ae_set_error_flag(rerrors, !testdirectdensesolversunit_rmatrixchecksingularmfast(n, m, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:808");
}
/*
* Test RMatrixLUSolve()
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_unset2d(&x, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
rmatrixlusolve(&lua, &p, n, &bv, &info, &rep, &xv, _state);
*rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksingular(n, info, &rep, &xv, _state);
/*
* Test RMatrixLUSolveFast(); performed only for matrices
* with zero rows or columns
*/
if( (taskkind==0||taskkind==1)||taskkind==2 )
{
info = 0;
ae_vector_set_length(&bv, n, _state);
ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
rmatrixlusolvefast(&lua, &p, n, &bv, &info, _state);
ae_set_error_flag(rerrors, !testdirectdensesolversunit_rmatrixchecksingularfast(n, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:832");
}
/*
* Test RMatrixMixedSolveM()
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_unset2d(&x, _state);
rmatrixmixedsolvem(&a, &lua, &p, n, &b, m, &info, &rep, &x, _state);
*rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksingularm(n, m, info, &rep, &x, _state);
/*
* Test RMatrixMixedSolve()
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_unset2d(&x, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
rmatrixmixedsolve(&a, &lua, &p, n, &bv, &info, &rep, &xv, _state);
*rerrors = *rerrors||!testdirectdensesolversunit_rmatrixchecksingular(n, info, &rep, &xv, _state);
}
}
}
}
/*
* test iterative improvement
*/
for(pass=1; pass<=passcount; pass++)
{
/*
* Test iterative improvement matrices
*
* A matrix/right part are constructed such that both matrix
* and solution components are within (-1,+1). Such matrix/right part
* have nice properties - system can be solved using iterative
* improvement with |A*x-b| about several ulps of max(1,|b|).
*/
n = 100;
ae_matrix_set_length(&a, n, n, _state);
ae_matrix_set_length(&b, n, 1, _state);
ae_vector_set_length(&bv, n, _state);
ae_vector_set_length(&tx, n, _state);
ae_vector_set_length(&xv, n, _state);
ae_vector_set_length(&y, n, _state);
for(i=0; i<=n-1; i++)
{
xv.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
ae_v_move(&y.ptr.p_double[0], 1, &a.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
xdot(&y, &xv, n, &tx, &v, &verr, _state);
bv.ptr.p_double[i] = v;
}
ae_v_move(&b.ptr.pp_double[0][0], b.stride, &bv.ptr.p_double[0], 1, ae_v_len(0,n-1));
/*
* Test RMatrixSolveM()
*/
testdirectdensesolversunit_unset2d(&x, _state);
rmatrixsolvem(&a, n, &b, 1, ae_true, &info, &rep, &x, _state);
if( info<=0 )
{
*rfserrors = ae_true;
}
else
{
ae_vector_set_length(&xv, n, _state);
ae_v_move(&xv.ptr.p_double[0], 1, &x.ptr.pp_double[0][0], x.stride, ae_v_len(0,n-1));
for(i=0; i<=n-1; i++)
{
ae_v_move(&y.ptr.p_double[0], 1, &a.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
xdot(&y, &xv, n, &tx, &v, &verr, _state);
*rfserrors = *rfserrors||ae_fp_greater(ae_fabs(v-b.ptr.pp_double[i][0], _state),8*ae_machineepsilon*ae_maxreal((double)(1), ae_fabs(b.ptr.pp_double[i][0], _state), _state));
}
}
/*
* Test RMatrixSolve()
*/
testdirectdensesolversunit_unset1d(&xv, _state);
rmatrixsolve(&a, n, &bv, &info, &rep, &xv, _state);
if( info<=0 )
{
*rfserrors = ae_true;
}
else
{
for(i=0; i<=n-1; i++)
{
ae_v_move(&y.ptr.p_double[0], 1, &a.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
xdot(&y, &xv, n, &tx, &v, &verr, _state);
*rfserrors = *rfserrors||ae_fp_greater(ae_fabs(v-bv.ptr.p_double[i], _state),8*ae_machineepsilon*ae_maxreal((double)(1), ae_fabs(bv.ptr.p_double[i], _state), _state));
}
}
/*
* Test LS-solver on the same matrix
*/
rmatrixsolvels(&a, n, n, &bv, 0.0, &info, &repls, &xv, _state);
if( info<=0 )
{
*rfserrors = ae_true;
}
else
{
for(i=0; i<=n-1; i++)
{
ae_v_move(&y.ptr.p_double[0], 1, &a.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
xdot(&y, &xv, n, &tx, &v, &verr, _state);
*rfserrors = *rfserrors||ae_fp_greater(ae_fabs(v-bv.ptr.p_double[i], _state),8*ae_machineepsilon*ae_maxreal((double)(1), ae_fabs(bv.ptr.p_double[i], _state), _state));
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
SPD test
*************************************************************************/
static void testdirectdensesolversunit_testspdsolver(ae_int_t maxn,
ae_int_t maxm,
ae_int_t passcount,
double threshold,
ae_bool* spderrors,
ae_bool* rfserrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix cha;
ae_matrix atmp;
ae_vector p;
ae_matrix xe;
ae_matrix b;
ae_vector bv;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t n;
ae_int_t m;
ae_int_t pass;
ae_int_t taskkind;
double v;
ae_bool isupper;
ae_int_t info;
densesolverreport rep;
densesolverlsreport repls;
ae_matrix x;
ae_vector xv;
ae_vector y;
ae_vector tx;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&cha, 0, sizeof(cha));
memset(&atmp, 0, sizeof(atmp));
memset(&p, 0, sizeof(p));
memset(&xe, 0, sizeof(xe));
memset(&b, 0, sizeof(b));
memset(&bv, 0, sizeof(bv));
memset(&rep, 0, sizeof(rep));
memset(&repls, 0, sizeof(repls));
memset(&x, 0, sizeof(x));
memset(&xv, 0, sizeof(xv));
memset(&y, 0, sizeof(y));
memset(&tx, 0, sizeof(tx));
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&cha, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&atmp, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&p, 0, DT_INT, _state, ae_true);
ae_matrix_init(&xe, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bv, 0, DT_REAL, _state, ae_true);
_densesolverreport_init(&rep, _state, ae_true);
_densesolverlsreport_init(&repls, _state, ae_true);
ae_matrix_init(&x, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xv, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tx, 0, DT_REAL, _state, ae_true);
/*
* General square matrices:
* * test general solvers
* * test least squares solver
*/
for(pass=1; pass<=passcount; pass++)
{
for(n=1; n<=maxn; n++)
{
for(m=1; m<=maxm; m++)
{
/*
* ********************************************************
* WELL CONDITIONED TASKS
* ability to find correct solution is tested
* ********************************************************
*
* 1. generate random well conditioned matrix A.
* 2. generate random solution vector xe
* 3. generate right part b=A*xe
* 4. test different methods on original A
*/
isupper = ae_fp_greater(ae_randomreal(_state),0.5);
spdmatrixrndcond(n, (double)(1000), &a, _state);
testdirectdensesolversunit_rmatrixmakeacopy(&a, n, n, &cha, _state);
if( !spdmatrixcholesky(&cha, n, isupper, _state) )
{
*spderrors = ae_true;
ae_frame_leave(_state);
return;
}
ae_matrix_set_length(&xe, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
xe.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
ae_matrix_set_length(&b, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xe.ptr.pp_double[0][j], xe.stride, ae_v_len(0,n-1));
b.ptr.pp_double[i][j] = v;
}
}
testdirectdensesolversunit_rmatrixdrophalf(&a, n, isupper, _state);
testdirectdensesolversunit_rmatrixdrophalf(&cha, n, isupper, _state);
/*
* Test solvers
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_unset2d(&x, _state);
spdmatrixsolvem(&a, n, isupper, &b, m, &info, &rep, &x, _state);
*spderrors = *spderrors||!testdirectdensesolversunit_rmatrixchecksolutionm(&xe, n, m, threshold, info, &rep, &x, _state);
info = 0;
ae_matrix_set_length(&x, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_double[i][j] = b.ptr.pp_double[i][j];
}
}
spdmatrixsolvemfast(&a, n, isupper, &x, m, &info, _state);
ae_set_error_flag(spderrors, !testdirectdensesolversunit_rmatrixchecksolutionmfast(&xe, n, m, threshold, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1023");
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_unset1d(&xv, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
spdmatrixsolve(&a, n, isupper, &bv, &info, &rep, &xv, _state);
*spderrors = *spderrors||!testdirectdensesolversunit_rmatrixchecksolution(&xe, n, threshold, info, &rep, &xv, _state);
info = 0;
ae_vector_set_length(&bv, n, _state);
ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
spdmatrixsolvefast(&a, n, isupper, &bv, &info, _state);
ae_set_error_flag(spderrors, !testdirectdensesolversunit_rmatrixchecksolutionfast(&xe, n, threshold, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1037");
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_unset2d(&x, _state);
spdmatrixcholeskysolvem(&cha, n, isupper, &b, m, &info, &rep, &x, _state);
*spderrors = *spderrors||!testdirectdensesolversunit_rmatrixchecksolutionm(&xe, n, m, threshold, info, &rep, &x, _state);
info = 0;
ae_matrix_set_length(&x, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_double[i][j] = b.ptr.pp_double[i][j];
}
}
spdmatrixcholeskysolvemfast(&cha, n, isupper, &x, m, &info, _state);
ae_set_error_flag(spderrors, !testdirectdensesolversunit_rmatrixchecksolutionmfast(&xe, n, m, threshold, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1051");
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_unset1d(&xv, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
spdmatrixcholeskysolve(&cha, n, isupper, &bv, &info, &rep, &xv, _state);
*spderrors = *spderrors||!testdirectdensesolversunit_rmatrixchecksolution(&xe, n, threshold, info, &rep, &xv, _state);
info = 0;
ae_vector_set_length(&bv, n, _state);
ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
spdmatrixcholeskysolvefast(&cha, n, isupper, &bv, &info, _state);
ae_set_error_flag(spderrors, !testdirectdensesolversunit_rmatrixchecksolutionfast(&xe, n, threshold, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1065");
/*
* ********************************************************
* EXACTLY SINGULAR MATRICES
* ability to detect singularity is tested
* ********************************************************
*
* 1. generate different types of singular matrices:
* * zero
* * with zero columns
* * with zero rows
* * with equal rows/columns
* 2. generate random solution vector xe
* 3. generate right part b=A*xe
* 4. test different methods
*/
for(taskkind=0; taskkind<=3; taskkind++)
{
testdirectdensesolversunit_unset2d(&a, _state);
if( taskkind==0 )
{
/*
* all zeros
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
}
if( taskkind==1 )
{
/*
* there is zero column
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=i; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j];
}
}
k = ae_randominteger(n, _state);
ae_v_muld(&a.ptr.pp_double[0][k], a.stride, ae_v_len(0,n-1), 0);
ae_v_muld(&a.ptr.pp_double[k][0], 1, ae_v_len(0,n-1), 0);
}
if( taskkind==2 )
{
/*
* there is zero row
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=i; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j];
}
}
k = ae_randominteger(n, _state);
ae_v_muld(&a.ptr.pp_double[k][0], 1, ae_v_len(0,n-1), 0);
ae_v_muld(&a.ptr.pp_double[0][k], a.stride, ae_v_len(0,n-1), 0);
}
if( taskkind==3 )
{
/*
* equal columns/rows
*/
if( n<2 )
{
continue;
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=i; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j];
}
}
k = 1+ae_randominteger(n-1, _state);
ae_v_move(&a.ptr.pp_double[0][0], a.stride, &a.ptr.pp_double[0][k], a.stride, ae_v_len(0,n-1));
ae_v_move(&a.ptr.pp_double[0][0], 1, &a.ptr.pp_double[k][0], 1, ae_v_len(0,n-1));
}
ae_matrix_set_length(&xe, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
xe.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
ae_matrix_set_length(&b, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xe.ptr.pp_double[0][j], xe.stride, ae_v_len(0,n-1));
b.ptr.pp_double[i][j] = v;
}
}
testdirectdensesolversunit_rmatrixmakeacopy(&a, n, n, &cha, _state);
testdirectdensesolversunit_rmatrixdrophalf(&a, n, isupper, _state);
testdirectdensesolversunit_rmatrixdrophalf(&cha, n, isupper, _state);
/*
* Test SPDMatrixSolveM()
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_unset2d(&x, _state);
spdmatrixsolvem(&a, n, isupper, &b, m, &info, &rep, &x, _state);
*spderrors = *spderrors||!testdirectdensesolversunit_rmatrixchecksingularm(n, m, info, &rep, &x, _state);
/*
* Test SPDMatrixSolveMFast()
*/
if( (taskkind==0||taskkind==1)||taskkind==2 )
{
info = 0;
ae_matrix_set_length(&x, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_double[i][j] = b.ptr.pp_double[i][j];
}
}
spdmatrixsolvemfast(&a, n, isupper, &x, m, &info, _state);
ae_set_error_flag(spderrors, !testdirectdensesolversunit_rmatrixchecksingularmfast(n, m, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1181");
}
/*
* Test SPDMatrixSolve()
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_unset2d(&x, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
spdmatrixsolve(&a, n, isupper, &bv, &info, &rep, &xv, _state);
*spderrors = *spderrors||!testdirectdensesolversunit_rmatrixchecksingular(n, info, &rep, &xv, _state);
/*
* Test SPDMatrixSolveFast()
*/
info = 0;
ae_vector_set_length(&bv, n, _state);
ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
spdmatrixsolvefast(&a, n, isupper, &bv, &info, _state);
ae_set_error_flag(spderrors, !testdirectdensesolversunit_rmatrixchecksingular(n, info, &rep, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1202");
/*
* 'equal columns/rows' are degenerate, but
* Cholesky matrix with equal columns/rows IS NOT degenerate,
* so it is not used for testing purposes.
*/
if( taskkind!=3 )
{
/*
* Test SPDMatrixLUSolveM() (and fast version)
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_unset2d(&x, _state);
spdmatrixcholeskysolvem(&cha, n, isupper, &b, m, &info, &rep, &x, _state);
*spderrors = *spderrors||!testdirectdensesolversunit_rmatrixchecksingularm(n, m, info, &rep, &x, _state);
if( (taskkind==0||taskkind==1)||taskkind==2 )
{
info = 0;
ae_matrix_set_length(&x, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_double[i][j] = b.ptr.pp_double[i][j];
}
}
spdmatrixcholeskysolvemfast(&a, n, isupper, &x, m, &info, _state);
ae_set_error_flag(spderrors, !testdirectdensesolversunit_rmatrixchecksingularmfast(n, m, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1227");
}
/*
* Test SPDMatrixLUSolve()
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_unset2d(&x, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
spdmatrixcholeskysolve(&cha, n, isupper, &bv, &info, &rep, &xv, _state);
*spderrors = *spderrors||!testdirectdensesolversunit_rmatrixchecksingular(n, info, &rep, &xv, _state);
if( (taskkind==0||taskkind==1)||taskkind==2 )
{
info = 0;
ae_vector_set_length(&bv, n, _state);
ae_v_move(&bv.ptr.p_double[0], 1, &b.ptr.pp_double[0][0], b.stride, ae_v_len(0,n-1));
spdmatrixcholeskysolvefast(&a, n, isupper, &bv, &info, _state);
ae_set_error_flag(spderrors, !testdirectdensesolversunit_rmatrixchecksingularfast(n, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1246");
}
}
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Real test
*************************************************************************/
static void testdirectdensesolversunit_testcsolver(ae_int_t maxn,
ae_int_t maxm,
ae_int_t passcount,
double threshold,
ae_bool* cerrors,
ae_bool* rfserrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix lua;
ae_matrix atmp;
ae_vector p;
ae_matrix xe;
ae_matrix b;
ae_vector bv;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t n;
ae_int_t m;
ae_int_t pass;
ae_int_t taskkind;
double verr;
ae_complex v;
ae_int_t info;
densesolverreport rep;
densesolverlsreport repls;
ae_matrix x;
ae_vector xv;
ae_vector y;
ae_vector tx;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&lua, 0, sizeof(lua));
memset(&atmp, 0, sizeof(atmp));
memset(&p, 0, sizeof(p));
memset(&xe, 0, sizeof(xe));
memset(&b, 0, sizeof(b));
memset(&bv, 0, sizeof(bv));
memset(&rep, 0, sizeof(rep));
memset(&repls, 0, sizeof(repls));
memset(&x, 0, sizeof(x));
memset(&xv, 0, sizeof(xv));
memset(&y, 0, sizeof(y));
memset(&tx, 0, sizeof(tx));
ae_matrix_init(&a, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&lua, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&atmp, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&p, 0, DT_INT, _state, ae_true);
ae_matrix_init(&xe, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&b, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&bv, 0, DT_COMPLEX, _state, ae_true);
_densesolverreport_init(&rep, _state, ae_true);
_densesolverlsreport_init(&repls, _state, ae_true);
ae_matrix_init(&x, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&xv, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&y, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&tx, 0, DT_REAL, _state, ae_true);
/*
* General square matrices:
* * test general solvers
* * test least squares solver
*/
for(pass=1; pass<=passcount; pass++)
{
for(n=1; n<=maxn; n++)
{
for(m=1; m<=maxm; m++)
{
/*
* ********************************************************
* WELL CONDITIONED TASKS
* ability to find correct solution is tested
* ********************************************************
*
* 1. generate random well conditioned matrix A.
* 2. generate random solution vector xe
* 3. generate right part b=A*xe
* 4. test different methods on original A
*/
cmatrixrndcond(n, (double)(1000), &a, _state);
testdirectdensesolversunit_cmatrixmakeacopy(&a, n, n, &lua, _state);
cmatrixlu(&lua, n, n, &p, _state);
ae_matrix_set_length(&xe, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
xe.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
xe.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
ae_matrix_set_length(&b, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
v = ae_v_cdotproduct(&a.ptr.pp_complex[i][0], 1, "N", &xe.ptr.pp_complex[0][j], xe.stride, "N", ae_v_len(0,n-1));
b.ptr.pp_complex[i][j] = v;
}
}
/*
* Test solvers
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_cunset2d(&x, _state);
cmatrixsolvem(&a, n, &b, m, ae_fp_greater(ae_randomreal(_state),0.5), &info, &rep, &x, _state);
*cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksolutionm(&xe, n, m, threshold, info, &rep, &x, _state);
info = 0;
ae_matrix_set_length(&x, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_complex[i][j] = b.ptr.pp_complex[i][j];
}
}
cmatrixsolvemfast(&a, n, &x, m, &info, _state);
*cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksolutionmfast(&xe, n, m, threshold, info, &x, _state);
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_cunset1d(&xv, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1));
cmatrixsolve(&a, n, &bv, &info, &rep, &xv, _state);
*cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksolution(&xe, n, threshold, info, &rep, &xv, _state);
info = 0;
ae_vector_set_length(&bv, n, _state);
ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1));
cmatrixsolvefast(&a, n, &bv, &info, _state);
*cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksolutionfast(&xe, n, threshold, info, &bv, _state);
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_cunset2d(&x, _state);
cmatrixlusolvem(&lua, &p, n, &b, m, &info, &rep, &x, _state);
*cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksolutionm(&xe, n, m, threshold, info, &rep, &x, _state);
info = 0;
ae_matrix_set_length(&x, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_complex[i][j] = b.ptr.pp_complex[i][j];
}
}
cmatrixlusolvemfast(&lua, &p, n, &x, m, &info, _state);
ae_set_error_flag(cerrors, !testdirectdensesolversunit_cmatrixchecksolutionmfast(&xe, n, m, threshold, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1358");
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_cunset1d(&xv, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1));
cmatrixlusolve(&lua, &p, n, &bv, &info, &rep, &xv, _state);
*cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksolution(&xe, n, threshold, info, &rep, &xv, _state);
info = 0;
ae_vector_set_length(&bv, n, _state);
ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1));
cmatrixlusolvefast(&lua, &p, n, &bv, &info, _state);
ae_set_error_flag(cerrors, !testdirectdensesolversunit_cmatrixchecksolutionfast(&xe, n, threshold, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1372");
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_cunset2d(&x, _state);
cmatrixmixedsolvem(&a, &lua, &p, n, &b, m, &info, &rep, &x, _state);
*cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksolutionm(&xe, n, m, threshold, info, &rep, &x, _state);
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_cunset1d(&xv, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1));
cmatrixmixedsolve(&a, &lua, &p, n, &bv, &info, &rep, &xv, _state);
*cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksolution(&xe, n, threshold, info, &rep, &xv, _state);
/*
* ********************************************************
* EXACTLY SINGULAR MATRICES
* ability to detect singularity is tested
* ********************************************************
*
* 1. generate different types of singular matrices:
* * zero
* * with zero columns
* * with zero rows
* * with equal rows/columns
* 2. generate random solution vector xe
* 3. generate right part b=A*xe
* 4. test different methods
*/
for(taskkind=0; taskkind<=4; taskkind++)
{
testdirectdensesolversunit_cunset2d(&a, _state);
if( taskkind==0 )
{
/*
* all zeros
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
}
if( taskkind==1 )
{
/*
* there is zero column
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
k = ae_randominteger(n, _state);
ae_v_cmuld(&a.ptr.pp_complex[0][k], a.stride, ae_v_len(0,n-1), 0);
}
if( taskkind==2 )
{
/*
* there is zero row
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
k = ae_randominteger(n, _state);
ae_v_cmuld(&a.ptr.pp_complex[k][0], 1, ae_v_len(0,n-1), 0);
}
if( taskkind==3 )
{
/*
* equal columns
*/
if( n<2 )
{
continue;
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
k = 1+ae_randominteger(n-1, _state);
ae_v_cmove(&a.ptr.pp_complex[0][0], a.stride, &a.ptr.pp_complex[0][k], a.stride, "N", ae_v_len(0,n-1));
}
if( taskkind==4 )
{
/*
* equal rows
*/
if( n<2 )
{
continue;
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
k = 1+ae_randominteger(n-1, _state);
ae_v_cmove(&a.ptr.pp_complex[0][0], 1, &a.ptr.pp_complex[k][0], 1, "N", ae_v_len(0,n-1));
}
ae_matrix_set_length(&xe, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
xe.ptr.pp_complex[i][j] = ae_complex_from_d(2*ae_randomreal(_state)-1);
}
}
ae_matrix_set_length(&b, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
v = ae_v_cdotproduct(&a.ptr.pp_complex[i][0], 1, "N", &xe.ptr.pp_complex[0][j], xe.stride, "N", ae_v_len(0,n-1));
b.ptr.pp_complex[i][j] = v;
}
}
testdirectdensesolversunit_cmatrixmakeacopy(&a, n, n, &lua, _state);
cmatrixlu(&lua, n, n, &p, _state);
/*
* Test CMatrixSolveM()
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_cunset2d(&x, _state);
cmatrixsolvem(&a, n, &b, m, ae_fp_greater(ae_randomreal(_state),0.5), &info, &rep, &x, _state);
*cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksingularm(n, m, info, &rep, &x, _state);
/*
* Test CMatrixSolveMFast(); performed only for matrices
* with zero rows or columns
*/
if( (taskkind==0||taskkind==1)||taskkind==2 )
{
info = 0;
ae_matrix_set_length(&x, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_complex[i][j] = b.ptr.pp_complex[i][j];
}
}
cmatrixsolvemfast(&a, n, &x, m, &info, _state);
ae_set_error_flag(cerrors, !testdirectdensesolversunit_cmatrixchecksingularmfast(n, m, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1515");
}
/*
* Test CMatrixSolve()
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_cunset2d(&x, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1));
cmatrixsolve(&a, n, &bv, &info, &rep, &xv, _state);
*cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksingular(n, info, &rep, &xv, _state);
if( (taskkind==0||taskkind==1)||taskkind==2 )
{
info = 0;
ae_vector_set_length(&bv, n, _state);
ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1));
cmatrixsolvefast(&a, n, &bv, &info, _state);
ae_set_error_flag(cerrors, !testdirectdensesolversunit_cmatrixchecksingularfast(n, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1535");
}
/*
* Test CMatrixLUSolveM()
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_cunset2d(&x, _state);
cmatrixlusolvem(&lua, &p, n, &b, m, &info, &rep, &x, _state);
*cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksingularm(n, m, info, &rep, &x, _state);
/*
* Test CMatrixLUSolveMFast()
*/
if( (taskkind==0||taskkind==1)||taskkind==2 )
{
info = 0;
ae_matrix_set_length(&x, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_complex[i][j] = b.ptr.pp_complex[i][j];
}
}
cmatrixlusolvemfast(&lua, &p, n, &x, m, &info, _state);
ae_set_error_flag(cerrors, !testdirectdensesolversunit_cmatrixchecksingularmfast(n, m, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1559");
}
/*
* Test CMatrixLUSolve()
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_cunset2d(&x, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1));
cmatrixlusolve(&lua, &p, n, &bv, &info, &rep, &xv, _state);
*cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksingular(n, info, &rep, &xv, _state);
/*
* Test CMatrixLUSolveFast()
*/
if( (taskkind==0||taskkind==1)||taskkind==2 )
{
info = 0;
ae_vector_set_length(&bv, n, _state);
ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1));
cmatrixlusolvefast(&lua, &p, n, &bv, &info, _state);
ae_set_error_flag(cerrors, !testdirectdensesolversunit_cmatrixchecksingularfast(n, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1582");
}
/*
* Test CMatrixMixedSolveM()
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_cunset2d(&x, _state);
cmatrixmixedsolvem(&a, &lua, &p, n, &b, m, &info, &rep, &x, _state);
*cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksingularm(n, m, info, &rep, &x, _state);
/*
* Test CMatrixMixedSolve()
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_cunset2d(&x, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1));
cmatrixmixedsolve(&a, &lua, &p, n, &bv, &info, &rep, &xv, _state);
*cerrors = *cerrors||!testdirectdensesolversunit_cmatrixchecksingular(n, info, &rep, &xv, _state);
}
}
}
}
/*
* test iterative improvement
*/
for(pass=1; pass<=passcount; pass++)
{
/*
* Test iterative improvement matrices
*
* A matrix/right part are constructed such that both matrix
* and solution components magnitudes are within (-1,+1).
* Such matrix/right part have nice properties - system can
* be solved using iterative improvement with |A*x-b| about
* several ulps of max(1,|b|).
*/
n = 100;
ae_matrix_set_length(&a, n, n, _state);
ae_matrix_set_length(&b, n, 1, _state);
ae_vector_set_length(&bv, n, _state);
ae_vector_set_length(&tx, 2*n, _state);
ae_vector_set_length(&xv, n, _state);
ae_vector_set_length(&y, n, _state);
for(i=0; i<=n-1; i++)
{
xv.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1;
xv.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
ae_v_cmove(&y.ptr.p_complex[0], 1, &a.ptr.pp_complex[i][0], 1, "N", ae_v_len(0,n-1));
xcdot(&y, &xv, n, &tx, &v, &verr, _state);
bv.ptr.p_complex[i] = v;
}
ae_v_cmove(&b.ptr.pp_complex[0][0], b.stride, &bv.ptr.p_complex[0], 1, "N", ae_v_len(0,n-1));
/*
* Test CMatrixSolveM()
*/
testdirectdensesolversunit_cunset2d(&x, _state);
cmatrixsolvem(&a, n, &b, 1, ae_true, &info, &rep, &x, _state);
if( info<=0 )
{
*rfserrors = ae_true;
}
else
{
ae_vector_set_length(&xv, n, _state);
ae_v_cmove(&xv.ptr.p_complex[0], 1, &x.ptr.pp_complex[0][0], x.stride, "N", ae_v_len(0,n-1));
for(i=0; i<=n-1; i++)
{
ae_v_cmove(&y.ptr.p_complex[0], 1, &a.ptr.pp_complex[i][0], 1, "N", ae_v_len(0,n-1));
xcdot(&y, &xv, n, &tx, &v, &verr, _state);
*rfserrors = *rfserrors||ae_fp_greater(ae_c_abs(ae_c_sub(v,b.ptr.pp_complex[i][0]), _state),8*ae_machineepsilon*ae_maxreal((double)(1), ae_c_abs(b.ptr.pp_complex[i][0], _state), _state));
}
}
/*
* Test CMatrixSolve()
*/
testdirectdensesolversunit_cunset1d(&xv, _state);
cmatrixsolve(&a, n, &bv, &info, &rep, &xv, _state);
if( info<=0 )
{
*rfserrors = ae_true;
}
else
{
for(i=0; i<=n-1; i++)
{
ae_v_cmove(&y.ptr.p_complex[0], 1, &a.ptr.pp_complex[i][0], 1, "N", ae_v_len(0,n-1));
xcdot(&y, &xv, n, &tx, &v, &verr, _state);
*rfserrors = *rfserrors||ae_fp_greater(ae_c_abs(ae_c_sub(v,bv.ptr.p_complex[i]), _state),8*ae_machineepsilon*ae_maxreal((double)(1), ae_c_abs(bv.ptr.p_complex[i], _state), _state));
}
}
/*
* TODO: Test LS-solver on the same matrix
*/
}
ae_frame_leave(_state);
}
/*************************************************************************
HPD test
*************************************************************************/
static void testdirectdensesolversunit_testhpdsolver(ae_int_t maxn,
ae_int_t maxm,
ae_int_t passcount,
double threshold,
ae_bool* hpderrors,
ae_bool* rfserrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix cha;
ae_matrix atmp;
ae_vector p;
ae_matrix xe;
ae_matrix b;
ae_vector bv;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t n;
ae_int_t m;
ae_int_t pass;
ae_int_t taskkind;
ae_complex v;
ae_bool isupper;
ae_int_t info;
densesolverreport rep;
densesolverlsreport repls;
ae_matrix x;
ae_vector xv;
ae_vector y;
ae_vector tx;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&cha, 0, sizeof(cha));
memset(&atmp, 0, sizeof(atmp));
memset(&p, 0, sizeof(p));
memset(&xe, 0, sizeof(xe));
memset(&b, 0, sizeof(b));
memset(&bv, 0, sizeof(bv));
memset(&rep, 0, sizeof(rep));
memset(&repls, 0, sizeof(repls));
memset(&x, 0, sizeof(x));
memset(&xv, 0, sizeof(xv));
memset(&y, 0, sizeof(y));
memset(&tx, 0, sizeof(tx));
ae_matrix_init(&a, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&cha, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&atmp, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&p, 0, DT_INT, _state, ae_true);
ae_matrix_init(&xe, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&b, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&bv, 0, DT_COMPLEX, _state, ae_true);
_densesolverreport_init(&rep, _state, ae_true);
_densesolverlsreport_init(&repls, _state, ae_true);
ae_matrix_init(&x, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&xv, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&y, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&tx, 0, DT_COMPLEX, _state, ae_true);
/*
* General square matrices:
* * test general solvers
* * test least squares solver
*/
for(pass=1; pass<=passcount; pass++)
{
for(n=1; n<=maxn; n++)
{
for(m=1; m<=maxm; m++)
{
/*
* ********************************************************
* WELL CONDITIONED TASKS
* ability to find correct solution is tested
* ********************************************************
*
* 1. generate random well conditioned matrix A.
* 2. generate random solution vector xe
* 3. generate right part b=A*xe
* 4. test different methods on original A
*/
isupper = ae_fp_greater(ae_randomreal(_state),0.5);
hpdmatrixrndcond(n, (double)(1000), &a, _state);
testdirectdensesolversunit_cmatrixmakeacopy(&a, n, n, &cha, _state);
if( !hpdmatrixcholesky(&cha, n, isupper, _state) )
{
*hpderrors = ae_true;
ae_frame_leave(_state);
return;
}
ae_matrix_set_length(&xe, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
xe.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
xe.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
ae_matrix_set_length(&b, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
v = ae_v_cdotproduct(&a.ptr.pp_complex[i][0], 1, "N", &xe.ptr.pp_complex[0][j], xe.stride, "N", ae_v_len(0,n-1));
b.ptr.pp_complex[i][j] = v;
}
}
testdirectdensesolversunit_cmatrixdrophalf(&a, n, isupper, _state);
testdirectdensesolversunit_cmatrixdrophalf(&cha, n, isupper, _state);
/*
* Test solvers
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_cunset2d(&x, _state);
hpdmatrixsolvem(&a, n, isupper, &b, m, &info, &rep, &x, _state);
*hpderrors = *hpderrors||!testdirectdensesolversunit_cmatrixchecksolutionm(&xe, n, m, threshold, info, &rep, &x, _state);
info = 0;
ae_matrix_set_length(&x, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_complex[i][j] = b.ptr.pp_complex[i][j];
}
}
hpdmatrixsolvemfast(&a, n, isupper, &x, m, &info, _state);
ae_set_error_flag(hpderrors, !testdirectdensesolversunit_cmatrixchecksolutionmfast(&xe, n, m, threshold, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1771");
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_cunset1d(&xv, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1));
hpdmatrixsolve(&a, n, isupper, &bv, &info, &rep, &xv, _state);
*hpderrors = *hpderrors||!testdirectdensesolversunit_cmatrixchecksolution(&xe, n, threshold, info, &rep, &xv, _state);
info = 0;
ae_vector_set_length(&bv, n, _state);
ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1));
hpdmatrixsolvefast(&a, n, isupper, &bv, &info, _state);
*hpderrors = *hpderrors||!testdirectdensesolversunit_cmatrixchecksolution(&xe, n, threshold, info, &rep, &bv, _state);
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_cunset2d(&x, _state);
hpdmatrixcholeskysolvem(&cha, n, isupper, &b, m, &info, &rep, &x, _state);
*hpderrors = *hpderrors||!testdirectdensesolversunit_cmatrixchecksolutionm(&xe, n, m, threshold, info, &rep, &x, _state);
info = 0;
ae_matrix_set_length(&x, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_complex[i][j] = b.ptr.pp_complex[i][j];
}
}
hpdmatrixcholeskysolvemfast(&cha, n, isupper, &x, m, &info, _state);
ae_set_error_flag(hpderrors, !testdirectdensesolversunit_cmatrixchecksolutionmfast(&xe, n, m, threshold, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1799");
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_cunset1d(&xv, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1));
hpdmatrixcholeskysolve(&cha, n, isupper, &bv, &info, &rep, &xv, _state);
*hpderrors = *hpderrors||!testdirectdensesolversunit_cmatrixchecksolution(&xe, n, threshold, info, &rep, &xv, _state);
info = 0;
ae_vector_set_length(&bv, n, _state);
ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1));
hpdmatrixcholeskysolvefast(&cha, n, isupper, &bv, &info, _state);
ae_set_error_flag(hpderrors, !testdirectdensesolversunit_cmatrixchecksolutionfast(&xe, n, threshold, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1813");
/*
* ********************************************************
* EXACTLY SINGULAR MATRICES
* ability to detect singularity is tested
* ********************************************************
*
* 1. generate different types of singular matrices:
* * zero
* * with zero columns
* * with zero rows
* * with equal rows/columns
* 2. generate random solution vector xe
* 3. generate right part b=A*xe
* 4. test different methods
*/
for(taskkind=0; taskkind<=3; taskkind++)
{
testdirectdensesolversunit_cunset2d(&a, _state);
if( taskkind==0 )
{
/*
* all zeros
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
}
if( taskkind==1 )
{
/*
* there is zero column
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=i; j<=n-1; j++)
{
a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
if( i==j )
{
a.ptr.pp_complex[i][j].y = (double)(0);
}
a.ptr.pp_complex[j][i] = a.ptr.pp_complex[i][j];
}
}
k = ae_randominteger(n, _state);
ae_v_cmuld(&a.ptr.pp_complex[0][k], a.stride, ae_v_len(0,n-1), 0);
ae_v_cmuld(&a.ptr.pp_complex[k][0], 1, ae_v_len(0,n-1), 0);
}
if( taskkind==2 )
{
/*
* there is zero row
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=i; j<=n-1; j++)
{
a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
if( i==j )
{
a.ptr.pp_complex[i][j].y = (double)(0);
}
a.ptr.pp_complex[j][i] = a.ptr.pp_complex[i][j];
}
}
k = ae_randominteger(n, _state);
ae_v_cmuld(&a.ptr.pp_complex[k][0], 1, ae_v_len(0,n-1), 0);
ae_v_cmuld(&a.ptr.pp_complex[0][k], a.stride, ae_v_len(0,n-1), 0);
}
if( taskkind==3 )
{
/*
* equal columns/rows
*/
if( n<2 )
{
continue;
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=i; j<=n-1; j++)
{
a.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
a.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
if( i==j )
{
a.ptr.pp_complex[i][j].y = (double)(0);
}
a.ptr.pp_complex[j][i] = a.ptr.pp_complex[i][j];
}
}
k = 1+ae_randominteger(n-1, _state);
ae_v_cmove(&a.ptr.pp_complex[0][0], a.stride, &a.ptr.pp_complex[0][k], a.stride, "N", ae_v_len(0,n-1));
ae_v_cmove(&a.ptr.pp_complex[0][0], 1, &a.ptr.pp_complex[k][0], 1, "N", ae_v_len(0,n-1));
}
ae_matrix_set_length(&xe, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
xe.ptr.pp_complex[i][j] = ae_complex_from_d(2*ae_randomreal(_state)-1);
}
}
ae_matrix_set_length(&b, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
v = ae_v_cdotproduct(&a.ptr.pp_complex[i][0], 1, "N", &xe.ptr.pp_complex[0][j], xe.stride, "N", ae_v_len(0,n-1));
b.ptr.pp_complex[i][j] = v;
}
}
testdirectdensesolversunit_cmatrixmakeacopy(&a, n, n, &cha, _state);
testdirectdensesolversunit_cmatrixdrophalf(&a, n, isupper, _state);
testdirectdensesolversunit_cmatrixdrophalf(&cha, n, isupper, _state);
/*
* Test SPDMatrixSolveM() (and fast version)
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_cunset2d(&x, _state);
hpdmatrixsolvem(&a, n, isupper, &b, m, &info, &rep, &x, _state);
*hpderrors = *hpderrors||!testdirectdensesolversunit_cmatrixchecksingularm(n, m, info, &rep, &x, _state);
if( (taskkind==0||taskkind==1)||taskkind==2 )
{
info = 0;
ae_matrix_set_length(&x, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_complex[i][j] = b.ptr.pp_complex[i][j];
}
}
hpdmatrixsolvemfast(&a, n, isupper, &x, m, &info, _state);
ae_set_error_flag(hpderrors, !testdirectdensesolversunit_cmatrixchecksingularmfast(n, m, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1934");
}
/*
* Test SPDMatrixSolve()
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_cunset2d(&x, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1));
hpdmatrixsolve(&a, n, isupper, &bv, &info, &rep, &xv, _state);
*hpderrors = *hpderrors||!testdirectdensesolversunit_cmatrixchecksingular(n, info, &rep, &xv, _state);
if( (taskkind==0||taskkind==1)||taskkind==2 )
{
info = 0;
ae_vector_set_length(&bv, n, _state);
ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1));
hpdmatrixsolvefast(&a, n, isupper, &bv, &info, _state);
ae_set_error_flag(hpderrors, !testdirectdensesolversunit_cmatrixchecksingularfast(n, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1953");
}
/*
* 'equal columns/rows' are degenerate, but
* Cholesky matrix with equal columns/rows IS NOT degenerate,
* so it is not used for testing purposes.
*/
if( taskkind!=3 )
{
/*
* Test SPDMatrixCholeskySolveM()/fast
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_cunset2d(&x, _state);
hpdmatrixcholeskysolvem(&cha, n, isupper, &b, m, &info, &rep, &x, _state);
*hpderrors = *hpderrors||!testdirectdensesolversunit_cmatrixchecksingularm(n, m, info, &rep, &x, _state);
if( (taskkind==0||taskkind==1)||taskkind==2 )
{
info = 0;
ae_matrix_set_length(&x, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_complex[i][j] = b.ptr.pp_complex[i][j];
}
}
hpdmatrixcholeskysolvemfast(&cha, n, isupper, &x, m, &info, _state);
ae_set_error_flag(hpderrors, !testdirectdensesolversunit_cmatrixchecksingularmfast(n, m, info, &x, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1979");
}
/*
* Test HPDMatrixCholeskySolve() (fast)
*/
info = 0;
testdirectdensesolversunit_unsetrep(&rep, _state);
testdirectdensesolversunit_cunset2d(&x, _state);
ae_vector_set_length(&bv, n, _state);
ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1));
hpdmatrixcholeskysolve(&cha, n, isupper, &bv, &info, &rep, &xv, _state);
*hpderrors = *hpderrors||!testdirectdensesolversunit_cmatrixchecksingular(n, info, &rep, &xv, _state);
if( (taskkind==0||taskkind==1)||taskkind==2 )
{
ae_vector_set_length(&bv, n, _state);
ae_v_cmove(&bv.ptr.p_complex[0], 1, &b.ptr.pp_complex[0][0], b.stride, "N", ae_v_len(0,n-1));
hpdmatrixcholeskysolvefast(&cha, n, isupper, &bv, &info, _state);
ae_set_error_flag(hpderrors, !testdirectdensesolversunit_cmatrixchecksingularfast(n, info, &bv, _state), __FILE__, __LINE__, "testdirectdensesolversunit.ap:1997");
}
}
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Unsets real matrix
*************************************************************************/
static void testdirectdensesolversunit_unset2d(/* Real */ ae_matrix* x,
ae_state *_state)
{
ae_matrix_set_length(x, 1, 1, _state);
x->ptr.pp_double[0][0] = 2*ae_randomreal(_state)-1;
}
/*************************************************************************
Unsets real vector
*************************************************************************/
static void testdirectdensesolversunit_unset1d(/* Real */ ae_vector* x,
ae_state *_state)
{
ae_vector_set_length(x, 1, _state);
x->ptr.p_double[0] = 2*ae_randomreal(_state)-1;
}
/*************************************************************************
Unsets real matrix
*************************************************************************/
static void testdirectdensesolversunit_cunset2d(/* Complex */ ae_matrix* x,
ae_state *_state)
{
ae_matrix_set_length(x, 1, 1, _state);
x->ptr.pp_complex[0][0] = ae_complex_from_d(2*ae_randomreal(_state)-1);
}
/*************************************************************************
Unsets real vector
*************************************************************************/
static void testdirectdensesolversunit_cunset1d(/* Complex */ ae_vector* x,
ae_state *_state)
{
ae_vector_set_length(x, 1, _state);
x->ptr.p_complex[0] = ae_complex_from_d(2*ae_randomreal(_state)-1);
}
/*************************************************************************
Unsets report
*************************************************************************/
static void testdirectdensesolversunit_unsetrep(densesolverreport* r,
ae_state *_state)
{
r->r1 = (double)(-1);
r->rinf = (double)(-1);
}
/*************************************************************************
Unsets report
*************************************************************************/
static void testdirectdensesolversunit_unsetlsrep(densesolverlsreport* r,
ae_state *_state)
{
r->r2 = (double)(-1);
r->n = -1;
r->k = -1;
testdirectdensesolversunit_unset2d(&r->cx, _state);
}
ae_bool testlinmin(ae_bool silent, ae_state *_state)
{
ae_bool waserrors;
ae_bool result;
waserrors = ae_false;
if( !silent )
{
printf("TESTING LINMIN\n");
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
return result;
}
static ae_int_t testminlbfgsunit_maxoptguardlevel = 1;
static void testminlbfgsunit_testfunc2(minlbfgsstate* state,
ae_state *_state);
static void testminlbfgsunit_testfunc3(minlbfgsstate* state,
ae_state *_state);
static void testminlbfgsunit_calciip2(minlbfgsstate* state,
ae_int_t n,
ae_state *_state);
static void testminlbfgsunit_testpreconditioning(ae_bool* err,
ae_state *_state);
static void testminlbfgsunit_testother(ae_bool* err, ae_state *_state);
static void testminlbfgsunit_testoptguard(ae_bool* wereerrors,
ae_state *_state);
static void testminlbfgsunit_testoptguardc1test0reportfortask0(ae_bool* err,
optguardnonc1test0report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state);
static void testminlbfgsunit_testoptguardc1test1reportfortask0(ae_bool* err,
optguardnonc1test1report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state);
ae_bool testminlbfgs(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_bool waserrors;
ae_bool referror;
ae_bool nonconverror;
ae_bool eqerror;
ae_bool converror;
ae_bool crashtest;
ae_bool othererrors;
ae_bool restartserror;
ae_bool precerror;
ae_bool optguarderr;
ae_int_t n;
ae_int_t m;
ae_vector x;
ae_vector xe;
ae_vector b;
ae_vector xlast;
ae_int_t i;
ae_int_t j;
double v;
ae_matrix a;
ae_vector diagh;
ae_int_t maxits;
minlbfgsstate state;
minlbfgsreport rep;
double diffstep;
ae_int_t dkind;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&xe, 0, sizeof(xe));
memset(&b, 0, sizeof(b));
memset(&xlast, 0, sizeof(xlast));
memset(&a, 0, sizeof(a));
memset(&diagh, 0, sizeof(diagh));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xe, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xlast, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&diagh, 0, DT_REAL, _state, ae_true);
_minlbfgsstate_init(&state, _state, ae_true);
_minlbfgsreport_init(&rep, _state, ae_true);
waserrors = ae_false;
referror = ae_false;
precerror = ae_false;
nonconverror = ae_false;
restartserror = ae_false;
eqerror = ae_false;
converror = ae_false;
crashtest = ae_false;
othererrors = ae_false;
testminlbfgsunit_testpreconditioning(&precerror, _state);
testminlbfgsunit_testother(&othererrors, _state);
/*
* Reference problem
*/
diffstep = 1.0E-6;
for(dkind=0; dkind<=1; dkind++)
{
ae_vector_set_length(&x, 3, _state);
n = 3;
m = 2;
x.ptr.p_double[0] = 100*ae_randomreal(_state)-50;
x.ptr.p_double[1] = 100*ae_randomreal(_state)-50;
x.ptr.p_double[2] = 100*ae_randomreal(_state)-50;
if( dkind==0 )
{
minlbfgscreate(n, m, &x, &state, _state);
}
if( dkind==1 )
{
minlbfgscreatef(n, m, &x, diffstep, &state, _state);
}
minlbfgssetcond(&state, (double)(0), (double)(0), (double)(0), 0, _state);
while(minlbfgsiteration(&state, _state))
{
if( state.needf||state.needfg )
{
state.f = ae_sqr(state.x.ptr.p_double[0]-2, _state)+ae_sqr(state.x.ptr.p_double[1], _state)+ae_sqr(state.x.ptr.p_double[2]-state.x.ptr.p_double[0], _state);
}
if( state.needfg )
{
state.g.ptr.p_double[0] = 2*(state.x.ptr.p_double[0]-2)+2*(state.x.ptr.p_double[0]-state.x.ptr.p_double[2]);
state.g.ptr.p_double[1] = 2*state.x.ptr.p_double[1];
state.g.ptr.p_double[2] = 2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0]);
}
}
minlbfgsresults(&state, &x, &rep, _state);
referror = (((referror||rep.terminationtype<=0)||ae_fp_greater(ae_fabs(x.ptr.p_double[0]-2, _state),0.001))||ae_fp_greater(ae_fabs(x.ptr.p_double[1], _state),0.001))||ae_fp_greater(ae_fabs(x.ptr.p_double[2]-2, _state),0.001);
}
/*
* nonconvex problems with complex surface: we start from point with very small
* gradient, but we need ever smaller gradient in the next step due to
* Wolfe conditions.
*/
diffstep = 1.0E-6;
for(dkind=0; dkind<=1; dkind++)
{
ae_vector_set_length(&x, 1, _state);
n = 1;
m = 1;
v = (double)(-100);
while(ae_fp_less(v,0.1))
{
x.ptr.p_double[0] = v;
if( dkind==0 )
{
minlbfgscreate(n, m, &x, &state, _state);
}
if( dkind==1 )
{
minlbfgscreatef(n, m, &x, diffstep, &state, _state);
}
minlbfgssetcond(&state, 1.0E-9, (double)(0), (double)(0), 0, _state);
while(minlbfgsiteration(&state, _state))
{
if( state.needf||state.needfg )
{
state.f = ae_sqr(state.x.ptr.p_double[0], _state)/(1+ae_sqr(state.x.ptr.p_double[0], _state));
}
if( state.needfg )
{
state.g.ptr.p_double[0] = (2*state.x.ptr.p_double[0]*(1+ae_sqr(state.x.ptr.p_double[0], _state))-ae_sqr(state.x.ptr.p_double[0], _state)*2*state.x.ptr.p_double[0])/ae_sqr(1+ae_sqr(state.x.ptr.p_double[0], _state), _state);
}
}
minlbfgsresults(&state, &x, &rep, _state);
nonconverror = (nonconverror||rep.terminationtype<=0)||ae_fp_greater(ae_fabs(x.ptr.p_double[0], _state),0.001);
v = v+0.1;
}
}
/*
* F2 problem with restarts:
* * make several iterations and restart BEFORE termination
* * iterate and restart AFTER termination
*
* NOTE: step is bounded from above to avoid premature convergence
*/
diffstep = 1.0E-6;
for(dkind=0; dkind<=1; dkind++)
{
ae_vector_set_length(&x, 3, _state);
n = 3;
m = 2;
x.ptr.p_double[0] = 10+10*ae_randomreal(_state);
x.ptr.p_double[1] = 10+10*ae_randomreal(_state);
x.ptr.p_double[2] = 10+10*ae_randomreal(_state);
if( dkind==0 )
{
minlbfgscreate(n, m, &x, &state, _state);
}
if( dkind==1 )
{
minlbfgscreatef(n, m, &x, diffstep, &state, _state);
}
minlbfgssetstpmax(&state, 0.1, _state);
minlbfgssetcond(&state, 0.0000001, 0.0, 0.0, 0, _state);
for(i=0; i<=10; i++)
{
if( !minlbfgsiteration(&state, _state) )
{
break;
}
testminlbfgsunit_testfunc2(&state, _state);
}
x.ptr.p_double[0] = 10+10*ae_randomreal(_state);
x.ptr.p_double[1] = 10+10*ae_randomreal(_state);
x.ptr.p_double[2] = 10+10*ae_randomreal(_state);
minlbfgsrestartfrom(&state, &x, _state);
while(minlbfgsiteration(&state, _state))
{
testminlbfgsunit_testfunc2(&state, _state);
}
minlbfgsresults(&state, &x, &rep, _state);
restartserror = (((restartserror||rep.terminationtype<=0)||ae_fp_greater(ae_fabs(x.ptr.p_double[0]-ae_log((double)(2), _state), _state),0.01))||ae_fp_greater(ae_fabs(x.ptr.p_double[1], _state),0.01))||ae_fp_greater(ae_fabs(x.ptr.p_double[2]-ae_log((double)(2), _state), _state),0.01);
x.ptr.p_double[0] = 10+10*ae_randomreal(_state);
x.ptr.p_double[1] = 10+10*ae_randomreal(_state);
x.ptr.p_double[2] = 10+10*ae_randomreal(_state);
minlbfgsrestartfrom(&state, &x, _state);
while(minlbfgsiteration(&state, _state))
{
testminlbfgsunit_testfunc2(&state, _state);
}
minlbfgsresults(&state, &x, &rep, _state);
restartserror = (((restartserror||rep.terminationtype<=0)||ae_fp_greater(ae_fabs(x.ptr.p_double[0]-ae_log((double)(2), _state), _state),0.01))||ae_fp_greater(ae_fabs(x.ptr.p_double[1], _state),0.01))||ae_fp_greater(ae_fabs(x.ptr.p_double[2]-ae_log((double)(2), _state), _state),0.01);
}
/*
* Linear equations
*/
diffstep = 1.0E-6;
for(n=1; n<=10; n++)
{
/*
* Prepare task
*/
ae_matrix_set_length(&a, n-1+1, n-1+1, _state);
ae_vector_set_length(&x, n-1+1, _state);
ae_vector_set_length(&xe, n-1+1, _state);
ae_vector_set_length(&b, n-1+1, _state);
for(i=0; i<=n-1; i++)
{
xe.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
a.ptr.pp_double[i][i] = a.ptr.pp_double[i][i]+3*ae_sign(a.ptr.pp_double[i][i], _state);
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xe.ptr.p_double[0], 1, ae_v_len(0,n-1));
b.ptr.p_double[i] = v;
}
/*
* Test different M/DKind
*/
for(m=1; m<=n; m++)
{
for(dkind=0; dkind<=1; dkind++)
{
/*
* Solve task
*/
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
if( dkind==0 )
{
minlbfgscreate(n, m, &x, &state, _state);
}
if( dkind==1 )
{
minlbfgscreatef(n, m, &x, diffstep, &state, _state);
}
minlbfgssetcond(&state, (double)(0), (double)(0), (double)(0), 0, _state);
while(minlbfgsiteration(&state, _state))
{
if( state.needf||state.needfg )
{
state.f = (double)(0);
}
if( state.needfg )
{
for(i=0; i<=n-1; i++)
{
state.g.ptr.p_double[i] = (double)(0);
}
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
if( state.needf||state.needfg )
{
state.f = state.f+ae_sqr(v-b.ptr.p_double[i], _state);
}
if( state.needfg )
{
for(j=0; j<=n-1; j++)
{
state.g.ptr.p_double[j] = state.g.ptr.p_double[j]+2*(v-b.ptr.p_double[i])*a.ptr.pp_double[i][j];
}
}
}
}
minlbfgsresults(&state, &x, &rep, _state);
eqerror = eqerror||rep.terminationtype<=0;
for(i=0; i<=n-1; i++)
{
eqerror = eqerror||ae_fp_greater(ae_fabs(x.ptr.p_double[i]-xe.ptr.p_double[i], _state),0.001);
}
}
}
}
/*
* Testing convergence properties
*/
diffstep = 1.0E-6;
for(dkind=0; dkind<=1; dkind++)
{
ae_vector_set_length(&x, 3, _state);
n = 3;
m = 2;
for(i=0; i<=2; i++)
{
x.ptr.p_double[i] = 6*ae_randomreal(_state)-3;
}
if( dkind==0 )
{
minlbfgscreate(n, m, &x, &state, _state);
}
if( dkind==1 )
{
minlbfgscreatef(n, m, &x, diffstep, &state, _state);
}
minlbfgssetcond(&state, 0.001, (double)(0), (double)(0), 0, _state);
while(minlbfgsiteration(&state, _state))
{
testminlbfgsunit_testfunc3(&state, _state);
}
minlbfgsresults(&state, &x, &rep, _state);
converror = converror||rep.terminationtype!=4;
for(i=0; i<=2; i++)
{
x.ptr.p_double[i] = 6*ae_randomreal(_state)-3;
}
if( dkind==0 )
{
minlbfgscreate(n, m, &x, &state, _state);
}
if( dkind==1 )
{
minlbfgscreatef(n, m, &x, diffstep, &state, _state);
}
minlbfgssetcond(&state, (double)(0), 0.001, (double)(0), 0, _state);
while(minlbfgsiteration(&state, _state))
{
testminlbfgsunit_testfunc3(&state, _state);
}
minlbfgsresults(&state, &x, &rep, _state);
converror = converror||rep.terminationtype!=1;
for(i=0; i<=2; i++)
{
x.ptr.p_double[i] = 6*ae_randomreal(_state)-3;
}
if( dkind==0 )
{
minlbfgscreate(n, m, &x, &state, _state);
}
if( dkind==1 )
{
minlbfgscreatef(n, m, &x, diffstep, &state, _state);
}
minlbfgssetcond(&state, (double)(0), (double)(0), 0.001, 0, _state);
while(minlbfgsiteration(&state, _state))
{
testminlbfgsunit_testfunc3(&state, _state);
}
minlbfgsresults(&state, &x, &rep, _state);
converror = converror||rep.terminationtype!=2;
for(i=0; i<=2; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
if( dkind==0 )
{
minlbfgscreate(n, m, &x, &state, _state);
}
if( dkind==1 )
{
minlbfgscreatef(n, m, &x, diffstep, &state, _state);
}
minlbfgssetcond(&state, (double)(0), (double)(0), (double)(0), 10, _state);
while(minlbfgsiteration(&state, _state))
{
testminlbfgsunit_testfunc3(&state, _state);
}
minlbfgsresults(&state, &x, &rep, _state);
converror = (converror||rep.terminationtype!=5)||rep.iterationscount!=10;
}
/*
* Crash test: too many iterations on a simple tasks
* May fail when encounter zero step, underflow or something like that
*/
ae_vector_set_length(&x, 2+1, _state);
n = 3;
m = 2;
maxits = 10000;
for(i=0; i<=2; i++)
{
x.ptr.p_double[i] = 6*ae_randomreal(_state)-3;
}
minlbfgscreate(n, m, &x, &state, _state);
minlbfgssetcond(&state, (double)(0), (double)(0), (double)(0), maxits, _state);
while(minlbfgsiteration(&state, _state))
{
state.f = ae_sqr(ae_exp(state.x.ptr.p_double[0], _state)-2, _state)+ae_sqr(state.x.ptr.p_double[1], _state)+ae_sqr(state.x.ptr.p_double[2]-state.x.ptr.p_double[0], _state);
state.g.ptr.p_double[0] = 2*(ae_exp(state.x.ptr.p_double[0], _state)-2)*ae_exp(state.x.ptr.p_double[0], _state)+2*(state.x.ptr.p_double[0]-state.x.ptr.p_double[2]);
state.g.ptr.p_double[1] = 2*state.x.ptr.p_double[1];
state.g.ptr.p_double[2] = 2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0]);
}
minlbfgsresults(&state, &x, &rep, _state);
crashtest = crashtest||rep.terminationtype<=0;
/*
* Test OptGuard
*/
optguarderr = ae_false;
testminlbfgsunit_testoptguard(&optguarderr, _state);
/*
* end
*/
waserrors = (((((((referror||nonconverror)||eqerror)||converror)||crashtest)||othererrors)||restartserror)||precerror)||optguarderr;
if( !silent )
{
printf("TESTING L-BFGS OPTIMIZATION\n");
printf("REFERENCE PROBLEM: ");
if( referror )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("NON-CONVEX PROBLEM: ");
if( nonconverror )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("LINEAR EQUATIONS: ");
if( eqerror )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("RESTARTS: ");
if( restartserror )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("PRECONDITIONER: ");
if( precerror )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("CONVERGENCE PROPERTIES: ");
if( converror )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("CRASH TEST: ");
if( crashtest )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("OTHER PROPERTIES: ");
if( othererrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("OPTGUARD: ");
if( optguarderr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Calculate test function #2
Simple variation of #1, much more nonlinear, which makes unlikely premature
convergence of algorithm .
*************************************************************************/
static void testminlbfgsunit_testfunc2(minlbfgsstate* state,
ae_state *_state)
{
if( ae_fp_less(state->x.ptr.p_double[0],(double)(100)) )
{
if( state->needf||state->needfg )
{
state->f = ae_sqr(ae_exp(state->x.ptr.p_double[0], _state)-2, _state)+ae_sqr(ae_sqr(state->x.ptr.p_double[1], _state), _state)+ae_sqr(state->x.ptr.p_double[2]-state->x.ptr.p_double[0], _state);
}
if( state->needfg )
{
state->g.ptr.p_double[0] = 2*(ae_exp(state->x.ptr.p_double[0], _state)-2)*ae_exp(state->x.ptr.p_double[0], _state)+2*(state->x.ptr.p_double[0]-state->x.ptr.p_double[2]);
state->g.ptr.p_double[1] = 4*state->x.ptr.p_double[1]*ae_sqr(state->x.ptr.p_double[1], _state);
state->g.ptr.p_double[2] = 2*(state->x.ptr.p_double[2]-state->x.ptr.p_double[0]);
}
}
else
{
if( state->needf||state->needfg )
{
state->f = ae_sqrt(ae_maxrealnumber, _state);
}
if( state->needfg )
{
state->g.ptr.p_double[0] = ae_sqrt(ae_maxrealnumber, _state);
state->g.ptr.p_double[1] = (double)(0);
state->g.ptr.p_double[2] = (double)(0);
}
}
}
/*************************************************************************
Calculate test function #3
Simple variation of #1, much more nonlinear, with non-zero value at minimum.
It achieve two goals:
* makes unlikely premature convergence of algorithm .
* solves some issues with EpsF stopping condition which arise when
F(minimum) is zero
*************************************************************************/
static void testminlbfgsunit_testfunc3(minlbfgsstate* state,
ae_state *_state)
{
double s;
s = 0.001;
if( ae_fp_less(state->x.ptr.p_double[0],(double)(100)) )
{
if( state->needf||state->needfg )
{
state->f = ae_sqr(ae_exp(state->x.ptr.p_double[0], _state)-2, _state)+ae_sqr(ae_sqr(state->x.ptr.p_double[1], _state)+s, _state)+ae_sqr(state->x.ptr.p_double[2]-state->x.ptr.p_double[0], _state);
}
if( state->needfg )
{
state->g.ptr.p_double[0] = 2*(ae_exp(state->x.ptr.p_double[0], _state)-2)*ae_exp(state->x.ptr.p_double[0], _state)+2*(state->x.ptr.p_double[0]-state->x.ptr.p_double[2]);
state->g.ptr.p_double[1] = 2*(ae_sqr(state->x.ptr.p_double[1], _state)+s)*2*state->x.ptr.p_double[1];
state->g.ptr.p_double[2] = 2*(state->x.ptr.p_double[2]-state->x.ptr.p_double[0]);
}
}
else
{
if( state->needf||state->needfg )
{
state->f = ae_sqrt(ae_maxrealnumber, _state);
}
if( state->needfg )
{
state->g.ptr.p_double[0] = ae_sqrt(ae_maxrealnumber, _state);
state->g.ptr.p_double[1] = (double)(0);
state->g.ptr.p_double[2] = (double)(0);
}
}
}
/*************************************************************************
Calculate test function IIP2
f(x) = sum( ((i*i+1)*x[i])^2, i=0..N-1)
It has high condition number which makes fast convergence unlikely without
good preconditioner.
*************************************************************************/
static void testminlbfgsunit_calciip2(minlbfgsstate* state,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
if( state->needf||state->needfg )
{
state->f = (double)(0);
}
for(i=0; i<=n-1; i++)
{
if( state->needf||state->needfg )
{
state->f = state->f+ae_sqr((double)(i*i+1), _state)*ae_sqr(state->x.ptr.p_double[i], _state);
}
if( state->needfg )
{
state->g.ptr.p_double[i] = ae_sqr((double)(i*i+1), _state)*2*state->x.ptr.p_double[i];
}
}
}
/*************************************************************************
This function tests preconditioning
On failure sets Err to True (leaves it unchanged otherwise)
*************************************************************************/
static void testminlbfgsunit_testpreconditioning(ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t pass;
ae_int_t n;
ae_int_t m;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t cntb1;
ae_int_t cntb2;
ae_int_t cntg1;
ae_int_t cntg2;
ae_int_t pkind;
minlbfgsstate state;
minlbfgsreport rep;
ae_vector x;
ae_vector s;
ae_matrix a;
ae_vector diagh;
ae_frame_make(_state, &_frame_block);
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&x, 0, sizeof(x));
memset(&s, 0, sizeof(s));
memset(&a, 0, sizeof(a));
memset(&diagh, 0, sizeof(diagh));
_minlbfgsstate_init(&state, _state, ae_true);
_minlbfgsreport_init(&rep, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&diagh, 0, DT_REAL, _state, ae_true);
m = 1;
k = 50;
/*
* Preconditioner test1.
*
* If
* * B1 is default preconditioner
* * B2 is Cholesky preconditioner with unit diagonal
* * G1 is Cholesky preconditioner based on exact Hessian with perturbations
* * G2 is diagonal precomditioner based on approximate diagonal of Hessian matrix
* then "bad" preconditioners (B1/B2/..) are worse than "good" ones (G1/G2/..).
* "Worse" means more iterations to converge.
*
* We test it using f(x) = sum( ((i*i+1)*x[i])^2, i=0..N-1) and L-BFGS
* optimizer with deliberately small M=1.
*
* N - problem size
* PKind - zero for upper triangular preconditioner, one for lower triangular.
* K - number of repeated passes (should be large enough to average out random factors)
*/
for(n=10; n<=15; n++)
{
pkind = ae_randominteger(2, _state);
ae_vector_set_length(&x, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = (double)(0);
}
minlbfgscreate(n, m, &x, &state, _state);
/*
* Test it with default preconditioner
*/
minlbfgssetprecdefault(&state, _state);
cntb1 = 0;
for(pass=0; pass<=k-1; pass++)
{
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
minlbfgsrestartfrom(&state, &x, _state);
while(minlbfgsiteration(&state, _state))
{
testminlbfgsunit_calciip2(&state, n, _state);
}
minlbfgsresults(&state, &x, &rep, _state);
cntb1 = cntb1+rep.iterationscount;
*err = *err||rep.terminationtype<=0;
}
/*
* Test it with unit preconditioner
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( i==j )
{
a.ptr.pp_double[i][i] = (double)(1);
}
else
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
}
minlbfgssetpreccholesky(&state, &a, pkind==0, _state);
cntb2 = 0;
for(pass=0; pass<=k-1; pass++)
{
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
minlbfgsrestartfrom(&state, &x, _state);
while(minlbfgsiteration(&state, _state))
{
testminlbfgsunit_calciip2(&state, n, _state);
}
minlbfgsresults(&state, &x, &rep, _state);
cntb2 = cntb2+rep.iterationscount;
*err = *err||rep.terminationtype<=0;
}
/*
* Test it with perturbed Hessian preconditioner
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( i==j )
{
a.ptr.pp_double[i][i] = (i*i+1)*(0.8+0.4*ae_randomreal(_state));
}
else
{
if( (pkind==0&&j>i)||(pkind==1&&jv_nan;
}
}
}
}
minlbfgssetpreccholesky(&state, &a, pkind==0, _state);
cntg1 = 0;
for(pass=0; pass<=k-1; pass++)
{
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
minlbfgsrestartfrom(&state, &x, _state);
while(minlbfgsiteration(&state, _state))
{
testminlbfgsunit_calciip2(&state, n, _state);
}
minlbfgsresults(&state, &x, &rep, _state);
cntg1 = cntg1+rep.iterationscount;
*err = *err||rep.terminationtype<=0;
}
/*
* Test it with perturbed diagonal preconditioner
*/
ae_vector_set_length(&diagh, n, _state);
for(i=0; i<=n-1; i++)
{
diagh.ptr.p_double[i] = 2*ae_sqr((double)(i*i+1), _state)*(0.8+0.4*ae_randomreal(_state));
}
minlbfgssetprecdiag(&state, &diagh, _state);
cntg2 = 0;
for(pass=0; pass<=k-1; pass++)
{
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
minlbfgsrestartfrom(&state, &x, _state);
while(minlbfgsiteration(&state, _state))
{
testminlbfgsunit_calciip2(&state, n, _state);
}
minlbfgsresults(&state, &x, &rep, _state);
cntg2 = cntg2+rep.iterationscount;
*err = *err||rep.terminationtype<=0;
}
/*
* Compare
*/
*err = *err||cntb1=0.999999
*
* where c is either 1.0 or 1.0E+6, M is either 1.0E8, 1.0E20 or +INF
* (we try different combinations)
*/
for(ckind=0; ckind<=1; ckind++)
{
for(mkind=0; mkind<=2; mkind++)
{
/*
* Choose c and M
*/
vc = (double)(1);
vm = (double)(1);
if( ckind==0 )
{
vc = 1.0;
}
if( ckind==1 )
{
vc = 1.0E+6;
}
if( mkind==0 )
{
vm = 1.0E+8;
}
if( mkind==1 )
{
vm = 1.0E+20;
}
if( mkind==2 )
{
vm = _state->v_posinf;
}
/*
* Create optimizer, solve optimization problem
*/
epsg = 1.0E-6*vc;
ae_vector_set_length(&x, 1, _state);
x.ptr.p_double[0] = 0.0;
minlbfgscreate(1, 1, &x, &state, _state);
minlbfgssetcond(&state, epsg, (double)(0), (double)(0), 0, _state);
while(minlbfgsiteration(&state, _state))
{
if( state.needfg )
{
if( ae_fp_less(-0.999999,state.x.ptr.p_double[0])&&ae_fp_less(state.x.ptr.p_double[0],0.999999) )
{
state.f = 1/(1-state.x.ptr.p_double[0])+1/(1+state.x.ptr.p_double[0])+vc*state.x.ptr.p_double[0];
state.g.ptr.p_double[0] = 1/ae_sqr(1-state.x.ptr.p_double[0], _state)-1/ae_sqr(1+state.x.ptr.p_double[0], _state)+vc;
}
else
{
state.f = vm;
}
}
}
minlbfgsresults(&state, &x, &rep, _state);
if( rep.terminationtype<=0 )
{
*err = ae_true;
ae_frame_leave(_state);
return;
}
*err = *err||ae_fp_greater(ae_fabs(1/ae_sqr(1-x.ptr.p_double[0], _state)-1/ae_sqr(1+x.ptr.p_double[0], _state)+vc, _state),epsg);
}
}
/*
* Test integrity checks for NAN/INF:
* * algorithm solves optimization problem, which is normal for some time (quadratic)
* * after 5-th step we choose random component of gradient and consistently spoil
* it by NAN or INF.
* * we check that correct termination code is returned (-8)
*/
n = 100;
for(pass=1; pass<=10; pass++)
{
spoiliteration = 5;
stopiteration = 8;
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
/*
* Gradient can be spoiled by +INF, -INF, NAN
*/
spoilvar = hqrnduniformi(&rs, n, _state);
i = hqrnduniformi(&rs, 3, _state);
spoilval = _state->v_nan;
if( i==0 )
{
spoilval = _state->v_neginf;
}
if( i==1 )
{
spoilval = _state->v_posinf;
}
}
else
{
/*
* Function value can be spoiled only by NAN
* (+INF can be recognized as legitimate value during optimization)
*/
spoilvar = -1;
spoilval = _state->v_nan;
}
spdmatrixrndcond(n, 1.0E5, &fulla, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
minlbfgscreate(n, 1, &x0, &state, _state);
minlbfgssetcond(&state, 0.0, 0.0, 0.0, stopiteration, _state);
minlbfgssetxrep(&state, ae_true, _state);
k = -1;
while(minlbfgsiteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.g.ptr.p_double[i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.f = state.f+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.g.ptr.p_double[i] = state.g.ptr.p_double[i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
if( k>=spoiliteration )
{
if( spoilvar<0 )
{
state.f = spoilval;
}
else
{
state.g.ptr.p_double[spoilvar] = spoilval;
}
}
continue;
}
if( state.xupdated )
{
inc(&k, _state);
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minlbfgsresults(&state, &x1, &rep, _state);
ae_set_error_flag(err, rep.terminationtype!=-8, __FILE__, __LINE__, "testminlbfgsunit.ap:1123");
}
/*
* Check algorithm ability to handle request for termination:
* * to terminate with correct return code = 8
* * to return point which was "current" at the moment of termination
*/
for(pass=1; pass<=50; pass++)
{
n = 3;
ss = (double)(100);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&xlast, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 6+ae_randomreal(_state);
}
stopcallidx = ae_randominteger(20, _state);
maxits = 25;
minlbfgscreate(n, 1, &x, &state, _state);
minlbfgssetcond(&state, (double)(0), (double)(0), (double)(0), maxits, _state);
minlbfgssetxrep(&state, ae_true, _state);
callidx = 0;
terminationrequested = ae_false;
ae_v_move(&xlast.ptr.p_double[0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1));
while(minlbfgsiteration(&state, _state))
{
if( state.needfg )
{
state.f = ss*ae_sqr(ae_exp(state.x.ptr.p_double[0], _state)-2, _state)+ae_sqr(state.x.ptr.p_double[1], _state)+ae_sqr(state.x.ptr.p_double[2]-state.x.ptr.p_double[0], _state);
state.g.ptr.p_double[0] = 2*ss*(ae_exp(state.x.ptr.p_double[0], _state)-2)*ae_exp(state.x.ptr.p_double[0], _state)+2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0])*(-1);
state.g.ptr.p_double[1] = 2*state.x.ptr.p_double[1];
state.g.ptr.p_double[2] = 2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0]);
if( callidx==stopcallidx )
{
minlbfgsrequesttermination(&state, _state);
terminationrequested = ae_true;
}
inc(&callidx, _state);
continue;
}
if( state.xupdated )
{
if( !terminationrequested )
{
ae_v_move(&xlast.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minlbfgsresults(&state, &x, &rep, _state);
ae_set_error_flag(err, rep.terminationtype!=8, __FILE__, __LINE__, "testminlbfgsunit.ap:1173");
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(err, ae_fp_neq(x.ptr.p_double[i],xlast.ptr.p_double[i]), __FILE__, __LINE__, "testminlbfgsunit.ap:1175");
}
}
ae_frame_leave(_state);
}
/*************************************************************************
This function tests OptGuard
On failure sets error flag.
*************************************************************************/
static void testminlbfgsunit_testoptguard(ae_bool* wereerrors,
ae_state *_state)
{
ae_frame _frame_block;
hqrndstate rs;
double v;
minlbfgsstate state;
minlbfgsreport rep;
optguardreport ogrep;
optguardnonc1test0report ognonc1test0strrep;
optguardnonc1test0report ognonc1test0lngrep;
optguardnonc1test1report ognonc1test1strrep;
optguardnonc1test1report ognonc1test1lngrep;
ae_int_t i;
ae_int_t j;
ae_int_t n;
ae_int_t m;
ae_matrix a;
ae_matrix a1;
ae_vector s;
ae_vector x0;
ae_vector x1;
ae_vector b;
double diffstep;
ae_int_t pass;
ae_int_t defecttype;
ae_bool failed;
ae_int_t passcount;
ae_int_t maxfails;
ae_int_t failurecounter;
ae_int_t maxc1test0fails;
ae_int_t maxc1test1fails;
ae_int_t c1test0fails;
ae_int_t c1test1fails;
double avgstr0len;
double avglng0len;
double avgstr1len;
double avglng1len;
ae_int_t varidx;
ae_int_t skind;
ae_matrix jactrue;
ae_matrix jacdefect;
ae_frame_make(_state, &_frame_block);
memset(&rs, 0, sizeof(rs));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&ogrep, 0, sizeof(ogrep));
memset(&ognonc1test0strrep, 0, sizeof(ognonc1test0strrep));
memset(&ognonc1test0lngrep, 0, sizeof(ognonc1test0lngrep));
memset(&ognonc1test1strrep, 0, sizeof(ognonc1test1strrep));
memset(&ognonc1test1lngrep, 0, sizeof(ognonc1test1lngrep));
memset(&a, 0, sizeof(a));
memset(&a1, 0, sizeof(a1));
memset(&s, 0, sizeof(s));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&b, 0, sizeof(b));
memset(&jactrue, 0, sizeof(jactrue));
memset(&jacdefect, 0, sizeof(jacdefect));
_hqrndstate_init(&rs, _state, ae_true);
_minlbfgsstate_init(&state, _state, ae_true);
_minlbfgsreport_init(&rep, _state, ae_true);
_optguardreport_init(&ogrep, _state, ae_true);
_optguardnonc1test0report_init(&ognonc1test0strrep, _state, ae_true);
_optguardnonc1test0report_init(&ognonc1test0lngrep, _state, ae_true);
_optguardnonc1test1report_init(&ognonc1test1strrep, _state, ae_true);
_optguardnonc1test1report_init(&ognonc1test1lngrep, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&jactrue, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&jacdefect, 0, 0, DT_REAL, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Check that gradient verification is disabled by default:
* gradient checking for bad problem must return nothing
*/
n = 10;
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 1.0+0.1*i;
}
spdmatrixrndcond(n, 1.0E3, &a, _state);
spdmatrixrndcond(n, 1.0E3, &a1, _state);
minlbfgscreate(n, 3, &x0, &state, _state);
minlbfgssetcond(&state, (double)(0), (double)(0), 1.0E-9, 10, _state);
while(minlbfgsiteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.f = state.f+0.5*state.x.ptr.p_double[i]*v;
}
for(i=0; i<=n-1; i++)
{
state.g.ptr.p_double[i] = (double)(0);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minlbfgsresults(&state, &x1, &rep, _state);
minlbfgsoptguardresults(&state, &ogrep, _state);
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1248");
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1249");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(wereerrors, ogrep.badgradxbase.cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1252");
ae_set_error_flag(wereerrors, ogrep.badgraduser.rows!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1253");
ae_set_error_flag(wereerrors, ogrep.badgraduser.cols!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1254");
ae_set_error_flag(wereerrors, ogrep.badgradnum.rows!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1255");
ae_set_error_flag(wereerrors, ogrep.badgradnum.cols!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1256");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(wereerrors, ogrep.badgradsuspected, __FILE__, __LINE__, "testminlbfgsunit.ap:1259");
ae_set_error_flag(wereerrors, ogrep.badgradfidx!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1260");
ae_set_error_flag(wereerrors, ogrep.badgradvidx!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1261");
/*
* Test that C0/C1 continuity monitoring is disabled by default;
* we solve nonsmooth problem and test that nothing is returned
* by OptGuard.
*/
n = 10;
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
minlbfgscreate(n, 2, &x0, &state, _state);
minlbfgssetcond(&state, (double)(0), (double)(0), 1.0E-9, 50, _state);
while(minlbfgsiteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.g.ptr.p_double[i] = (double)(0);
}
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.f = state.f+ae_fabs(v, _state);
v = (double)(ae_sign(v, _state));
for(j=0; j<=n-1; j++)
{
state.g.ptr.p_double[j] = state.g.ptr.p_double[j]+v*a.ptr.pp_double[i][j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minlbfgsresults(&state, &x1, &rep, _state);
minlbfgsoptguardresults(&state, &ogrep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1301");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1302");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminlbfgsunit.ap:1305");
ae_set_error_flag(wereerrors, ogrep.nonc1suspected, __FILE__, __LINE__, "testminlbfgsunit.ap:1306");
ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1307");
ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1308");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx>=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1309");
ae_set_error_flag(wereerrors, ogrep.nonc1test0positive, __FILE__, __LINE__, "testminlbfgsunit.ap:1310");
ae_set_error_flag(wereerrors, ogrep.nonc1test1positive, __FILE__, __LINE__, "testminlbfgsunit.ap:1311");
/*
* Test gradient checking functionality, try various
* defect types:
* * accidental zeroing of some gradient component
* * accidental addition of 1.0 to some component
* * accidental multiplication by 2.0
* Try distorting both target and constraints.
*/
diffstep = 0.001;
n = 10;
m = 2;
for(skind=0; skind<=1; skind++)
{
for(defecttype=-1; defecttype<=2; defecttype++)
{
varidx = hqrnduniformi(&rs, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = ae_pow((double)(10), skind*(30*hqrnduniformr(&rs, _state)-15), _state);
x0.ptr.p_double[i] = (1.0+0.1*i)*s.ptr.p_double[i];
}
spdmatrixrndcond(n, 1.0E3, &a, _state);
spdmatrixrndcond(n, 1.0E3, &a1, _state);
minlbfgscreate(n, m, &x0, &state, _state);
minlbfgsoptguardgradient(&state, diffstep, _state);
minlbfgssetcond(&state, (double)(0), (double)(0), 1.0E-9, 10, _state);
minlbfgssetscale(&state, &s, _state);
while(minlbfgsiteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.f = state.f+0.5*(state.x.ptr.p_double[i]/s.ptr.p_double[i])*v;
state.g.ptr.p_double[i] = v;
}
if( defecttype==0 )
{
state.g.ptr.p_double[varidx] = (double)(0);
}
if( defecttype==1 )
{
state.g.ptr.p_double[varidx] = state.g.ptr.p_double[varidx]+1;
}
if( defecttype==2 )
{
state.g.ptr.p_double[varidx] = state.g.ptr.p_double[varidx]*2;
}
for(i=0; i<=n-1; i++)
{
state.g.ptr.p_double[i] = state.g.ptr.p_double[i]/s.ptr.p_double[i];
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minlbfgsresults(&state, &x1, &rep, _state);
minlbfgsoptguardresults(&state, &ogrep, _state);
/*
* Check that something is returned
*/
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1377");
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1378");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Compute reference values for true and spoiled Jacobian at X0
*/
ae_set_error_flag(wereerrors, !isfinitevector(&ogrep.badgradxbase, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1385");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_matrix_set_length(&jactrue, 1, n, _state);
ae_matrix_set_length(&jacdefect, 1, n, _state);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+ogrep.badgradxbase.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
jactrue.ptr.pp_double[0][i] = v;
jacdefect.ptr.pp_double[0][i] = v;
}
if( defecttype==0 )
{
jacdefect.ptr.pp_double[0][varidx] = (double)(0);
}
if( defecttype==1 )
{
jacdefect.ptr.pp_double[0][varidx] = jacdefect.ptr.pp_double[0][varidx]+1;
}
if( defecttype==2 )
{
jacdefect.ptr.pp_double[0][varidx] = jacdefect.ptr.pp_double[0][varidx]*2;
}
for(i=0; i<=n-1; i++)
{
jactrue.ptr.pp_double[0][i] = jactrue.ptr.pp_double[0][i]/s.ptr.p_double[i];
jacdefect.ptr.pp_double[0][i] = jacdefect.ptr.pp_double[0][i]/s.ptr.p_double[i];
}
/*
* Check OptGuard report
*/
ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgraduser, 1, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1413");
ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgradnum, 1, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1414");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
if( defecttype>=0 )
{
ae_set_error_flag(wereerrors, !ogrep.badgradsuspected, __FILE__, __LINE__, "testminlbfgsunit.ap:1419");
ae_set_error_flag(wereerrors, ogrep.badgradfidx!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1420");
ae_set_error_flag(wereerrors, ogrep.badgradvidx!=varidx, __FILE__, __LINE__, "testminlbfgsunit.ap:1421");
}
else
{
ae_set_error_flag(wereerrors, ogrep.badgradsuspected, __FILE__, __LINE__, "testminlbfgsunit.ap:1425");
ae_set_error_flag(wereerrors, ogrep.badgradfidx!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1426");
ae_set_error_flag(wereerrors, ogrep.badgradvidx!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1427");
}
for(j=0; j<=n-1; j++)
{
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jactrue.ptr.pp_double[0][j]-ogrep.badgradnum.ptr.pp_double[0][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testminlbfgsunit.ap:1431");
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jacdefect.ptr.pp_double[0][j]-ogrep.badgraduser.ptr.pp_double[0][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testminlbfgsunit.ap:1432");
}
}
}
/*
* A test for detection of C1 continuity violations in the target.
*
* Target function is a sum of |(x,c_i)| for i=1..N.
* No constraints is present.
* Analytic gradient is provided.
*
* OptGuard should be able to detect violations in more than
* 99.9% of runs; it means that 100 runs should have no more than 4
* failures in all cases (even after multiple repeated tests; according
* to the binomial distribution quantiles).
*
* We select some N and perform exhaustive search for this N.
*/
passcount = 100;
maxfails = 4;
maxc1test0fails = 10;
maxc1test1fails = 10;
n = 1+hqrnduniformi(&rs, 10, _state);
m = 1+hqrnduniformi(&rs, n, _state);
failurecounter = 0;
c1test0fails = 0;
c1test1fails = 0;
avgstr0len = (double)(0);
avglng0len = (double)(0);
avgstr1len = (double)(0);
avglng1len = (double)(0);
for(pass=1; pass<=passcount; pass++)
{
/*
* Formulate problem
*/
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
/*
* Create and try to solve
*/
minlbfgscreate(n, m, &x0, &state, _state);
minlbfgssetcond(&state, (double)(0), (double)(0), 1.0E-9, 50, _state);
minlbfgssetscale(&state, &s, _state);
minlbfgsoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminlbfgsunit_maxoptguardlevel, _state), _state);
while(minlbfgsiteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.g.ptr.p_double[i] = (double)(0);
}
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.f = state.f+ae_fabs(v, _state);
v = (double)(ae_sign(v, _state));
for(j=0; j<=n-1; j++)
{
state.g.ptr.p_double[j] = state.g.ptr.p_double[j]+v*a.ptr.pp_double[i][j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minlbfgsresults(&state, &x1, &rep, _state);
minlbfgsoptguardresults(&state, &ogrep, _state);
/*
* Check basic properties of the solution
*/
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1514");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1515");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Check generic OptGuard report: distinguish between "hard"
* failures which result in immediate termination
* (C0 violation being reported) and "soft" ones
* (C1 violation is NOT reported) which accumulate
* until we exhaust limit.
*/
ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminlbfgsunit.ap:1526");
ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1527");
failed = ae_false;
failed = failed||optguardallclear(&ogrep, _state);
failed = failed||!ogrep.nonc1suspected;
failed = failed||ogrep.nonc1fidx!=0;
if( failed )
{
inc(&failurecounter, _state);
}
/*
* Check C1 continuity test #0
*/
minlbfgsoptguardnonc1test0results(&state, &ognonc1test0strrep, &ognonc1test0lngrep, _state);
minlbfgsoptguardnonc1test1results(&state, &ognonc1test1strrep, &ognonc1test1lngrep, _state);
if( ogrep.nonc1test0positive )
{
ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminlbfgsunit.ap:1542");
ae_set_error_flag(wereerrors, !ognonc1test0strrep.positive, __FILE__, __LINE__, "testminlbfgsunit.ap:1543");
ae_set_error_flag(wereerrors, !ognonc1test0lngrep.positive, __FILE__, __LINE__, "testminlbfgsunit.ap:1544");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1545");
testminlbfgsunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0strrep, &a, n, _state);
testminlbfgsunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0lngrep, &a, n, _state);
avgstr0len = avgstr0len+(double)ognonc1test0strrep.cnt/(double)passcount;
avglng0len = avglng0len+(double)ognonc1test0lngrep.cnt/(double)passcount;
}
else
{
ae_set_error_flag(wereerrors, ognonc1test0strrep.positive, __FILE__, __LINE__, "testminlbfgsunit.ap:1553");
ae_set_error_flag(wereerrors, ognonc1test0lngrep.positive, __FILE__, __LINE__, "testminlbfgsunit.ap:1554");
testminlbfgsunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0strrep, &a, n, _state);
testminlbfgsunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0lngrep, &a, n, _state);
inc(&c1test0fails, _state);
}
if( ogrep.nonc1test1positive )
{
ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminlbfgsunit.ap:1561");
ae_set_error_flag(wereerrors, !ognonc1test1strrep.positive, __FILE__, __LINE__, "testminlbfgsunit.ap:1562");
ae_set_error_flag(wereerrors, !ognonc1test1lngrep.positive, __FILE__, __LINE__, "testminlbfgsunit.ap:1563");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1564");
testminlbfgsunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1strrep, &a, n, _state);
testminlbfgsunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1lngrep, &a, n, _state);
avgstr1len = avgstr1len+(double)ognonc1test1strrep.cnt/(double)passcount;
avglng1len = avglng1len+(double)ognonc1test1lngrep.cnt/(double)passcount;
}
else
{
ae_set_error_flag(wereerrors, ognonc1test1strrep.positive, __FILE__, __LINE__, "testminlbfgsunit.ap:1572");
ae_set_error_flag(wereerrors, ognonc1test1lngrep.positive, __FILE__, __LINE__, "testminlbfgsunit.ap:1573");
testminlbfgsunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1strrep, &a, n, _state);
testminlbfgsunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1lngrep, &a, n, _state);
inc(&c1test1fails, _state);
}
}
ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testminlbfgsunit.ap:1580");
ae_set_error_flag(wereerrors, c1test0fails>maxc1test0fails, __FILE__, __LINE__, "testminlbfgsunit.ap:1581");
ae_set_error_flag(wereerrors, c1test1fails>maxc1test1fails, __FILE__, __LINE__, "testminlbfgsunit.ap:1582");
ae_set_error_flag(wereerrors, ae_fp_less_eq(avglng0len,avgstr0len), __FILE__, __LINE__, "testminlbfgsunit.ap:1583");
ae_set_error_flag(wereerrors, ae_fp_less_eq(avglng1len,avgstr1len), __FILE__, __LINE__, "testminlbfgsunit.ap:1584");
/*
* Detection of C1 continuity violations in the target under numerical differentiation:
* * target function is a sum of |(x,c_i)| for i=1..N.
* * no constraints is present.
* * analytic gradient is provided.
*
* OptGuard should always be able to detect violations in more than
* 99% of runs (note: reduced strength when compared with analytic gradient);
* it means that 100 runs should have no more than 10 failures in all cases
* (even after multiple repeated tests; according to the binomial distribution
* quantiles).
*
* We select some N and perform exhaustive search for this N.
*/
diffstep = 0.0001;
passcount = 100;
maxfails = 10;
n = 1+hqrnduniformi(&rs, 10, _state);
m = 1+hqrnduniformi(&rs, n, _state);
failurecounter = 0;
for(pass=1; pass<=passcount; pass++)
{
/*
* Formulate problem
*/
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = 0.01*ae_pow((double)(2), 0.33*hqrndnormal(&rs, _state), _state);
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
/*
* Create and try to solve
*/
minlbfgscreatef(n, m, &x0, diffstep, &state, _state);
minlbfgssetcond(&state, (double)(0), (double)(0), 1.0E-9, 50, _state);
minlbfgsoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminlbfgsunit_maxoptguardlevel, _state), _state);
while(minlbfgsiteration(&state, _state))
{
if( state.needf )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.f = state.f+ae_fabs(v, _state);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minlbfgsresults(&state, &x1, &rep, _state);
minlbfgsoptguardresults(&state, &ogrep, _state);
/*
* Check basic properties of the solution
*/
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1650");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1651");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Check OptGuard report: distinguish between "hard"
* failures which result in immediate termination
* (C0 violation being reported) and "soft" ones
* (C1 violation is NOT reported) which accumulate
* until we exhaust limit.
*/
ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminlbfgsunit.ap:1662");
ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1663");
failed = ae_false;
failed = failed||optguardallclear(&ogrep, _state);
failed = failed||!ogrep.nonc1suspected;
failed = failed||ogrep.nonc1fidx!=0;
if( failed )
{
inc(&failurecounter, _state);
}
}
ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testminlbfgsunit.ap:1671");
/*
* Make sure than no false positives are reported for larger
* problems where numerical noise can be an issue:
* * N=100 dimensions
* * positive-definite quadratic programming problem
* * upper limit on iterations count, MaxIts=25
* We simply test that OptGuard does not return error code.
*/
n = 100;
m = 5;
spdmatrixrndcond(n, 1.0E2, &a, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
x0.ptr.p_double[i] = ae_pow(2.0, hqrndnormal(&rs, _state), _state);
}
minlbfgscreate(n, m, &x0, &state, _state);
minlbfgsoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminlbfgsunit_maxoptguardlevel, _state), _state);
minlbfgssetcond(&state, (double)(0), (double)(0), 1.0E-9, 25, _state);
while(minlbfgsiteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.g.ptr.p_double[i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.f = state.f+0.5*state.x.ptr.p_double[i]*a.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.g.ptr.p_double[i] = state.g.ptr.p_double[i]+a.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minlbfgsresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1715");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1716");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
minlbfgsoptguardresults(&state, &ogrep, _state);
ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1720");
ae_frame_leave(_state);
}
/*************************************************************************
This function tests report of "non-C1" test #0 for task #0
given by matrix A.
On failure sets error flag.
*************************************************************************/
static void testminlbfgsunit_testoptguardc1test0reportfortask0(ae_bool* err,
optguardnonc1test0report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
double vv;
double va;
double vb;
ae_bool hasc1discontinuities;
if( rep->positive )
{
/*
* Check positive report, first checks
*/
ae_set_error_flag(err, rep->fidx!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1747");
ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testminlbfgsunit.ap:1748");
ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testminlbfgsunit.ap:1749");
ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testminlbfgsunit.ap:1750");
ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testminlbfgsunit.ap:1751");
ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testminlbfgsunit.ap:1752");
ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testminlbfgsunit.ap:1753");
ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testminlbfgsunit.ap:1754");
ae_set_error_flag(err, rep->f.cnt!=rep->cnt, __FILE__, __LINE__, "testminlbfgsunit.ap:1755");
ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1756");
ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1757");
ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1758");
ae_set_error_flag(err, !isfinitevector(&rep->f, rep->cnt, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1759");
if( *err )
{
return;
}
/*
* Check consistency of X0, D, Stp and F
*/
for(k=0; k<=rep->cnt-2; k++)
{
ae_set_error_flag(err, ae_fp_greater_eq(rep->stp.ptr.p_double[k],rep->stp.ptr.p_double[k+1]), __FILE__, __LINE__, "testminlbfgsunit.ap:1767");
}
for(k=0; k<=rep->cnt-1; k++)
{
v = (double)(0);
for(i=0; i<=n-1; i++)
{
vv = (double)(0);
for(j=0; j<=n-1; j++)
{
vv = vv+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[k]);
}
v = v+ae_fabs(vv, _state);
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-rep->f.ptr.p_double[k], _state),1.0E-6*ae_maxreal(ae_fabs(v, _state), (double)(1), _state)), __FILE__, __LINE__, "testminlbfgsunit.ap:1780");
}
/*
* Check that interval [#StpIdxA,#StpIdxB] contains at least one discontinuity
*/
hasc1discontinuities = ae_false;
for(i=0; i<=n-1; i++)
{
va = (double)(0);
vb = (double)(0);
for(j=0; j<=n-1; j++)
{
va = va+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxa]);
vb = vb+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxb]);
}
hasc1discontinuities = hasc1discontinuities||ae_sign(va, _state)!=ae_sign(vb, _state);
}
ae_set_error_flag(err, !hasc1discontinuities, __FILE__, __LINE__, "testminlbfgsunit.ap:1798");
}
else
{
/*
* Check negative report: fields must be empty
*/
ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1805");
ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1806");
ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1807");
ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1808");
ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1809");
ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1810");
ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1811");
ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1812");
ae_set_error_flag(err, rep->f.cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1813");
}
}
/*************************************************************************
This function tests report of "non-C1" test #1 for task #0
given by matrix A.
On failure sets error flag.
*************************************************************************/
static void testminlbfgsunit_testoptguardc1test1reportfortask0(ae_bool* err,
optguardnonc1test1report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
double vv;
double va;
double vb;
ae_bool tooclose;
ae_bool hasc1discontinuities;
if( rep->positive )
{
/*
* Check positive report, first checks
*/
ae_set_error_flag(err, rep->fidx!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1841");
ae_set_error_flag(err, rep->vidx<0, __FILE__, __LINE__, "testminlbfgsunit.ap:1842");
ae_set_error_flag(err, rep->vidx>n, __FILE__, __LINE__, "testminlbfgsunit.ap:1843");
ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testminlbfgsunit.ap:1844");
ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testminlbfgsunit.ap:1845");
ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testminlbfgsunit.ap:1846");
ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testminlbfgsunit.ap:1847");
ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testminlbfgsunit.ap:1848");
ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testminlbfgsunit.ap:1849");
ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testminlbfgsunit.ap:1850");
ae_set_error_flag(err, rep->g.cnt!=rep->cnt, __FILE__, __LINE__, "testminlbfgsunit.ap:1851");
ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1852");
ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1853");
ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1854");
ae_set_error_flag(err, !isfinitevector(&rep->g, rep->cnt, _state), __FILE__, __LINE__, "testminlbfgsunit.ap:1855");
if( *err )
{
return;
}
/*
* Check consistency of X0, D, Stp and G
*/
for(k=0; k<=rep->cnt-2; k++)
{
ae_set_error_flag(err, ae_fp_greater_eq(rep->stp.ptr.p_double[k],rep->stp.ptr.p_double[k+1]), __FILE__, __LINE__, "testminlbfgsunit.ap:1863");
}
for(k=0; k<=rep->cnt-1; k++)
{
v = (double)(0);
tooclose = ae_false;
for(i=0; i<=n-1; i++)
{
vv = (double)(0);
for(j=0; j<=n-1; j++)
{
vv = vv+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[k]);
}
v = v+ae_sign(vv, _state)*a->ptr.pp_double[i][rep->vidx];
tooclose = tooclose||ae_fp_less(ae_fabs(vv, _state),1.0E-4);
}
if( !tooclose )
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-rep->g.ptr.p_double[k], _state),1.0E-6*ae_maxreal(ae_fabs(v, _state), (double)(1), _state)), __FILE__, __LINE__, "testminlbfgsunit.ap:1877");
}
}
/*
* Check that interval [#StpIdxA,#StpIdxB] contains at least one discontinuity
*/
tooclose = ae_false;
hasc1discontinuities = ae_false;
for(i=0; i<=n-1; i++)
{
va = (double)(0);
vb = (double)(0);
for(j=0; j<=n-1; j++)
{
va = va+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxa]);
vb = vb+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxb]);
}
tooclose = (tooclose||ae_fp_less(ae_fabs(va, _state),1.0E-8))||ae_fp_less(ae_fabs(vb, _state),1.0E-8);
hasc1discontinuities = hasc1discontinuities||ae_sign(va, _state)!=ae_sign(vb, _state);
}
if( !tooclose )
{
ae_set_error_flag(err, !hasc1discontinuities, __FILE__, __LINE__, "testminlbfgsunit.ap:1898");
}
}
else
{
/*
* Check negative report: fields must be empty
*/
ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1905");
ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1906");
ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1907");
ae_set_error_flag(err, rep->vidx!=-1, __FILE__, __LINE__, "testminlbfgsunit.ap:1908");
ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1909");
ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1910");
ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1911");
ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1912");
ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1913");
ae_set_error_flag(err, rep->g.cnt!=0, __FILE__, __LINE__, "testminlbfgsunit.ap:1914");
}
}
ae_bool testnormestimator(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
double tol;
ae_int_t maxmn;
ae_int_t m;
ae_int_t n;
ae_int_t pass;
ae_int_t passcount;
ae_matrix a;
ae_vector rowsizes;
sparsematrix s;
double snorm;
double enorm;
double enorm2;
ae_int_t nbetter;
double sigma;
ae_int_t i;
ae_int_t j;
normestimatorstate e;
normestimatorstate e2;
ae_bool waserrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&rowsizes, 0, sizeof(rowsizes));
memset(&s, 0, sizeof(s));
memset(&e, 0, sizeof(e));
memset(&e2, 0, sizeof(e2));
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rowsizes, 0, DT_INT, _state, ae_true);
_sparsematrix_init(&s, _state, ae_true);
_normestimatorstate_init(&e, _state, ae_true);
_normestimatorstate_init(&e2, _state, ae_true);
tol = 0.01;
maxmn = 5;
waserrors = ae_false;
/*
* First test: algorithm must correctly determine matrix norm
*/
for(m=1; m<=maxmn; m++)
{
for(n=1; n<=maxmn; n++)
{
/*
* Create estimator with quite large NStart and NIts.
* It should guarantee that we converge to the correct solution.
*/
normestimatorcreate(m, n, 15, 15, &e, _state);
/*
* Try with zero A first
*/
sparsecreate(m, n, 1, &s, _state);
sparseconverttocrs(&s, _state);
normestimatorestimatesparse(&e, &s, _state);
normestimatorresults(&e, &enorm, _state);
waserrors = waserrors||ae_fp_neq(enorm,(double)(0));
/*
* Choose random norm, try with non-zero matrix
* with specified norm.
*/
snorm = ae_exp(10*ae_randomreal(_state)-5, _state);
sparsecreate(m, n, 1, &s, _state);
if( m>=n )
{
/*
* Generate random orthogonal M*M matrix,
* use N leading columns as columns of A
*/
rmatrixrndorthogonal(m, &a, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
sparseset(&s, i, j, snorm*a.ptr.pp_double[i][j], _state);
}
}
}
else
{
/*
* Generate random orthogonal N*N matrix,
* use M leading rows as rows of A
*/
rmatrixrndorthogonal(n, &a, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
sparseset(&s, i, j, snorm*a.ptr.pp_double[i][j], _state);
}
}
}
sparseconverttocrs(&s, _state);
normestimatorestimatesparse(&e, &s, _state);
normestimatorresults(&e, &enorm, _state);
waserrors = (waserrors||ae_fp_greater(enorm,snorm*(1+tol)))||ae_fp_less(enorm,snorm*(1-tol));
}
}
/*
* NStart=10 should give statistically better results than NStart=1.
* In order to test it we perform PassCount attempts to solve random
* problem by means of two estimators: one with NStart=10 and another
* one with NStart=1. Every time we compare two estimates and choose
* better one.
*
* Random variable NBetter is a number of cases when NStart=10 was better.
* Under null hypothesis (no difference) it is binomially distributed
* with mean PassCount/2 and variance PassCount/4. However, we expect
* to have significant deviation to the right, in the area of larger
* values.
*
* NOTE: we use fixed N because this test is independent of problem size.
*/
n = 3;
normestimatorcreate(n, n, 1, 1, &e, _state);
normestimatorcreate(n, n, 10, 1, &e2, _state);
normestimatorsetseed(&e, 0, _state);
normestimatorsetseed(&e2, 0, _state);
nbetter = 0;
passcount = 2000;
sigma = 5.0;
for(pass=1; pass<=passcount; pass++)
{
snorm = ae_pow(10.0, 2*ae_randomreal(_state)-1, _state);
sparsecreate(n, n, 1, &s, _state);
rmatrixrndcond(n, 2.0, &a, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
sparseset(&s, i, j, snorm*a.ptr.pp_double[i][j], _state);
}
}
sparseconverttocrs(&s, _state);
normestimatorestimatesparse(&e, &s, _state);
normestimatorresults(&e, &enorm, _state);
normestimatorestimatesparse(&e2, &s, _state);
normestimatorresults(&e2, &enorm2, _state);
if( ae_fp_less(ae_fabs(enorm2-snorm, _state),ae_fabs(enorm-snorm, _state)) )
{
nbetter = nbetter+1;
}
}
waserrors = waserrors||ae_fp_less((double)(nbetter),0.5*passcount+sigma*ae_sqrt(0.25*passcount, _state));
/*
* Same as previous one (for NStart), but tests dependence on NIts.
*/
n = 3;
normestimatorcreate(n, n, 1, 1, &e, _state);
normestimatorcreate(n, n, 1, 10, &e2, _state);
normestimatorsetseed(&e, 0, _state);
normestimatorsetseed(&e2, 0, _state);
nbetter = 0;
passcount = 2000;
sigma = 5.0;
for(pass=1; pass<=passcount; pass++)
{
snorm = ae_pow(10.0, 2*ae_randomreal(_state)-1, _state);
sparsecreate(n, n, 1, &s, _state);
rmatrixrndcond(n, 2.0, &a, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
sparseset(&s, i, j, snorm*a.ptr.pp_double[i][j], _state);
}
}
sparseconverttocrs(&s, _state);
normestimatorestimatesparse(&e, &s, _state);
normestimatorresults(&e, &enorm, _state);
normestimatorestimatesparse(&e2, &s, _state);
normestimatorresults(&e2, &enorm2, _state);
if( ae_fp_less(ae_fabs(enorm2-snorm, _state),ae_fabs(enorm-snorm, _state)) )
{
nbetter = nbetter+1;
}
}
waserrors = waserrors||ae_fp_less((double)(nbetter),0.5*passcount+sigma*ae_sqrt(0.25*passcount, _state));
/*
* report
*/
if( !silent )
{
printf("TESTING NORM ESTIMATOR\n");
printf("TEST: ");
if( !waserrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
static double testlinlsqrunit_e0 = 1.0E-6;
static double testlinlsqrunit_tolort = 1.0E-4;
static double testlinlsqrunit_emergencye0 = 1.0E-12;
static ae_bool testlinlsqrunit_svdtest(ae_bool silent, ae_state *_state);
static ae_bool testlinlsqrunit_mwcranksvdtest(ae_bool silent,
ae_state *_state);
static ae_bool testlinlsqrunit_mwicranksvdtest(ae_bool silent,
ae_state *_state);
static ae_bool testlinlsqrunit_bidiagonaltest(ae_bool silent,
ae_state *_state);
static ae_bool testlinlsqrunit_zeromatrixtest(ae_bool silent,
ae_state *_state);
static ae_bool testlinlsqrunit_reportcorrectnesstest(ae_bool silent,
ae_state *_state);
static ae_bool testlinlsqrunit_stoppingcriteriatest(ae_bool silent,
ae_state *_state);
static ae_bool testlinlsqrunit_analytictest(ae_bool silent,
ae_state *_state);
static void testlinlsqrunit_testterminationrequests(ae_bool* err,
ae_state *_state);
static ae_bool testlinlsqrunit_isitgoodsolution(/* Real */ ae_matrix* a,
/* Real */ ae_vector* b,
ae_int_t m,
ae_int_t n,
double lambdav,
/* Real */ ae_vector* x,
double epserr,
double epsort,
ae_state *_state);
static ae_bool testlinlsqrunit_preconditionertest(ae_state *_state);
ae_bool testlinlsqr(ae_bool silent, ae_state *_state)
{
ae_bool svdtesterrors;
ae_bool mwcranksvderr;
ae_bool mwicranksvderr;
ae_bool bidiagonalerr;
ae_bool zeromatrixerr;
ae_bool reportcorrectnesserr;
ae_bool stoppingcriteriaerr;
ae_bool analytictesterrors;
ae_bool prectesterrors;
ae_bool termreqerrors;
ae_bool waserrors;
ae_bool result;
termreqerrors = ae_false;
svdtesterrors = testlinlsqrunit_svdtest(ae_true, _state);
mwcranksvderr = testlinlsqrunit_mwcranksvdtest(ae_true, _state);
mwicranksvderr = testlinlsqrunit_mwicranksvdtest(ae_true, _state);
bidiagonalerr = testlinlsqrunit_bidiagonaltest(ae_true, _state);
zeromatrixerr = testlinlsqrunit_zeromatrixtest(ae_true, _state);
reportcorrectnesserr = testlinlsqrunit_reportcorrectnesstest(ae_true, _state);
stoppingcriteriaerr = testlinlsqrunit_stoppingcriteriatest(ae_true, _state);
analytictesterrors = testlinlsqrunit_analytictest(ae_true, _state);
prectesterrors = testlinlsqrunit_preconditionertest(_state);
testlinlsqrunit_testterminationrequests(&termreqerrors, _state);
/*
* report
*/
waserrors = ((((((((svdtesterrors||mwcranksvderr)||mwicranksvderr)||bidiagonalerr)||zeromatrixerr)||reportcorrectnesserr)||stoppingcriteriaerr)||analytictesterrors)||prectesterrors)||termreqerrors;
if( !silent )
{
printf("TESTING LinLSQR\n");
printf("Different matrix types:\n");
printf("* general M*N ");
if( svdtesterrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* well conditioned M*N ");
if( mwcranksvderr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* rank deficient M*N ");
if( mwicranksvderr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* sparse bidiagonal ");
if( bidiagonalerr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* zero ");
if( zeromatrixerr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("Other properties:\n");
printf("* report correctness ");
if( reportcorrectnesserr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* stopping criteria ");
if( stoppingcriteriaerr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* analytic properties ");
if( analytictesterrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* preconditioner test ");
if( prectesterrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* termination requests ");
if( termreqerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
/*
*was errors?
*/
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
return result;
}
/*************************************************************************
This function generates random MxN problem, solves it with LSQR and
compares with results obtained from SVD solver. Matrix A is generated as
MxN matrix with uniformly distributed random entries, i.e. it has no
special properties (like conditioning or separation of singular values).
We apply random amount regularization to our problem (from zero to large)
in order to test regularizer. Default stopping criteria are used.
Preconditioning is turned off because it skews results for rank-deficient
problems.
INPUT:
Silent - if true then function output report
-- ALGLIB --
Copyright 30.11.2011 by Bochkanov Sergey
*************************************************************************/
static ae_bool testlinlsqrunit_svdtest(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
linlsqrstate s;
linlsqrreport rep;
sparsematrix spa;
ae_matrix a;
ae_vector b;
ae_vector x0;
ae_int_t szn;
ae_int_t szm;
ae_int_t n;
ae_int_t m;
double lambdai;
ae_int_t i;
ae_int_t j;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&spa, 0, sizeof(spa));
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
memset(&x0, 0, sizeof(x0));
_linlsqrstate_init(&s, _state, ae_true);
_linlsqrreport_init(&rep, _state, ae_true);
_sparsematrix_init(&spa, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
szm = 5;
szn = 5;
for(m=1; m<=szm; m++)
{
for(n=1; n<=szn; n++)
{
/*
* Prepare MxN matrix A, right part B, lambda
*/
lambdai = ae_randomreal(_state);
ae_matrix_set_length(&a, m, n, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
sparsecreate(m, n, 1, &spa, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
sparseset(&spa, i, j, a.ptr.pp_double[i][j], _state);
}
}
sparseconverttocrs(&spa, _state);
ae_vector_set_length(&b, m, _state);
for(i=0; i<=m-1; i++)
{
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
/*
* Solve by calling LinLSQRIteration
*/
linlsqrcreate(m, n, &s, _state);
linlsqrsetb(&s, &b, _state);
linlsqrsetlambdai(&s, lambdai, _state);
linlsqrsetprecunit(&s, _state);
while(linlsqriteration(&s, _state))
{
if( s.needmv )
{
for(i=0; i<=m-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
}
}
if( s.needmtv )
{
for(i=0; i<=n-1; i++)
{
s.mtv.ptr.p_double[i] = (double)(0);
for(j=0; j<=m-1; j++)
{
s.mtv.ptr.p_double[i] = s.mtv.ptr.p_double[i]+a.ptr.pp_double[j][i]*s.x.ptr.p_double[j];
}
}
}
}
linlsqrresults(&s, &x0, &rep, _state);
if( !testlinlsqrunit_isitgoodsolution(&a, &b, m, n, lambdai, &x0, testlinlsqrunit_e0, testlinlsqrunit_tolort, _state) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
/*
*test LinLSQRRestart and LinLSQRSolveSparse
*/
linlsqrrestart(&s, _state);
linlsqrsolvesparse(&s, &spa, &b, _state);
linlsqrresults(&s, &x0, &rep, _state);
if( !testlinlsqrunit_isitgoodsolution(&a, &b, m, n, lambdai, &x0, testlinlsqrunit_e0, testlinlsqrunit_tolort, _state) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
if( !silent )
{
printf("SVDTest::Ok\n");
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
The test checks that algorithm can solve MxN (with N<=M) well-conditioned
problems - and can do so within exactly N iterations. We use moderate
condition numbers, from 1.0 to 10.0, because larger condition number may
require several additional iterations to converge.
We try different scalings of the A and B.
INPUT:
Silent - if true then function does not outputs results to console
-- ALGLIB --
Copyright 30.11.2011 by Bochkanov Sergey
*************************************************************************/
static ae_bool testlinlsqrunit_mwcranksvdtest(ae_bool silent,
ae_state *_state)
{
ae_frame _frame_block;
linlsqrstate s;
linlsqrreport rep;
ae_matrix a;
ae_vector b;
double bnorm;
ae_vector x0;
ae_int_t szm;
ae_int_t n;
ae_int_t m;
ae_int_t ns0;
ae_int_t ns1;
ae_int_t nlambdai;
double s0;
double s1;
double lambdai;
double c;
ae_int_t i;
ae_int_t j;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
memset(&x0, 0, sizeof(x0));
_linlsqrstate_init(&s, _state, ae_true);
_linlsqrreport_init(&rep, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
szm = 5;
for(m=1; m<=szm; m++)
{
for(n=1; n<=m; n++)
{
for(nlambdai=0; nlambdai<=3; nlambdai++)
{
for(ns0=-1; ns0<=1; ns0++)
{
for(ns1=-1; ns1<=1; ns1++)
{
/*
* Generate problem:
* * scale factors s0, s1
* * MxN well conditioned A (with condition number C in [1,10] and norm s0)
* * regularization coefficient LambdaI
* * right part b, with |b|=s1
*/
s0 = ae_pow((double)(10), (double)(10*ns0), _state);
s1 = ae_pow((double)(10), (double)(10*ns1), _state);
lambdai = (double)(0);
if( nlambdai==0 )
{
lambdai = (double)(0);
}
if( nlambdai==1 )
{
lambdai = s0/1000;
}
if( nlambdai==2 )
{
lambdai = s0;
}
if( nlambdai==3 )
{
lambdai = s0*1000;
}
c = (10-1)*ae_randomreal(_state)+1;
rmatrixrndcond(m, c, &a, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = s0*a.ptr.pp_double[i][j];
}
}
ae_vector_set_length(&b, m, _state);
do
{
bnorm = (double)(0);
for(i=0; i<=m-1; i++)
{
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
bnorm = bnorm+b.ptr.p_double[i]*b.ptr.p_double[i];
}
bnorm = ae_sqrt(bnorm, _state);
}
while(ae_fp_less_eq(bnorm,testlinlsqrunit_e0));
for(i=0; i<=m-1; i++)
{
b.ptr.p_double[i] = b.ptr.p_double[i]*s1/bnorm;
}
/*
* Solve by LSQR method
*/
linlsqrcreate(m, n, &s, _state);
linlsqrsetb(&s, &b, _state);
linlsqrsetcond(&s, (double)(0), (double)(0), n, _state);
linlsqrsetlambdai(&s, lambdai, _state);
while(linlsqriteration(&s, _state))
{
if( s.needmv )
{
for(i=0; i<=m-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
}
}
if( s.needmtv )
{
for(i=0; i<=n-1; i++)
{
s.mtv.ptr.p_double[i] = (double)(0);
for(j=0; j<=m-1; j++)
{
s.mtv.ptr.p_double[i] = s.mtv.ptr.p_double[i]+a.ptr.pp_double[j][i]*s.x.ptr.p_double[j];
}
}
}
}
linlsqrresults(&s, &x0, &rep, _state);
if( !testlinlsqrunit_isitgoodsolution(&a, &b, m, n, lambdai, &x0, testlinlsqrunit_e0, testlinlsqrunit_tolort, _state) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
The test checks that algorithm can find a solution with minimum norm for a
singular rectangular problem. System matrix has special property - singular
values are either zero or well separated from zero.
INPUT:
Silent - if true then function output report
-- ALGLIB --
Copyright 30.11.2011 by Bochkanov Sergey
*************************************************************************/
static ae_bool testlinlsqrunit_mwicranksvdtest(ae_bool silent,
ae_state *_state)
{
ae_frame _frame_block;
linlsqrstate s;
linlsqrreport rep;
sparsematrix spa;
ae_vector b;
double bnorm;
ae_vector x0;
ae_int_t szm;
ae_int_t n;
ae_int_t m;
ae_int_t nz;
ae_int_t ns0;
ae_int_t ns1;
ae_int_t nlambdai;
double s0;
double s1;
double lambdai;
ae_int_t i;
ae_int_t j;
ae_matrix a;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&spa, 0, sizeof(spa));
memset(&b, 0, sizeof(b));
memset(&x0, 0, sizeof(x0));
memset(&a, 0, sizeof(a));
_linlsqrstate_init(&s, _state, ae_true);
_linlsqrreport_init(&rep, _state, ae_true);
_sparsematrix_init(&spa, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
result = ae_false;
szm = 5;
for(m=1; m<=szm; m++)
{
for(n=1; n<=m; n++)
{
for(nlambdai=0; nlambdai<=2; nlambdai++)
{
for(ns0=-1; ns0<=1; ns0++)
{
for(ns1=-1; ns1<=1; ns1++)
{
for(nz=0; nz<=n-1; nz++)
{
/*
* Generate problem:
* * scale coefficients s0, s1
* * regularization coefficient LambdaI
* * MxN matrix A, norm(A)=s0, with NZ zero singular values and N-NZ nonzero ones
* * right part b with norm(b)=s1
*/
s0 = ae_pow((double)(10), (double)(10*ns0), _state);
s1 = ae_pow((double)(10), (double)(10*ns1), _state);
lambdai = (double)(0);
if( nlambdai==0 )
{
lambdai = (double)(0);
}
if( nlambdai==1 )
{
lambdai = s0;
}
if( nlambdai==2 )
{
lambdai = s0*1000;
}
ae_matrix_set_length(&a, m, n, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
for(i=0; i<=n-nz-1; i++)
{
a.ptr.pp_double[i][i] = s0*(0.1+0.9*ae_randomreal(_state));
}
rmatrixrndorthogonalfromtheleft(&a, m, n, _state);
rmatrixrndorthogonalfromtheright(&a, m, n, _state);
ae_vector_set_length(&b, m, _state);
do
{
bnorm = (double)(0);
for(i=0; i<=m-1; i++)
{
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
bnorm = bnorm+b.ptr.p_double[i]*b.ptr.p_double[i];
}
bnorm = ae_sqrt(bnorm, _state);
}
while(ae_fp_less_eq(bnorm,testlinlsqrunit_e0));
for(i=0; i<=m-1; i++)
{
b.ptr.p_double[i] = b.ptr.p_double[i]*s1/bnorm;
}
/*
* Solve by LSQR method
*/
linlsqrcreate(m, n, &s, _state);
linlsqrsetb(&s, &b, _state);
linlsqrsetcond(&s, testlinlsqrunit_emergencye0, testlinlsqrunit_emergencye0, n, _state);
linlsqrsetlambdai(&s, lambdai, _state);
while(linlsqriteration(&s, _state))
{
if( s.needmv )
{
for(i=0; i<=m-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
}
}
if( s.needmtv )
{
for(i=0; i<=n-1; i++)
{
s.mtv.ptr.p_double[i] = (double)(0);
for(j=0; j<=m-1; j++)
{
s.mtv.ptr.p_double[i] = s.mtv.ptr.p_double[i]+a.ptr.pp_double[j][i]*s.x.ptr.p_double[j];
}
}
}
}
linlsqrresults(&s, &x0, &rep, _state);
/*
* Check
*/
if( !testlinlsqrunit_isitgoodsolution(&a, &b, m, n, lambdai, &x0, testlinlsqrunit_e0, testlinlsqrunit_tolort, _state) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
The test does check, that algorithm can find a solution with minimum norm,
if a problem has bidiagonal matrix on diagonals of a lot of zeros. This
problem has to lead to case when State.Alpha and State.Beta are zero, and we
we can be sure that the algorithm correctly handles it.
We do not use iteration count as stopping condition, because problem can
be degenerate and we may need more than N iterations to converge.
INPUT:
Silent - if true then function output report
-- ALGLIB --
Copyright 30.11.2011 by Bochkanov Sergey
*************************************************************************/
static ae_bool testlinlsqrunit_bidiagonaltest(ae_bool silent,
ae_state *_state)
{
ae_frame _frame_block;
linlsqrstate s;
linlsqrreport rep;
ae_matrix a;
ae_vector b;
double bnorm;
ae_vector x0;
ae_int_t sz;
ae_int_t n;
ae_int_t m;
ae_int_t minmn;
ae_int_t ns0;
ae_int_t ns1;
double s0;
double s1;
ae_int_t i;
ae_int_t j;
ae_int_t p;
ae_int_t diag;
double pz;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
memset(&x0, 0, sizeof(x0));
_linlsqrstate_init(&s, _state, ae_true);
_linlsqrreport_init(&rep, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
sz = 5;
for(m=1; m<=sz; m++)
{
for(n=1; n<=sz; n++)
{
minmn = ae_minint(m, n, _state);
for(p=0; p<=2; p++)
{
for(ns0=-1; ns0<=1; ns0++)
{
for(ns1=-1; ns1<=1; ns1++)
{
for(diag=0; diag<=1; diag++)
{
/*
* Generate problem:
* * scaling coefficients s0, s1
* * bidiagonal A, with probability of having zero element at diagonal equal to PZ
*/
s0 = ae_pow((double)(10), (double)(10*ns0), _state);
s1 = ae_pow((double)(10), (double)(10*ns1), _state);
pz = 0.0;
if( p==0 )
{
pz = 0.25;
}
if( p==1 )
{
pz = 0.5;
}
if( p==2 )
{
pz = 0.75;
}
ae_matrix_set_length(&a, m, n, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
for(i=0; i<=minmn-1; i++)
{
if( ae_fp_greater_eq(ae_randomreal(_state),pz) )
{
a.ptr.pp_double[i][i] = 2*ae_randomreal(_state)-1;
}
}
for(i=1; i<=minmn-1; i++)
{
if( ae_fp_greater_eq(ae_randomreal(_state),pz) )
{
if( diag==0 )
{
a.ptr.pp_double[i-1][i] = 2*ae_randomreal(_state)-1;
}
if( diag==1 )
{
a.ptr.pp_double[i][i-1] = 2*ae_randomreal(_state)-1;
}
}
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = s0*a.ptr.pp_double[i][j];
}
}
ae_vector_set_length(&b, m, _state);
do
{
bnorm = (double)(0);
for(i=0; i<=m-1; i++)
{
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
bnorm = bnorm+b.ptr.p_double[i]*b.ptr.p_double[i];
}
bnorm = ae_sqrt(bnorm, _state);
}
while(ae_fp_less_eq(bnorm,testlinlsqrunit_e0));
for(i=0; i<=m-1; i++)
{
b.ptr.p_double[i] = b.ptr.p_double[i]*s1/bnorm;
}
/*
* LSQR solution
*/
linlsqrcreate(m, n, &s, _state);
linlsqrsetb(&s, &b, _state);
linlsqrsetcond(&s, testlinlsqrunit_e0, testlinlsqrunit_e0, 0, _state);
while(linlsqriteration(&s, _state))
{
if( s.needmv )
{
for(i=0; i<=m-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
}
}
if( s.needmtv )
{
for(i=0; i<=n-1; i++)
{
s.mtv.ptr.p_double[i] = (double)(0);
for(j=0; j<=m-1; j++)
{
s.mtv.ptr.p_double[i] = s.mtv.ptr.p_double[i]+a.ptr.pp_double[j][i]*s.x.ptr.p_double[j];
}
}
}
}
linlsqrresults(&s, &x0, &rep, _state);
/*
* Check
*/
if( !testlinlsqrunit_isitgoodsolution(&a, &b, m, n, 0.0, &x0, testlinlsqrunit_e0, testlinlsqrunit_tolort, _state) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
The test does check, that algorithm correctly solves a problem in cases:
1. A=0, B<>0;
2. A<>0, B=0;
3. A=0, B=0.
If some part is not zero then it filled with ones.
INPUT:
Silent - if true then function output report
-- ALGLIB --
Copyright 30.11.2011 by Bochkanov Sergey
*************************************************************************/
static ae_bool testlinlsqrunit_zeromatrixtest(ae_bool silent,
ae_state *_state)
{
ae_frame _frame_block;
linlsqrstate s;
linlsqrreport rep;
ae_matrix a;
ae_vector b;
ae_vector x0;
ae_int_t sz;
ae_int_t n;
ae_int_t m;
ae_int_t i;
ae_int_t j;
ae_int_t nzeropart;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
memset(&x0, 0, sizeof(x0));
_linlsqrstate_init(&s, _state, ae_true);
_linlsqrreport_init(&rep, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
sz = 5;
result = ae_false;
for(m=1; m<=sz; m++)
{
for(n=1; n<=sz; n++)
{
for(nzeropart=0; nzeropart<=2; nzeropart++)
{
/*
* Initialize A, b
*/
ae_matrix_set_length(&a, m, n, _state);
if( nzeropart==0||nzeropart==2 )
{
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
}
else
{
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = (double)(1);
}
}
}
ae_vector_set_length(&b, m, _state);
if( nzeropart==1||nzeropart==2 )
{
for(i=0; i<=m-1; i++)
{
b.ptr.p_double[i] = (double)(0);
}
}
else
{
for(i=0; i<=m-1; i++)
{
b.ptr.p_double[i] = (double)(1);
}
}
/*
* LSQR
*/
linlsqrcreate(m, n, &s, _state);
linlsqrsetb(&s, &b, _state);
linlsqrsetcond(&s, (double)(0), (double)(0), n, _state);
while(linlsqriteration(&s, _state))
{
if( s.needmv )
{
for(i=0; i<=m-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
}
}
if( s.needmtv )
{
for(i=0; i<=n-1; i++)
{
s.mtv.ptr.p_double[i] = (double)(0);
for(j=0; j<=m-1; j++)
{
s.mtv.ptr.p_double[i] = s.mtv.ptr.p_double[i]+a.ptr.pp_double[j][i]*s.x.ptr.p_double[j];
}
}
}
}
linlsqrresults(&s, &x0, &rep, _state);
/*
* Check
*/
if( !testlinlsqrunit_isitgoodsolution(&a, &b, m, n, 0.0, &x0, testlinlsqrunit_e0, testlinlsqrunit_tolort, _state) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
The test does check, that algorithm correctly displays a progress report.
INPUT:
Silent - if true then function output report
-- ALGLIB --
Copyright 30.11.2011 by Bochkanov Sergey
*************************************************************************/
static ae_bool testlinlsqrunit_reportcorrectnesstest(ae_bool silent,
ae_state *_state)
{
ae_frame _frame_block;
linlsqrstate s;
linlsqrreport rep;
ae_matrix a;
ae_matrix u;
ae_matrix v;
ae_vector w;
ae_vector b;
ae_vector x0;
ae_vector firstx;
ae_vector lastx;
double rnorm;
double tnorm;
ae_int_t sz;
ae_int_t n;
ae_int_t m;
ae_int_t lambdai;
double mn;
double mx;
double c;
ae_int_t i;
ae_int_t j;
ae_int_t its;
double tmp;
double eps;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&a, 0, sizeof(a));
memset(&u, 0, sizeof(u));
memset(&v, 0, sizeof(v));
memset(&w, 0, sizeof(w));
memset(&b, 0, sizeof(b));
memset(&x0, 0, sizeof(x0));
memset(&firstx, 0, sizeof(firstx));
memset(&lastx, 0, sizeof(lastx));
_linlsqrstate_init(&s, _state, ae_true);
_linlsqrreport_init(&rep, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&firstx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&lastx, 0, DT_REAL, _state, ae_true);
eps = 0.001;
sz = 5;
mn = (double)(-100);
mx = (double)(100);
c = (double)(100);
result = ae_false;
for(m=1; m<=sz; m++)
{
for(n=1; n<=m; n++)
{
for(lambdai=0; lambdai<=1; lambdai++)
{
its = -1;
/*
*initialize matrix A
*/
spdmatrixrndcond(m+n, c, &a, _state);
for(i=m; i<=m+n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( i-m==j )
{
a.ptr.pp_double[i][j] = (double)(lambdai);
}
else
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
}
/*
*initialize b
*/
ae_vector_set_length(&b, m+n, _state);
rnorm = (double)(0);
for(i=0; i<=m+n-1; i++)
{
if( imaxits||rep.terminationtype<=0 )
{
if( !silent )
{
printf("StoppingCriteriaTest::Fail\n");
printf("N=%0d\n",
(int)(n));
printf("IterationsCount=%0d\n",
(int)(rep.iterationscount));
printf("NMV=%0d\n",
(int)(rep.nmv));
printf("TerminationType=%0d\n",
(int)(rep.terminationtype));
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
/*
* Test EpsB.
* Set EpsB=eps, check that |r|=2) and using first N-1 columns as rectangular
* system matrix, and sum of all columns with random non-zero coefficients
* as right part.
*/
for(n=2; n<=sz; n++)
{
for(k0=-1; k0<=1; k0++)
{
for(k1=-1; k1<=1; k1++)
{
/*
* Initialize A with non-unit norm 10^(10*K0), b with non-unit norm 10^(10*K1)
*/
anorm = ae_pow((double)(10), (double)(10*k0), _state);
rmatrixrndorthogonal(n, &a, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = anorm*a.ptr.pp_double[i][j];
}
}
ae_vector_set_length(&b, n, _state);
for(j=0; j<=n-1; j++)
{
b.ptr.p_double[j] = (double)(0);
}
for(i=0; i<=n-1; i++)
{
tmp = 1+ae_randomreal(_state);
ae_v_addd(&b.ptr.p_double[0], 1, &a.ptr.pp_double[0][i], a.stride, ae_v_len(0,n-1), tmp);
}
tmp = (double)(0);
for(i=0; i<=n-1; i++)
{
tmp = tmp+ae_sqr(b.ptr.p_double[i], _state);
}
tmp = ae_pow((double)(10), (double)(10*k1), _state)/ae_sqrt(tmp, _state);
ae_v_muld(&b.ptr.p_double[0], 1, ae_v_len(0,n-1), tmp);
/*
* Test EpsA
*
* NOTE: it is guaranteed that algorithm will terminate with correct
* TerminationType because other stopping criteria (EpsB) won't be satisfied
* on such system.
*/
eps = ae_pow((double)(10), (double)(-(2+ae_randominteger(3, _state))), _state);
epsmod = 1.1*eps;
linlsqrcreate(n, n-1, &s, _state);
linlsqrsetb(&s, &b, _state);
linlsqrsetcond(&s, eps, (double)(0), 0, _state);
while(linlsqriteration(&s, _state))
{
if( s.needmv )
{
for(i=0; i<=n-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-2; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
}
}
if( s.needmtv )
{
for(i=0; i<=n-2; i++)
{
s.mtv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mtv.ptr.p_double[i] = s.mtv.ptr.p_double[i]+a.ptr.pp_double[j][i]*s.x.ptr.p_double[j];
}
}
}
}
linlsqrresults(&s, &x0, &rep, _state);
/*
* Check condition
*/
ae_vector_set_length(&rk, n, _state);
ae_vector_set_length(&ark, n-1, _state);
rknorm = (double)(0);
for(i=0; i<=n-1; i++)
{
rk.ptr.p_double[i] = b.ptr.p_double[i];
for(j=0; j<=n-2; j++)
{
rk.ptr.p_double[i] = rk.ptr.p_double[i]-a.ptr.pp_double[i][j]*x0.ptr.p_double[j];
}
rknorm = rknorm+ae_sqr(rk.ptr.p_double[i], _state);
}
rknorm = ae_sqrt(rknorm, _state);
arknorm = (double)(0);
for(i=0; i<=n-2; i++)
{
ark.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
ark.ptr.p_double[i] = ark.ptr.p_double[i]+a.ptr.pp_double[j][i]*rk.ptr.p_double[j];
}
arknorm = arknorm+ae_sqr(ark.ptr.p_double[i], _state);
}
arknorm = ae_sqrt(arknorm, _state);
if( ae_fp_greater(arknorm/(anorm*rknorm),epsmod)||rep.terminationtype!=4 )
{
if( !silent )
{
printf("StoppingCriteriaTest::Fail\n");
printf("N=%0d\n",
(int)(n));
printf("IterationsCount=%0d\n",
(int)(rep.iterationscount));
printf("NMV=%0d\n",
(int)(rep.nmv));
printf("TerminationType=%0d\n",
(int)(rep.terminationtype));
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
if( !silent )
{
printf("StoppingCriteriaTest::Ok\n");
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This test compares LSQR for original system A*x=b against CG for a
modified system (A'*A)x = A*b. Both algorithms should give same sequences
of trial points (under exact arithmetics, or for very good conditioned
systems).
INPUT:
Silent - if true then function does not output report
-- ALGLIB --
Copyright 30.11.2011 by Bochkanov Sergey
*************************************************************************/
static ae_bool testlinlsqrunit_analytictest(ae_bool silent,
ae_state *_state)
{
ae_frame _frame_block;
linlsqrstate s;
linlsqrreport rep;
ae_matrix a;
ae_matrix xk;
ae_matrix ap;
ae_matrix r;
ae_vector b;
ae_vector tmp;
ae_int_t n;
ae_int_t m;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t smallk;
ae_int_t pointsstored;
double v;
double tol;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&a, 0, sizeof(a));
memset(&xk, 0, sizeof(xk));
memset(&ap, 0, sizeof(ap));
memset(&r, 0, sizeof(r));
memset(&b, 0, sizeof(b));
memset(&tmp, 0, sizeof(tmp));
_linlsqrstate_init(&s, _state, ae_true);
_linlsqrreport_init(&rep, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xk, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ap, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&r, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
/*
* Set:
* * SmallK - number of steps to check, must be small number in order
* to reduce influence of the rounding errors
* * Tol - error tolerance for orthogonality/conjugacy criteria
*/
result = ae_false;
smallk = 4;
tol = 1.0E-7;
for(m=smallk; m<=smallk+5; m++)
{
for(n=smallk; n<=m; n++)
{
/*
* Prepare problem:
* * MxN matrix A, Mx1 vector B
* * A is filled with random values from [-1,+1]
* * diagonal elements are filled with large positive values
* (should make system better conditioned)
*/
ae_matrix_set_length(&a, m, n, _state);
ae_vector_set_length(&b, m, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=n-1; i++)
{
a.ptr.pp_double[i][i] = 10*(1+ae_randomreal(_state));
}
/*
* Solve with LSQR, save trial points into XK[] array
*/
ae_matrix_set_length(&xk, smallk+1, n, _state);
linlsqrcreate(m, n, &s, _state);
linlsqrsetb(&s, &b, _state);
linlsqrsetcond(&s, (double)(0), (double)(0), smallk, _state);
linlsqrsetxrep(&s, ae_true, _state);
pointsstored = 0;
while(linlsqriteration(&s, _state))
{
if( s.needmv )
{
for(i=0; i<=m-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
}
}
if( s.needmtv )
{
for(i=0; i<=n-1; i++)
{
s.mtv.ptr.p_double[i] = (double)(0);
for(j=0; j<=m-1; j++)
{
s.mtv.ptr.p_double[i] = s.mtv.ptr.p_double[i]+a.ptr.pp_double[j][i]*s.x.ptr.p_double[j];
}
}
}
if( s.xupdated )
{
ae_assert(pointsstoredj
* * (p[i]^T)*A'*A*p[j]=0 for i<>j
* where r[i]=(A'*A)*x[i]-A'*b is I-th residual , p[i] is I-th step.
*
* In order to test these criteria we generate two matrices:
* * (PointsStored-1)*M matrix AP (matrix of A*p products)
* * (PointsStored-1)*N matrix R (matrix of residuals)
* Then, we check that each matrix has orthogonal rows.
*/
ae_matrix_set_length(&ap, pointsstored-1, m, _state);
ae_matrix_set_length(&r, pointsstored-1, n, _state);
ae_vector_set_length(&tmp, m, _state);
for(k=0; k<=pointsstored-2; k++)
{
/*
* Calculate K-th row of AP
*/
for(i=0; i<=m-1; i++)
{
ap.ptr.pp_double[k][i] = 0.0;
for(j=0; j<=n-1; j++)
{
ap.ptr.pp_double[k][i] = ap.ptr.pp_double[k][i]+a.ptr.pp_double[i][j]*(xk.ptr.pp_double[k+1][j]-xk.ptr.pp_double[k][j]);
}
}
/*
* Calculate K-th row of R
*/
for(i=0; i<=m-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xk.ptr.pp_double[k][0], 1, ae_v_len(0,n-1));
tmp.ptr.p_double[i] = v-b.ptr.p_double[i];
}
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[0][j], a.stride, &tmp.ptr.p_double[0], 1, ae_v_len(0,m-1));
r.ptr.pp_double[k][j] = v;
}
}
for(i=0; i<=pointsstored-2; i++)
{
for(j=0; j<=pointsstored-2; j++)
{
if( i!=j )
{
v = ae_v_dotproduct(&ap.ptr.pp_double[i][0], 1, &ap.ptr.pp_double[j][0], 1, ae_v_len(0,m-1));
result = result||ae_fp_greater(ae_fabs(v, _state),tol);
v = ae_v_dotproduct(&r.ptr.pp_double[i][0], 1, &r.ptr.pp_double[j][0], 1, ae_v_len(0,n-1));
result = result||ae_fp_greater(ae_fabs(v, _state),tol);
}
}
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This test checks behavior of the termination requests. Sets error flag on
failure, leaves it unchanged on success.
-- ALGLIB --
Copyright 16.11.2018 by Bochkanov Sergey
*************************************************************************/
static void testlinlsqrunit_testterminationrequests(ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
linlsqrstate s;
linlsqrreport rep;
hqrndstate rs;
ae_int_t pass;
ae_matrix a;
ae_vector b;
ae_vector x1;
ae_int_t n;
ae_int_t m;
ae_int_t callsleft;
ae_int_t reportsafterrequest;
ae_bool firstpointreported;
ae_int_t i;
ae_int_t j;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&rs, 0, sizeof(rs));
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
memset(&x1, 0, sizeof(x1));
_linlsqrstate_init(&s, _state, ae_true);
_linlsqrreport_init(&rep, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
hqrndrandomize(&rs, _state);
for(pass=1; pass<=50; pass++)
{
/*
* Prepare problem
*/
callsleft = 1+hqrnduniformi(&rs, 10, _state);
n = callsleft+100+hqrnduniformi(&rs, 50, _state);
m = n+hqrnduniformi(&rs, 50, _state);
ae_matrix_set_length(&a, m, n, _state);
ae_vector_set_length(&b, m, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
/*
* Solve with LSQR, terminate after specified amount of A*x/A^T*x requests.
*/
linlsqrcreate(m, n, &s, _state);
linlsqrsetb(&s, &b, _state);
linlsqrsetcond(&s, (double)(0), (double)(0), n, _state);
linlsqrsetxrep(&s, ae_true, _state);
firstpointreported = ae_false;
reportsafterrequest = 0;
while(linlsqriteration(&s, _state))
{
if( s.needmv )
{
for(i=0; i<=m-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
}
if( firstpointreported )
{
dec(&callsleft, _state);
}
if( callsleft==0 )
{
linlsqrrequesttermination(&s, _state);
}
}
if( s.needmtv )
{
for(i=0; i<=n-1; i++)
{
s.mtv.ptr.p_double[i] = (double)(0);
for(j=0; j<=m-1; j++)
{
s.mtv.ptr.p_double[i] = s.mtv.ptr.p_double[i]+a.ptr.pp_double[j][i]*s.x.ptr.p_double[j];
}
}
if( firstpointreported )
{
dec(&callsleft, _state);
}
if( callsleft==0 )
{
linlsqrrequesttermination(&s, _state);
}
}
if( s.xupdated )
{
firstpointreported = ae_true;
if( callsleft<=0 )
{
inc(&reportsafterrequest, _state);
}
}
}
linlsqrresults(&s, &x1, &rep, _state);
ae_set_error_flag(err, rep.terminationtype!=8, __FILE__, __LINE__, "testlinlsqrunit.ap:1460");
ae_set_error_flag(err, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testlinlsqrunit.ap:1461");
ae_set_error_flag(err, reportsafterrequest!=1, __FILE__, __LINE__, "testlinlsqrunit.ap:1462");
}
ae_frame_leave(_state);
}
/*************************************************************************
This function compares solution calculated by LSQR with one calculated by
SVD solver. Following comparisons are performed:
1. either:
1.a) residual norm |Rk| for LSQR solution is at most epsErr*|B|
1.b) |A^T*Rk|/(|A|*|Rk|)<=EpsOrt
2. norm(LSQR_solution) is at most 1.2*norm(SVD_solution)
Test (1) verifies that LSQR found good solution, test (2) verifies that
LSQR finds solution with close-to-minimum norm. We use factor as large as
1.2 to test deviation from SVD solution because LSQR is not very good at
solving degenerate problems.
INPUT PARAMETERS:
A - array[M,N], system matrix
B - right part
M, N - problem size
LambdaV - regularization value for the problem, >=0
X - array[N], solution found by LSQR
EpsErr - tolerance for |A*x-b|
EpsOrt - tolerance for |A^T*Rk|/(|A|*|Rk|)
RESULT
True, for solution which passess all the tests
*************************************************************************/
static ae_bool testlinlsqrunit_isitgoodsolution(/* Real */ ae_matrix* a,
/* Real */ ae_vector* b,
ae_int_t m,
ae_int_t n,
double lambdav,
/* Real */ ae_vector* x,
double epserr,
double epsort,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix svda;
ae_matrix u;
ae_matrix vt;
ae_vector w;
ae_vector svdx;
ae_vector tmparr;
ae_vector r;
ae_int_t i;
ae_int_t j;
ae_int_t minmn;
ae_bool svdresult;
double v;
double rnorm;
double bnorm;
double anorm;
double atrnorm;
double xnorm;
double svdxnorm;
ae_bool clause1holds;
ae_bool clause2holds;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&svda, 0, sizeof(svda));
memset(&u, 0, sizeof(u));
memset(&vt, 0, sizeof(vt));
memset(&w, 0, sizeof(w));
memset(&svdx, 0, sizeof(svdx));
memset(&tmparr, 0, sizeof(tmparr));
memset(&r, 0, sizeof(r));
ae_matrix_init(&svda, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&vt, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
ae_vector_init(&svdx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmparr, 0, DT_REAL, _state, ae_true);
ae_vector_init(&r, 0, DT_REAL, _state, ae_true);
/*
* Solve regularized problem with SVD solver
*/
ae_matrix_set_length(&svda, m+n, n, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
svda.ptr.pp_double[i][j] = a->ptr.pp_double[i][j];
}
}
for(i=m; i<=m+n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( i-m==j )
{
svda.ptr.pp_double[i][j] = lambdav;
}
else
{
svda.ptr.pp_double[i][j] = (double)(0);
}
}
}
svdresult = rmatrixsvd(&svda, m+n, n, 1, 1, 0, &w, &u, &vt, _state);
ae_assert(svdresult, "LINLSQR: internal error in unit test (SVD failed)", _state);
minmn = ae_minint(m, n, _state);
ae_vector_set_length(&svdx, n, _state);
ae_vector_set_length(&tmparr, minmn, _state);
for(i=0; i<=minmn-1; i++)
{
tmparr.ptr.p_double[i] = (double)(0);
for(j=0; j<=m-1; j++)
{
tmparr.ptr.p_double[i] = tmparr.ptr.p_double[i]+u.ptr.pp_double[j][i]*b->ptr.p_double[j];
}
if( ae_fp_less_eq(w.ptr.p_double[i],ae_sqrt(ae_machineepsilon, _state)*w.ptr.p_double[0]) )
{
tmparr.ptr.p_double[i] = (double)(0);
}
else
{
tmparr.ptr.p_double[i] = tmparr.ptr.p_double[i]/w.ptr.p_double[i];
}
}
for(i=0; i<=n-1; i++)
{
svdx.ptr.p_double[i] = (double)(0);
for(j=0; j<=minmn-1; j++)
{
svdx.ptr.p_double[i] = svdx.ptr.p_double[i]+vt.ptr.pp_double[j][i]*tmparr.ptr.p_double[j];
}
}
/*
* Calculate residual, perform checks 1.a and 1.b:
* * first, we check 1.a
* * in case 1.a fails we check 1.b
*/
ae_vector_set_length(&r, m+n, _state);
for(i=0; i<=m+n-1; i++)
{
v = ae_v_dotproduct(&svda.ptr.pp_double[i][0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
r.ptr.p_double[i] = v;
if( iptr.p_double[i];
}
}
v = ae_v_dotproduct(&r.ptr.p_double[0], 1, &r.ptr.p_double[0], 1, ae_v_len(0,m+n-1));
rnorm = ae_sqrt(v, _state);
v = ae_v_dotproduct(&b->ptr.p_double[0], 1, &b->ptr.p_double[0], 1, ae_v_len(0,m-1));
bnorm = ae_sqrt(v, _state);
if( ae_fp_less_eq(rnorm,epserr*bnorm) )
{
/*
* 1.a is true, no further checks is needed
*/
clause1holds = ae_true;
}
else
{
/*
* 1.a is false, we have to check 1.b
*
* In order to do so, we calculate ||A|| and ||A^T*Rk||. We do
* not store product of A and Rk to some array, all we need is
* just one component of product at time, stored in V.
*
*/
anorm = (double)(0);
atrnorm = (double)(0);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=m+n-1; j++)
{
v = v+svda.ptr.pp_double[j][i]*r.ptr.p_double[j];
anorm = anorm+ae_sqr(svda.ptr.pp_double[j][i], _state);
}
atrnorm = atrnorm+ae_sqr(v, _state);
}
anorm = ae_sqrt(anorm, _state);
atrnorm = ae_sqrt(atrnorm, _state);
clause1holds = ae_fp_eq(anorm*rnorm,(double)(0))||ae_fp_less_eq(atrnorm/(anorm*rnorm),epsort);
}
/*
* Check (2).
* Here we assume that Result=True when we enter this block.
*/
v = ae_v_dotproduct(&x->ptr.p_double[0], 1, &x->ptr.p_double[0], 1, ae_v_len(0,n-1));
xnorm = ae_sqrt(v, _state);
v = ae_v_dotproduct(&svdx.ptr.p_double[0], 1, &svdx.ptr.p_double[0], 1, ae_v_len(0,n-1));
svdxnorm = ae_sqrt(v, _state);
clause2holds = ae_fp_less_eq(xnorm,1.2*svdxnorm);
/*
* End
*/
result = clause1holds&&clause2holds;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Function for testing preconditioned LSQR method.
-- ALGLIB --
Copyright 14.11.2011 by Bochkanov Sergey
*************************************************************************/
static ae_bool testlinlsqrunit_preconditionertest(ae_state *_state)
{
ae_frame _frame_block;
linlsqrstate s;
linlsqrreport rep;
ae_matrix a;
ae_matrix ta;
sparsematrix sa;
ae_vector b;
ae_vector d;
ae_vector xe;
ae_vector x0;
ae_bool bflag;
ae_int_t i;
ae_int_t j;
ae_int_t n;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&a, 0, sizeof(a));
memset(&ta, 0, sizeof(ta));
memset(&sa, 0, sizeof(sa));
memset(&b, 0, sizeof(b));
memset(&d, 0, sizeof(d));
memset(&xe, 0, sizeof(xe));
memset(&x0, 0, sizeof(x0));
_linlsqrstate_init(&s, _state, ae_true);
_linlsqrreport_init(&rep, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ta, 0, 0, DT_REAL, _state, ae_true);
_sparsematrix_init(&sa, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xe, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
/*
* Test 1.
*
* We test automatic diagonal preconditioning used by SolveSparse.
* In order to do so we:
* 1. generate 20*20 matrix A0 with condition number equal to 1.0E1
* 2. generate random "exact" solution xe and right part b=A0*xe
* 3. generate random ill-conditioned diagonal scaling matrix D with
* condition number equal to 1.0E50:
* 4. transform A*x=b into badly scaled problem:
* A0*x0=b0
* (A0*D)*(inv(D)*x0)=b0
* finally we got new problem A*x=b with A=A0*D, b=b0, x=inv(D)*x0
*
* Then we solve A*x=b:
* 1. with default preconditioner
* 2. with explicitly activayed diagonal preconditioning
* 3. with unit preconditioner.
* 1st and 2nd solutions must be close to xe, 3rd solution must be very
* far from the true one.
*/
n = 20;
rmatrixrndcond(n, 1.0E1, &ta, _state);
ae_vector_set_length(&xe, n, _state);
for(i=0; i<=n-1; i++)
{
xe.ptr.p_double[i] = randomnormal(_state);
}
ae_vector_set_length(&b, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
b.ptr.p_double[i] = b.ptr.p_double[i]+ta.ptr.pp_double[i][j]*xe.ptr.p_double[j];
}
}
ae_vector_set_length(&d, n, _state);
for(i=0; i<=n-1; i++)
{
d.ptr.p_double[i] = ae_pow((double)(10), 100*ae_randomreal(_state)-50, _state);
}
ae_matrix_set_length(&a, n, n, _state);
sparsecreate(n, n, n*n, &sa, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = ta.ptr.pp_double[i][j]*d.ptr.p_double[j];
sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state);
}
xe.ptr.p_double[i] = xe.ptr.p_double[i]/d.ptr.p_double[i];
}
sparseconverttocrs(&sa, _state);
linlsqrcreate(n, n, &s, _state);
linlsqrsetcond(&s, (double)(0), (double)(0), 2*n, _state);
linlsqrsolvesparse(&s, &sa, &b, _state);
linlsqrresults(&s, &x0, &rep, _state);
if( rep.terminationtype<=0 )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=n-1; i++)
{
if( ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-x0.ptr.p_double[i], _state),5.0E-2/d.ptr.p_double[i]) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
linlsqrsetprecunit(&s, _state);
linlsqrsolvesparse(&s, &sa, &b, _state);
linlsqrresults(&s, &x0, &rep, _state);
if( rep.terminationtype>0 )
{
bflag = ae_false;
for(i=0; i<=n-1; i++)
{
bflag = bflag||ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-x0.ptr.p_double[i], _state),5.0E-2/d.ptr.p_double[i]);
}
if( !bflag )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
linlsqrsetprecdiag(&s, _state);
linlsqrsolvesparse(&s, &sa, &b, _state);
linlsqrresults(&s, &x0, &rep, _state);
if( rep.terminationtype<=0 )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=n-1; i++)
{
if( ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-x0.ptr.p_double[i], _state),5.0E-2/d.ptr.p_double[i]) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
/*
*test has been passed
*/
result = ae_false;
ae_frame_leave(_state);
return result;
}
static ae_int_t testminbleicunit_maxoptguardlevel = 1;
static void testminbleicunit_calciip2(minbleicstate* state,
ae_int_t n,
ae_int_t fk,
ae_state *_state);
static void testminbleicunit_testfeasibility(ae_bool* feaserr,
ae_bool* converr,
ae_bool* interr,
ae_state *_state);
static void testminbleicunit_testother(ae_bool* err, ae_state *_state);
static void testminbleicunit_testconv(ae_bool* err, ae_state *_state);
static void testminbleicunit_testpreconditioning(ae_bool* err,
ae_state *_state);
static void testminbleicunit_setrandompreconditioner(minbleicstate* state,
ae_int_t n,
ae_int_t preckind,
ae_state *_state);
static void testminbleicunit_testbugs(ae_bool* err, ae_state *_state);
static void testminbleicunit_testoptguard(ae_bool* wereerrors,
ae_state *_state);
static void testminbleicunit_testoptguardc1test0reportfortask0(ae_bool* err,
optguardnonc1test0report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state);
static void testminbleicunit_testoptguardc1test1reportfortask0(ae_bool* err,
optguardnonc1test1report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state);
ae_bool testminbleic(ae_bool silent, ae_state *_state)
{
ae_bool waserrors;
ae_bool feasibilityerrors;
ae_bool othererrors;
ae_bool precerrors;
ae_bool interrors;
ae_bool converrors;
ae_bool optguarderrors;
ae_bool bugs;
ae_bool result;
waserrors = ae_false;
feasibilityerrors = ae_false;
othererrors = ae_false;
precerrors = ae_false;
interrors = ae_false;
converrors = ae_false;
optguarderrors = ae_false;
bugs = ae_false;
testminbleicunit_testfeasibility(&feasibilityerrors, &converrors, &interrors, _state);
testminbleicunit_testother(&othererrors, _state);
testminbleicunit_testconv(&converrors, _state);
testminbleicunit_testbugs(&bugs, _state);
testminbleicunit_testpreconditioning(&precerrors, _state);
testminbleicunit_testoptguard(&optguarderrors, _state);
/*
* end
*/
waserrors = (((((feasibilityerrors||othererrors)||converrors)||interrors)||precerrors)||optguarderrors)||bugs;
if( !silent )
{
printf("TESTING BLEIC OPTIMIZATION\n");
printf("FEASIBILITY PROPERTIES: ");
if( feasibilityerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("PRECONDITIONING: ");
if( precerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("OTHER PROPERTIES: ");
if( othererrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("CONVERGENCE PROPERTIES: ");
if( converrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("INTERNAL ERRORS: ");
if( interrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("OPTGUARD: ");
if( optguarderrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("FIXED BUGS: ");
if( bugs )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
return result;
}
/*************************************************************************
Calculate test function IIP2
f(x) = sum( ((i*i+1)^FK*x[i])^2, i=0..N-1)
It has high condition number which makes fast convergence unlikely without
good preconditioner.
*************************************************************************/
static void testminbleicunit_calciip2(minbleicstate* state,
ae_int_t n,
ae_int_t fk,
ae_state *_state)
{
ae_int_t i;
if( state->needfg )
{
state->f = (double)(0);
}
for(i=0; i<=n-1; i++)
{
if( state->needfg )
{
state->f = state->f+ae_pow((double)(i*i+1), (double)(2*fk), _state)*ae_sqr(state->x.ptr.p_double[i], _state);
state->g.ptr.p_double[i] = ae_pow((double)(i*i+1), (double)(2*fk), _state)*2*state->x.ptr.p_double[i];
}
}
}
/*************************************************************************
This function test feasibility properties.
It launches a sequence of problems and examines their solutions.
Most of the attention is directed towards feasibility properties,
although we make some quick checks to ensure that actual solution is found.
On failure sets FeasErr (or ConvErr, depending on failure type) to True,
or leaves it unchanged otherwise.
IntErr is set to True on internal errors (errors in the control flow).
*************************************************************************/
static void testminbleicunit_testfeasibility(ae_bool* feaserr,
ae_bool* converr,
ae_bool* interr,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t pkind;
ae_int_t preckind;
ae_int_t passcount;
ae_int_t pass;
ae_int_t n;
ae_int_t nmax;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t p;
double v;
double v2;
double v3;
double vv;
ae_vector bl;
ae_vector bu;
ae_vector x;
ae_vector g;
ae_vector x0;
ae_vector xc;
ae_vector xs;
ae_vector svdw;
ae_matrix c;
ae_matrix svdu;
ae_matrix svdvt;
ae_vector ct;
minbleicstate state;
double epsx;
double epsfeas;
double weakepsg;
minbleicreport rep;
ae_int_t dkind;
double diffstep;
ae_frame_make(_state, &_frame_block);
memset(&bl, 0, sizeof(bl));
memset(&bu, 0, sizeof(bu));
memset(&x, 0, sizeof(x));
memset(&g, 0, sizeof(g));
memset(&x0, 0, sizeof(x0));
memset(&xc, 0, sizeof(xc));
memset(&xs, 0, sizeof(xs));
memset(&svdw, 0, sizeof(svdw));
memset(&c, 0, sizeof(c));
memset(&svdu, 0, sizeof(svdu));
memset(&svdvt, 0, sizeof(svdvt));
memset(&ct, 0, sizeof(ct));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
ae_vector_init(&bl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&g, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xs, 0, DT_REAL, _state, ae_true);
ae_vector_init(&svdw, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&svdu, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&svdvt, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
_minbleicstate_init(&state, _state, ae_true);
_minbleicreport_init(&rep, _state, ae_true);
nmax = 5;
weakepsg = 1.0E-4;
epsx = 1.0E-4;
epsfeas = 1.0E-6;
passcount = 10;
for(pass=1; pass<=passcount; pass++)
{
/*
* Test problem 1:
* * no boundary and inequality constraints
* * randomly generated plane as equality constraint
* * random point (not necessarily on the plane)
* * f = |x|^P, P = {2, 4} is used as target function
* * preconditioner is chosen at random (we just want to be
* sure that preconditioning won't prevent us from converging
* to the feasible point):
* * unit preconditioner
* * random diagonal-based preconditioner
* * random scale-based preconditioner
* * either analytic gradient or numerical differentiation are used
* * we check that after work is over we are on the plane and
* that we are in the stationary point of constrained F
*/
diffstep = 1.0E-6;
for(dkind=0; dkind<=1; dkind++)
{
for(preckind=0; preckind<=2; preckind++)
{
for(pkind=1; pkind<=2; pkind++)
{
for(n=1; n<=nmax; n++)
{
/*
* Generate X, BL, BU, CT and left part of C.
*
* Right part of C is generated using somewhat complex algo:
* * we generate random vector and multiply it by C.
* * result is used as the right part.
* * calculations are done on the fly, vector itself is not stored
* We use such algo to be sure that our system is consistent.
*/
p = 2*pkind;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&g, n, _state);
ae_matrix_set_length(&c, 1, n+1, _state);
ae_vector_set_length(&ct, 1, _state);
c.ptr.pp_double[0][n] = (double)(0);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
c.ptr.pp_double[0][i] = 2*ae_randomreal(_state)-1;
v = 2*ae_randomreal(_state)-1;
c.ptr.pp_double[0][n] = c.ptr.pp_double[0][n]+c.ptr.pp_double[0][i]*v;
}
ct.ptr.p_int[0] = 0;
/*
* Create and optimize
*/
if( dkind==0 )
{
minbleiccreate(n, &x, &state, _state);
}
if( dkind==1 )
{
minbleiccreatef(n, &x, diffstep, &state, _state);
}
minbleicsetlc(&state, &c, &ct, 1, _state);
minbleicsetcond(&state, weakepsg, 0.0, 0.0, 0, _state);
testminbleicunit_setrandompreconditioner(&state, n, preckind, _state);
while(minbleiciteration(&state, _state))
{
if( state.needf||state.needfg )
{
state.f = (double)(0);
}
for(i=0; i<=n-1; i++)
{
if( state.needf||state.needfg )
{
state.f = state.f+ae_pow(state.x.ptr.p_double[i], (double)(p), _state);
}
if( state.needfg )
{
state.g.ptr.p_double[i] = p*ae_pow(state.x.ptr.p_double[i], (double)(p-1), _state);
}
}
}
minbleicresults(&state, &x, &rep, _state);
if( rep.terminationtype<=0 )
{
*converr = ae_true;
ae_frame_leave(_state);
return;
}
/*
* Test feasibility of solution
*/
v = ae_v_dotproduct(&c.ptr.pp_double[0][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1));
*feaserr = *feaserr||ae_fp_greater(ae_fabs(v-c.ptr.pp_double[0][n], _state),epsfeas);
/*
* if C is nonzero, test that result is
* a stationary point of constrained F.
*
* NOTE: this check is done only if C is nonzero
*/
vv = ae_v_dotproduct(&c.ptr.pp_double[0][0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1));
if( ae_fp_neq(vv,(double)(0)) )
{
/*
* Calculate gradient at the result
* Project gradient into C
* Check projected norm
*/
for(i=0; i<=n-1; i++)
{
g.ptr.p_double[i] = p*ae_pow(x.ptr.p_double[i], (double)(p-1), _state);
}
v2 = ae_v_dotproduct(&c.ptr.pp_double[0][0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1));
v = ae_v_dotproduct(&c.ptr.pp_double[0][0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,n-1));
vv = v/v2;
ae_v_subd(&g.ptr.p_double[0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1), vv);
v3 = ae_v_dotproduct(&g.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,n-1));
*converr = *converr||ae_fp_greater(ae_sqrt(v3, _state),weakepsg);
}
}
}
}
}
/*
* Test problem 2 (multiple equality constraints):
* * 1<=N<=NMax, 1<=K<=N
* * no boundary constraints
* * N-dimensional space
* * randomly generated point xs
* * K randomly generated hyperplanes which all pass through xs
* define K equality constraints: (a[k],x)=b[k]
* * equality constraints are checked for being well conditioned
* * preconditioner is chosen at random (we just want to be
* sure that preconditioning won't prevent us from converging
* to the feasible point):
* * unit preconditioner
* * random diagonal-based preconditioner
* * random scale-based preconditioner
* * f(x) = |x-x0|^2, x0 = xs+a[0]
* * either analytic gradient or numerical differentiation are used
* * extremum of f(x) is exactly xs because:
* * xs is the closest point in the plane defined by (a[0],x)=b[0]
* * xs is feasible by definition
*/
diffstep = 1.0E-6;
for(dkind=0; dkind<=1; dkind++)
{
for(preckind=0; preckind<=2; preckind++)
{
for(n=2; n<=nmax; n++)
{
for(k=1; k<=n; k++)
{
/*
* Generate X, X0, XS, BL, BU, CT and left part of C.
*
* Right part of C is generated using somewhat complex algo:
* * we generate random vector and multiply it by C.
* * result is used as the right part.
* * calculations are done on the fly, vector itself is not stored
* We use such algo to be sure that our system is consistent.
*/
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xs, n, _state);
ae_vector_set_length(&g, n, _state);
ae_matrix_set_length(&c, k, n+1, _state);
ae_vector_set_length(&ct, k, _state);
c.ptr.pp_double[0][n] = (double)(0);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
xs.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
do
{
for(i=0; i<=k-1; i++)
{
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &xs.ptr.p_double[0], 1, ae_v_len(0,n-1));
c.ptr.pp_double[i][n] = v;
ct.ptr.p_int[i] = 0;
}
ae_set_error_flag(feaserr, !rmatrixsvd(&c, k, n, 0, 0, 0, &svdw, &svdu, &svdvt, _state), __FILE__, __LINE__, "testminbleicunit.ap:342");
}
while(!(ae_fp_greater(svdw.ptr.p_double[0],(double)(0))&&ae_fp_greater(svdw.ptr.p_double[k-1],0.001*svdw.ptr.p_double[0])));
ae_v_move(&x0.ptr.p_double[0], 1, &xs.ptr.p_double[0], 1, ae_v_len(0,n-1));
ae_v_add(&x0.ptr.p_double[0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1));
/*
* Create and optimize
*/
if( dkind==0 )
{
minbleiccreate(n, &x, &state, _state);
}
if( dkind==1 )
{
minbleiccreatef(n, &x, diffstep, &state, _state);
}
minbleicsetlc(&state, &c, &ct, k, _state);
minbleicsetcond(&state, weakepsg, 0.0, 0.0, 0, _state);
testminbleicunit_setrandompreconditioner(&state, n, preckind, _state);
while(minbleiciteration(&state, _state))
{
if( state.needf||state.needfg )
{
state.f = (double)(0);
}
for(i=0; i<=n-1; i++)
{
if( state.needf||state.needfg )
{
state.f = state.f+ae_sqr(state.x.ptr.p_double[i]-x0.ptr.p_double[i], _state);
}
if( state.needfg )
{
state.g.ptr.p_double[i] = 2*(state.x.ptr.p_double[i]-x0.ptr.p_double[i]);
}
}
}
minbleicresults(&state, &x, &rep, _state);
if( rep.terminationtype<=0 )
{
*converr = ae_true;
ae_frame_leave(_state);
return;
}
/*
* check feasiblity properties
*/
for(i=0; i<=k-1; i++)
{
v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1));
*feaserr = *feaserr||ae_fp_greater(ae_fabs(v-c.ptr.pp_double[i][n], _state),epsx);
}
/*
* Compare with XS
*/
v = (double)(0);
for(i=0; i<=n-1; i++)
{
v = v+ae_sqr(x.ptr.p_double[i]-xs.ptr.p_double[i], _state);
}
v = ae_sqrt(v, _state);
*converr = *converr||ae_fp_greater(ae_fabs(v, _state),0.001);
}
}
}
}
/*
* Another simple problem:
* * bound constraints 0 <= x[i] <= 1
* * no linear constraints
* * preconditioner is chosen at random (we just want to be
* sure that preconditioning won't prevent us from converging
* to the feasible point):
* * unit preconditioner
* * random diagonal-based preconditioner
* * random scale-based preconditioner
* * F(x) = |x-x0|^P, where P={2,4} and x0 is randomly selected from [-1,+2]^N
* * with such simple boundaries and function it is easy to find
* analytic form of solution: S[i] = bound(x0[i], 0, 1)
* * we also check that both final solution and subsequent iterates
* are strictly feasible
*/
diffstep = 1.0E-6;
for(dkind=0; dkind<=1; dkind++)
{
for(preckind=0; preckind<=2; preckind++)
{
for(pkind=1; pkind<=2; pkind++)
{
for(n=1; n<=nmax; n++)
{
/*
* Generate X, BL, BU.
*/
p = 2*pkind;
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
bl.ptr.p_double[i] = (double)(0);
bu.ptr.p_double[i] = (double)(1);
x.ptr.p_double[i] = ae_randomreal(_state);
x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1;
}
/*
* Create and optimize
*/
if( dkind==0 )
{
minbleiccreate(n, &x, &state, _state);
}
if( dkind==1 )
{
minbleiccreatef(n, &x, diffstep, &state, _state);
}
minbleicsetbc(&state, &bl, &bu, _state);
minbleicsetcond(&state, weakepsg, 0.0, 0.0, 0, _state);
testminbleicunit_setrandompreconditioner(&state, n, preckind, _state);
while(minbleiciteration(&state, _state))
{
if( state.needf||state.needfg )
{
state.f = (double)(0);
}
for(i=0; i<=n-1; i++)
{
if( state.needf||state.needfg )
{
state.f = state.f+ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p), _state);
}
if( state.needfg )
{
state.g.ptr.p_double[i] = p*ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state);
}
*feaserr = *feaserr||ae_fp_less(state.x.ptr.p_double[i],0.0);
*feaserr = *feaserr||ae_fp_greater(state.x.ptr.p_double[i],1.0);
}
}
minbleicresults(&state, &x, &rep, _state);
if( rep.terminationtype<=0 )
{
*converr = ae_true;
ae_frame_leave(_state);
return;
}
/*
* * compare solution with analytic one
* * check feasibility
*/
v = 0.0;
for(i=0; i<=n-1; i++)
{
if( ae_fp_greater(x.ptr.p_double[i],(double)(0))&&ae_fp_less(x.ptr.p_double[i],(double)(1)) )
{
v = v+ae_sqr(p*ae_pow(x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state), _state);
}
*feaserr = *feaserr||ae_fp_less(x.ptr.p_double[i],0.0);
*feaserr = *feaserr||ae_fp_greater(x.ptr.p_double[i],1.0);
}
*converr = *converr||ae_fp_greater(ae_sqrt(v, _state),weakepsg);
}
}
}
}
/*
* Same as previous problem, but with minor modifications:
* * some bound constraints are 0<=x[i]<=1, some are Ci=x[i]=Ci
* * no linear constraints
* * preconditioner is chosen at random (we just want to be
* sure that preconditioning won't prevent us from converging
* to the feasible point):
* * unit preconditioner
* * random diagonal-based preconditioner
* * random scale-based preconditioner
* * F(x) = |x-x0|^P, where P={2,4} and x0 is randomly selected from [-1,+2]^N
* * with such simple boundaries and function it is easy to find
* analytic form of solution: S[i] = bound(x0[i], 0, 1)
* * we also check that both final solution and subsequent iterates
* are strictly feasible
*/
diffstep = 1.0E-6;
for(dkind=0; dkind<=1; dkind++)
{
for(preckind=0; preckind<=2; preckind++)
{
for(pkind=1; pkind<=2; pkind++)
{
for(n=1; n<=nmax; n++)
{
/*
* Generate X, BL, BU.
*/
p = 2*pkind;
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
bl.ptr.p_double[i] = (double)(0);
bu.ptr.p_double[i] = (double)(1);
}
else
{
bl.ptr.p_double[i] = ae_randomreal(_state);
bu.ptr.p_double[i] = bl.ptr.p_double[i];
}
x.ptr.p_double[i] = ae_randomreal(_state);
x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1;
}
/*
* Create and optimize
*/
if( dkind==0 )
{
minbleiccreate(n, &x, &state, _state);
}
if( dkind==1 )
{
minbleiccreatef(n, &x, diffstep, &state, _state);
}
minbleicsetbc(&state, &bl, &bu, _state);
minbleicsetcond(&state, weakepsg, 0.0, 0.0, 0, _state);
testminbleicunit_setrandompreconditioner(&state, n, preckind, _state);
while(minbleiciteration(&state, _state))
{
if( state.needf||state.needfg )
{
state.f = (double)(0);
}
for(i=0; i<=n-1; i++)
{
if( state.needf||state.needfg )
{
state.f = state.f+ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p), _state);
}
if( state.needfg )
{
state.g.ptr.p_double[i] = p*ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state);
}
*feaserr = *feaserr||ae_fp_less(state.x.ptr.p_double[i],bl.ptr.p_double[i]);
*feaserr = *feaserr||ae_fp_greater(state.x.ptr.p_double[i],bu.ptr.p_double[i]);
}
}
minbleicresults(&state, &x, &rep, _state);
if( rep.terminationtype<=0 )
{
*converr = ae_true;
ae_frame_leave(_state);
return;
}
/*
* * compare solution with analytic one
* * check feasibility
*/
v = 0.0;
for(i=0; i<=n-1; i++)
{
if( ae_fp_greater(x.ptr.p_double[i],bl.ptr.p_double[i])&&ae_fp_less(x.ptr.p_double[i],bu.ptr.p_double[i]) )
{
v = v+ae_sqr(p*ae_pow(x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state), _state);
}
*feaserr = *feaserr||ae_fp_less(x.ptr.p_double[i],bl.ptr.p_double[i]);
*feaserr = *feaserr||ae_fp_greater(x.ptr.p_double[i],bu.ptr.p_double[i]);
}
*converr = *converr||ae_fp_greater(ae_sqrt(v, _state),weakepsg);
}
}
}
}
/*
* Same as previous one, but with bound constraints posed
* as general linear ones:
* * no bound constraints
* * 2*N linear constraints 0 <= x[i] <= 1
* * preconditioner is chosen at random (we just want to be
* sure that preconditioning won't prevent us from converging
* to the feasible point):
* * unit preconditioner
* * random diagonal-based preconditioner
* * random scale-based preconditioner
* * F(x) = |x-x0|^P, where P={2,4} and x0 is randomly selected from [-1,+2]^N
* * with such simple constraints and function it is easy to find
* analytic form of solution: S[i] = bound(x0[i], 0, 1).
* * however, we can't guarantee that solution is strictly feasible
* with respect to nonlinearity constraint, so we check
* for approximate feasibility.
*/
for(preckind=0; preckind<=2; preckind++)
{
for(pkind=1; pkind<=2; pkind++)
{
for(n=1; n<=nmax; n++)
{
/*
* Generate X, BL, BU.
*/
p = 2*pkind;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_matrix_set_length(&c, 2*n, n+1, _state);
ae_vector_set_length(&ct, 2*n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = ae_randomreal(_state);
x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1;
for(j=0; j<=n; j++)
{
c.ptr.pp_double[2*i+0][j] = (double)(0);
c.ptr.pp_double[2*i+1][j] = (double)(0);
}
c.ptr.pp_double[2*i+0][i] = (double)(1);
c.ptr.pp_double[2*i+0][n] = (double)(0);
ct.ptr.p_int[2*i+0] = 1;
c.ptr.pp_double[2*i+1][i] = (double)(1);
c.ptr.pp_double[2*i+1][n] = (double)(1);
ct.ptr.p_int[2*i+1] = -1;
}
/*
* Create and optimize
*/
minbleiccreate(n, &x, &state, _state);
minbleicsetlc(&state, &c, &ct, 2*n, _state);
minbleicsetcond(&state, weakepsg, 0.0, 0.0, 0, _state);
testminbleicunit_setrandompreconditioner(&state, n, preckind, _state);
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p), _state);
state.g.ptr.p_double[i] = p*ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state);
}
continue;
}
/*
* Unknown protocol specified
*/
*interr = ae_true;
ae_frame_leave(_state);
return;
}
minbleicresults(&state, &x, &rep, _state);
if( rep.terminationtype<=0 )
{
*converr = ae_true;
ae_frame_leave(_state);
return;
}
/*
* * compare solution with analytic one
* * check feasibility
*/
v = 0.0;
for(i=0; i<=n-1; i++)
{
if( ae_fp_greater(x.ptr.p_double[i],0.02)&&ae_fp_less(x.ptr.p_double[i],0.98) )
{
v = v+ae_sqr(p*ae_pow(x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state), _state);
}
*feaserr = *feaserr||ae_fp_less(x.ptr.p_double[i],0.0-epsfeas);
*feaserr = *feaserr||ae_fp_greater(x.ptr.p_double[i],1.0+epsfeas);
}
*converr = *converr||ae_fp_greater(ae_sqrt(v, _state),weakepsg);
}
}
}
/*
* Feasibility problem:
* * bound constraints 0<=x[i]<=1
* * starting point xs with xs[i] in [-1,+2]
* * random point xc from [0,1] is used to generate K<=N
* random linear equality/inequality constraints of the form
* (c,x-xc)=0.0 (or, alternatively, >= or <=), where
* c is a random vector.
* * preconditioner is chosen at random (we just want to be
* sure that preconditioning won't prevent us from converging
* to the feasible point):
* * unit preconditioner
* * random diagonal-based preconditioner
* * random scale-based preconditioner
* * F(x) = |x-x0|^P, where P={2,4} and x0 is randomly selected from [-1,+2]^N
* * we do not know analytic form of the solution, and, if fact, we do not
* check for solution correctness. We just check that algorithm converges
* to the feasible points.
*/
for(preckind=0; preckind<=2; preckind++)
{
for(pkind=1; pkind<=2; pkind++)
{
for(n=1; n<=nmax; n++)
{
for(k=1; k<=n; k++)
{
/*
* Generate X, BL, BU.
*/
p = 2*pkind;
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xc, n, _state);
ae_vector_set_length(&xs, n, _state);
ae_matrix_set_length(&c, k, n+1, _state);
ae_vector_set_length(&ct, k, _state);
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1;
xs.ptr.p_double[i] = 3*ae_randomreal(_state)-1;
xc.ptr.p_double[i] = 0.1+0.8*ae_randomreal(_state);
bl.ptr.p_double[i] = (double)(0);
bu.ptr.p_double[i] = (double)(1);
}
for(i=0; i<=k-1; i++)
{
c.ptr.pp_double[i][n] = (double)(0);
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
c.ptr.pp_double[i][n] = c.ptr.pp_double[i][n]+c.ptr.pp_double[i][j]*xc.ptr.p_double[j];
}
ct.ptr.p_int[i] = ae_randominteger(3, _state)-1;
}
/*
* Create and optimize
*/
minbleiccreate(n, &xs, &state, _state);
minbleicsetbc(&state, &bl, &bu, _state);
minbleicsetlc(&state, &c, &ct, k, _state);
minbleicsetcond(&state, weakepsg, 0.0, 0.0, 0, _state);
testminbleicunit_setrandompreconditioner(&state, n, preckind, _state);
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p), _state);
state.g.ptr.p_double[i] = p*ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state);
}
continue;
}
/*
* Unknown protocol specified
*/
*interr = ae_true;
ae_frame_leave(_state);
return;
}
minbleicresults(&state, &x, &rep, _state);
if( rep.terminationtype<=0 )
{
*converr = ae_true;
ae_frame_leave(_state);
return;
}
/*
* Check feasibility
*/
for(i=0; i<=n-1; i++)
{
*feaserr = *feaserr||ae_fp_less(x.ptr.p_double[i],0.0);
*feaserr = *feaserr||ae_fp_greater(x.ptr.p_double[i],1.0);
}
for(i=0; i<=k-1; i++)
{
v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = v-c.ptr.pp_double[i][n];
if( ct.ptr.p_int[i]==0 )
{
*feaserr = *feaserr||ae_fp_greater(ae_fabs(v, _state),epsfeas);
}
if( ct.ptr.p_int[i]<0 )
{
*feaserr = *feaserr||ae_fp_greater(v,epsfeas);
}
if( ct.ptr.p_int[i]>0 )
{
*feaserr = *feaserr||ae_fp_less(v,-epsfeas);
}
}
}
}
}
}
/*
* Infeasible problem:
* * all bound constraints are 0 <= x[i] <= 1 except for one
* * that one is 0 >= x[i] >= 1
* * no linear constraints
* * preconditioner is chosen at random (we just want to be
* sure that preconditioning won't prevent us from detecting
* infeasible point):
* * unit preconditioner
* * random diagonal-based preconditioner
* * random scale-based preconditioner
* * F(x) = |x-x0|^P, where P={2,4} and x0 is randomly selected from [-1,+2]^N
* * algorithm must return correct error code on such problem
*/
for(preckind=0; preckind<=2; preckind++)
{
for(pkind=1; pkind<=2; pkind++)
{
for(n=1; n<=nmax; n++)
{
/*
* Generate X, BL, BU.
*/
p = 2*pkind;
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
bl.ptr.p_double[i] = (double)(0);
bu.ptr.p_double[i] = (double)(1);
x.ptr.p_double[i] = ae_randomreal(_state);
x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1;
}
i = ae_randominteger(n, _state);
bl.ptr.p_double[i] = (double)(1);
bu.ptr.p_double[i] = (double)(0);
/*
* Create and optimize
*/
minbleiccreate(n, &x, &state, _state);
minbleicsetbc(&state, &bl, &bu, _state);
minbleicsetcond(&state, weakepsg, 0.0, 0.0, 0, _state);
testminbleicunit_setrandompreconditioner(&state, n, preckind, _state);
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p), _state);
state.g.ptr.p_double[i] = p*ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state);
}
continue;
}
/*
* Unknown protocol specified
*/
*interr = ae_true;
ae_frame_leave(_state);
return;
}
minbleicresults(&state, &x, &rep, _state);
*feaserr = *feaserr||rep.terminationtype!=-3;
}
}
}
/*
* Infeasible problem (2):
* * no bound and inequality constraints
* * 1<=K<=N arbitrary equality constraints
* * (K+1)th constraint which is equal to the first constraint a*x=c,
* but with c:=c+1. I.e. we have both a*x=c and a*x=c+1, which can't
* be true (other constraints may be inconsistent too, but we don't
* have to check it).
* * preconditioner is chosen at random (we just want to be
* sure that preconditioning won't prevent us from detecting
* infeasible point):
* * unit preconditioner
* * random diagonal-based preconditioner
* * random scale-based preconditioner
* * F(x) = |x|^P, where P={2,4}
* * algorithm must return correct error code on such problem
*/
for(preckind=0; preckind<=2; preckind++)
{
for(pkind=1; pkind<=2; pkind++)
{
for(n=1; n<=nmax; n++)
{
for(k=1; k<=n; k++)
{
/*
* Generate X, BL, BU.
*/
p = 2*pkind;
ae_vector_set_length(&x, n, _state);
ae_matrix_set_length(&c, k+1, n+1, _state);
ae_vector_set_length(&ct, k+1, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = ae_randomreal(_state);
}
for(i=0; i<=k-1; i++)
{
for(j=0; j<=n; j++)
{
c.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
ct.ptr.p_int[i] = 0;
}
ct.ptr.p_int[k] = 0;
ae_v_move(&c.ptr.pp_double[k][0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1));
c.ptr.pp_double[k][n] = c.ptr.pp_double[0][n]+1;
/*
* Create and optimize
*/
minbleiccreate(n, &x, &state, _state);
minbleicsetlc(&state, &c, &ct, k+1, _state);
minbleicsetcond(&state, weakepsg, 0.0, 0.0, 0, _state);
testminbleicunit_setrandompreconditioner(&state, n, preckind, _state);
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+ae_pow(state.x.ptr.p_double[i], (double)(p), _state);
state.g.ptr.p_double[i] = p*ae_pow(state.x.ptr.p_double[i], (double)(p-1), _state);
}
continue;
}
/*
* Unknown protocol specified
*/
*interr = ae_true;
ae_frame_leave(_state);
return;
}
minbleicresults(&state, &x, &rep, _state);
*feaserr = *feaserr||rep.terminationtype!=-3;
}
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
This function additional properties.
On failure sets Err to True (leaves it unchanged otherwise)
*************************************************************************/
static void testminbleicunit_testother(ae_bool* err, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t passcount;
ae_int_t pass;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_vector bl;
ae_vector bu;
ae_vector x;
ae_vector xf;
ae_vector x0;
ae_vector x1;
ae_vector b;
ae_vector xlast;
ae_vector a;
ae_vector s;
ae_vector h;
ae_matrix c;
ae_matrix fulla;
ae_vector ct;
double fprev;
double xprev;
double stpmax;
double v;
ae_int_t nec;
ae_int_t nic;
ae_int_t pkind;
ae_int_t ckind;
ae_int_t mkind;
double vc;
double vm;
minbleicstate state;
double epsx;
double epsg;
double eps;
double tmpeps;
minbleicreport rep;
double diffstep;
ae_int_t dkind;
ae_bool wasf;
ae_bool wasfg;
double r;
hqrndstate rs;
ae_int_t spoiliteration;
ae_int_t stopiteration;
ae_int_t spoilvar;
double spoilval;
double ss;
ae_int_t stopcallidx;
ae_int_t callidx;
ae_int_t maxits;
ae_bool terminationrequested;
ae_int_t scaletype;
ae_frame_make(_state, &_frame_block);
memset(&bl, 0, sizeof(bl));
memset(&bu, 0, sizeof(bu));
memset(&x, 0, sizeof(x));
memset(&xf, 0, sizeof(xf));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&b, 0, sizeof(b));
memset(&xlast, 0, sizeof(xlast));
memset(&a, 0, sizeof(a));
memset(&s, 0, sizeof(s));
memset(&h, 0, sizeof(h));
memset(&c, 0, sizeof(c));
memset(&fulla, 0, sizeof(fulla));
memset(&ct, 0, sizeof(ct));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&rs, 0, sizeof(rs));
ae_vector_init(&bl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xf, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xlast, 0, DT_REAL, _state, ae_true);
ae_vector_init(&a, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&h, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&fulla, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
_minbleicstate_init(&state, _state, ae_true);
_minbleicreport_init(&rep, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
epsx = 1.0E-4;
epsg = 1.0E-8;
passcount = 10;
/*
* Try to reproduce bug 570 (optimizer hangs on problems where it is required
* to perform very small step - less than 1E-50 - in order to activate constraints).
*
* The problem being solved is:
*
* min x[0]+x[1]+...+x[n-1]
*
* subject to
*
* x[i]>=0, for i=0..n-1
*
* with initial point
*
* x[0] = 1.0E-100, x[1]=x[2]=...=0.5
*
* We try to reproduce this problem in different settings:
* * boundary-only constraints - we test that completion code is positive,
* and all x[] are EXACTLY zero
* * boundary constraints posed as general linear ones - we test that
* completion code is positive, and all x[] are APPROXIMATELY zero.
*/
n = 10;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
ae_matrix_set_length(&c, n, n+1, _state);
ae_vector_set_length(&ct, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 0.5;
bl.ptr.p_double[i] = 0.0;
bu.ptr.p_double[i] = _state->v_posinf;
ct.ptr.p_int[i] = 1;
for(j=0; j<=n; j++)
{
c.ptr.pp_double[i][j] = 0.0;
}
c.ptr.pp_double[i][i] = 1.0;
}
x.ptr.p_double[0] = 1.0E-100;
minbleiccreate(n, &x, &state, _state);
minbleicsetbc(&state, &bl, &bu, _state);
minbleicsetcond(&state, (double)(0), (double)(0), (double)(0), 2*n, _state);
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+state.x.ptr.p_double[i];
state.g.ptr.p_double[i] = 1.0;
}
}
}
minbleicresults(&state, &xf, &rep, _state);
ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminbleicunit.ap:1030");
if( rep.terminationtype>0 )
{
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(err, ae_fp_neq(xf.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testminbleicunit.ap:1033");
}
}
minbleiccreate(n, &x, &state, _state);
minbleicsetlc(&state, &c, &ct, n, _state);
minbleicsetcond(&state, 1.0E-64, (double)(0), (double)(0), 10, _state);
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+state.x.ptr.p_double[i];
state.g.ptr.p_double[i] = 1.0;
}
}
}
minbleicresults(&state, &xf, &rep, _state);
ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminbleicunit.ap:1051");
if( rep.terminationtype>0 )
{
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(xf.ptr.p_double[i], _state),1.0E-10), __FILE__, __LINE__, "testminbleicunit.ap:1054");
}
}
/*
* Test reports:
* * first value must be starting point
* * last value must be last point
*/
for(pass=1; pass<=passcount; pass++)
{
n = 50;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&xlast, n, _state);
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = (double)(10);
bl.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
bu.ptr.p_double[i] = _state->v_posinf;
}
minbleiccreate(n, &x, &state, _state);
minbleicsetbc(&state, &bl, &bu, _state);
minbleicsetcond(&state, 1.0E-64, (double)(0), (double)(0), 10, _state);
minbleicsetxrep(&state, ae_true, _state);
fprev = ae_maxrealnumber;
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+ae_sqr((1+i)*state.x.ptr.p_double[i], _state);
state.g.ptr.p_double[i] = 2*(1+i)*state.x.ptr.p_double[i];
}
}
if( state.xupdated )
{
if( ae_fp_eq(fprev,ae_maxrealnumber) )
{
for(i=0; i<=n-1; i++)
{
*err = *err||ae_fp_neq(state.x.ptr.p_double[i],x.ptr.p_double[i]);
}
}
fprev = state.f;
ae_v_move(&xlast.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
}
}
minbleicresults(&state, &x, &rep, _state);
for(i=0; i<=n-1; i++)
{
*err = *err||ae_fp_neq(x.ptr.p_double[i],xlast.ptr.p_double[i]);
}
}
/*
* Test differentiation vs. analytic gradient
* (first one issues NeedF requests, second one issues NeedFG requests)
*/
for(pass=1; pass<=passcount; pass++)
{
n = 10;
diffstep = 1.0E-6;
for(dkind=0; dkind<=1; dkind++)
{
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&xlast, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = (double)(1);
}
if( dkind==0 )
{
minbleiccreate(n, &x, &state, _state);
}
if( dkind==1 )
{
minbleiccreatef(n, &x, diffstep, &state, _state);
}
minbleicsetcond(&state, 1.0E-6, (double)(0), epsx, 0, _state);
wasf = ae_false;
wasfg = ae_false;
while(minbleiciteration(&state, _state))
{
if( state.needf||state.needfg )
{
state.f = (double)(0);
}
for(i=0; i<=n-1; i++)
{
if( state.needf||state.needfg )
{
state.f = state.f+ae_sqr((1+i)*state.x.ptr.p_double[i], _state);
}
if( state.needfg )
{
state.g.ptr.p_double[i] = 2*(1+i)*state.x.ptr.p_double[i];
}
}
wasf = wasf||state.needf;
wasfg = wasfg||state.needfg;
}
minbleicresults(&state, &x, &rep, _state);
if( dkind==0 )
{
*err = (*err||wasf)||!wasfg;
}
if( dkind==1 )
{
*err = (*err||!wasf)||wasfg;
}
}
}
/*
* Test that numerical differentiation uses scaling.
*
* In order to test that we solve simple optimization
* problem: min(x^2) with initial x equal to 0.0.
*
* We choose random DiffStep and S, then we check that
* optimizer evaluates function at +-DiffStep*S only.
*/
for(pass=1; pass<=passcount; pass++)
{
ae_vector_set_length(&x, 1, _state);
ae_vector_set_length(&s, 1, _state);
diffstep = ae_randomreal(_state)*1.0E-6;
s.ptr.p_double[0] = ae_exp(ae_randomreal(_state)*4-2, _state);
x.ptr.p_double[0] = (double)(0);
minbleiccreatef(1, &x, diffstep, &state, _state);
minbleicsetcond(&state, 1.0E-6, (double)(0), epsx, 0, _state);
minbleicsetscale(&state, &s, _state);
v = (double)(0);
while(minbleiciteration(&state, _state))
{
state.f = ae_sqr(state.x.ptr.p_double[0], _state);
v = ae_maxreal(v, ae_fabs(state.x.ptr.p_double[0], _state), _state);
}
minbleicresults(&state, &x, &rep, _state);
r = v/(s.ptr.p_double[0]*diffstep);
*err = *err||ae_fp_greater(ae_fabs(ae_log(r, _state), _state),ae_log(1+1000*ae_machineepsilon, _state));
}
/*
* Test stpmax
*/
for(pass=1; pass<=passcount; pass++)
{
n = 1;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
x.ptr.p_double[0] = (double)(100);
bl.ptr.p_double[0] = 2*ae_randomreal(_state)-1;
bu.ptr.p_double[0] = _state->v_posinf;
stpmax = 0.05+0.05*ae_randomreal(_state);
minbleiccreate(n, &x, &state, _state);
minbleicsetbc(&state, &bl, &bu, _state);
minbleicsetcond(&state, epsg, (double)(0), epsx, 0, _state);
minbleicsetxrep(&state, ae_true, _state);
minbleicsetstpmax(&state, stpmax, _state);
xprev = x.ptr.p_double[0];
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
state.f = ae_exp(state.x.ptr.p_double[0], _state)+ae_exp(-state.x.ptr.p_double[0], _state);
state.g.ptr.p_double[0] = ae_exp(state.x.ptr.p_double[0], _state)-ae_exp(-state.x.ptr.p_double[0], _state);
*err = *err||ae_fp_greater(ae_fabs(state.x.ptr.p_double[0]-xprev, _state),(1+ae_sqrt(ae_machineepsilon, _state))*stpmax);
}
if( state.xupdated )
{
*err = *err||ae_fp_greater(ae_fabs(state.x.ptr.p_double[0]-xprev, _state),(1+ae_sqrt(ae_machineepsilon, _state))*stpmax);
xprev = state.x.ptr.p_double[0];
}
}
}
/*
* Ability to solve problems with function which is unbounded from below
*/
for(pass=1; pass<=passcount; pass++)
{
n = 1;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
bl.ptr.p_double[0] = 4*ae_randomreal(_state)+1;
bu.ptr.p_double[0] = bl.ptr.p_double[0]+1;
x.ptr.p_double[0] = 0.5*(bl.ptr.p_double[0]+bu.ptr.p_double[0]);
minbleiccreate(n, &x, &state, _state);
minbleicsetbc(&state, &bl, &bu, _state);
minbleicsetcond(&state, epsg, (double)(0), epsx, 0, _state);
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
state.f = -1.0E8*ae_sqr(state.x.ptr.p_double[0], _state);
state.g.ptr.p_double[0] = -2.0E8*state.x.ptr.p_double[0];
}
}
minbleicresults(&state, &x, &rep, _state);
*err = *err||ae_fp_greater(ae_fabs(x.ptr.p_double[0]-bu.ptr.p_double[0], _state),epsx);
}
/*
* Test correctness of the scaling:
* * initial point is random point from [+1,+2]^N
* * f(x) = SUM(A[i]*x[i]^4), C[i] is random from [0.01,100]
* * function is EFFECTIVELY unconstrained; it has formal constraints,
* but they are inactive at the solution; we try different variants
* in order to explore different control paths of the optimizer:
* 0) absense of constraints
* 1) bound constraints -100000<=x[i]<=100000
* 2) one linear constraint 0*x=0
* 3) combination of (1) and (2)
* * we use random scaling matrix
* * we test different variants of the preconditioning:
* 0) unit preconditioner
* 1) random diagonal from [0.01,100]
* 2) scale preconditioner
* * we set very stringent stopping conditions
* * and we test that in the extremum stopping conditions are
* satisfied subject to the current scaling coefficients.
*/
for(pass=1; pass<=passcount; pass++)
{
tmpeps = 1.0E-5;
for(n=1; n<=10; n++)
{
for(ckind=0; ckind<=3; ckind++)
{
for(pkind=0; pkind<=2; pkind++)
{
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&a, n, _state);
ae_vector_set_length(&s, n, _state);
ae_vector_set_length(&h, n, _state);
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
ae_matrix_set_length(&c, 1, n+1, _state);
ae_vector_set_length(&ct, 1, _state);
ct.ptr.p_int[0] = 0;
c.ptr.pp_double[0][n] = (double)(0);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = ae_randomreal(_state)+1;
bl.ptr.p_double[i] = (double)(-100000);
bu.ptr.p_double[i] = (double)(100000);
c.ptr.pp_double[0][i] = (double)(0);
a.ptr.p_double[i] = ae_exp(ae_log((double)(10), _state)*(2*ae_randomreal(_state)-1), _state);
s.ptr.p_double[i] = ae_exp(ae_log((double)(10), _state)*(2*ae_randomreal(_state)-1), _state);
h.ptr.p_double[i] = ae_exp(ae_log((double)(10), _state)*(2*ae_randomreal(_state)-1), _state);
}
minbleiccreate(n, &x, &state, _state);
if( ckind==1||ckind==3 )
{
minbleicsetbc(&state, &bl, &bu, _state);
}
if( ckind==2||ckind==3 )
{
minbleicsetlc(&state, &c, &ct, 1, _state);
}
if( pkind==1 )
{
minbleicsetprecdiag(&state, &h, _state);
}
if( pkind==2 )
{
minbleicsetprecscale(&state, _state);
}
minbleicsetcond(&state, tmpeps, (double)(0), (double)(0), 0, _state);
minbleicsetscale(&state, &s, _state);
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+a.ptr.p_double[i]*ae_sqr(state.x.ptr.p_double[i], _state);
state.g.ptr.p_double[i] = 2*a.ptr.p_double[i]*state.x.ptr.p_double[i];
}
}
}
minbleicresults(&state, &x, &rep, _state);
if( rep.terminationtype<=0 )
{
*err = ae_true;
ae_frame_leave(_state);
return;
}
v = (double)(0);
for(i=0; i<=n-1; i++)
{
v = v+ae_sqr(s.ptr.p_double[i]*2*a.ptr.p_double[i]*x.ptr.p_double[i], _state);
}
v = ae_sqrt(v, _state);
ae_set_error_flag(err, ae_fp_greater(v,tmpeps), __FILE__, __LINE__, "testminbleicunit.ap:1320");
}
}
}
}
/*
* Check correctness of the "trimming".
*
* Trimming is a technique which is used to help algorithm
* cope with unbounded functions. In order to check this
* technique we will try to solve following optimization
* problem:
*
* min f(x) subject to no constraints on X
* { 1/(1-x) + 1/(1+x) + c*x, if -0.999999=0.999999
*
* where c is either 1.0 or 1.0E+4, M is either 1.0E8, 1.0E20 or +INF
* (we try different combinations)
*/
for(pass=1; pass<=passcount; pass++)
{
for(ckind=0; ckind<=1; ckind++)
{
for(mkind=0; mkind<=2; mkind++)
{
/*
* Choose c and M
*/
vc = (double)(1);
vm = (double)(1);
if( ckind==0 )
{
vc = 1.0;
}
if( ckind==1 )
{
vc = 1.0E+4;
}
if( mkind==0 )
{
vm = 1.0E+8;
}
if( mkind==1 )
{
vm = 1.0E+20;
}
if( mkind==2 )
{
vm = _state->v_posinf;
}
/*
* Create optimizer, solve optimization problem
*/
epsg = 1.0E-6*vc;
ae_vector_set_length(&x, 1, _state);
x.ptr.p_double[0] = 0.0;
minbleiccreate(1, &x, &state, _state);
minbleicsetcond(&state, epsg, (double)(0), (double)(0), 0, _state);
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
if( ae_fp_less(-0.999999,state.x.ptr.p_double[0])&&ae_fp_less(state.x.ptr.p_double[0],0.999999) )
{
state.f = 1/(1-state.x.ptr.p_double[0])+1/(1+state.x.ptr.p_double[0])+vc*state.x.ptr.p_double[0];
state.g.ptr.p_double[0] = 1/ae_sqr(1-state.x.ptr.p_double[0], _state)-1/ae_sqr(1+state.x.ptr.p_double[0], _state)+vc;
}
else
{
state.f = vm;
state.g.ptr.p_double[0] = (double)(0);
}
}
}
minbleicresults(&state, &x, &rep, _state);
if( rep.terminationtype<=0 )
{
*err = ae_true;
ae_frame_leave(_state);
return;
}
*err = *err||ae_fp_greater(ae_fabs(1/ae_sqr(1-x.ptr.p_double[0], _state)-1/ae_sqr(1+x.ptr.p_double[0], _state)+vc, _state),epsg);
}
}
}
/*
* Test behaviour on noisy functions.
*
* Consider following problem:
* * f(x,y) = (x+1)^2 + (y+1)^2 + 10000*MachineEpsilon*RandomReal()
* * boundary constraints x>=0, y>=0
* * starting point (x0,y0)=(10*MachineEpsilon,1.0)
*
* Such problem contains small numerical noise. Without noise its
* solution is (xs,ys)=(0,0), which is easy to find. However, presence
* of the noise makes it hard to solve:
* * noisy f(x,y) is monotonically decreasing only when we perform
* steps orders of magnitude larger than 10000*MachineEpsilon
* * at small scales f(x,y) is non-monotonic and non-convex
* * however, our first step must be done towards
* (x1,y1) = (0,1-some_small_value), and length of such step is
* many times SMALLER than 10000*MachineEpsilon
* * second step, from (x1,y1) to (xs,ys), will be large enough to
* ignore numerical noise, so the only problem is to perform
* first step
*
* Naive implementation of BLEIC should fail sometimes (sometimes -
* due to non-deterministic nature of noise) on such problem. However,
* our improved implementation should solve it correctly. We test
* several variations of inner stopping criteria.
*/
for(pass=1; pass<=passcount; pass++)
{
eps = 1.0E-9;
ae_vector_set_length(&x, 2, _state);
ae_vector_set_length(&bl, 2, _state);
ae_vector_set_length(&bu, 2, _state);
x.ptr.p_double[0] = 10*ae_machineepsilon;
x.ptr.p_double[1] = 1.0;
bl.ptr.p_double[0] = 0.0;
bu.ptr.p_double[0] = _state->v_posinf;
bl.ptr.p_double[1] = 0.0;
bu.ptr.p_double[1] = _state->v_posinf;
for(ckind=0; ckind<=2; ckind++)
{
minbleiccreate(2, &x, &state, _state);
minbleicsetbc(&state, &bl, &bu, _state);
if( ckind==0 )
{
minbleicsetcond(&state, eps, (double)(0), (double)(0), 0, _state);
}
if( ckind==1 )
{
minbleicsetcond(&state, (double)(0), eps, (double)(0), 0, _state);
}
if( ckind==2 )
{
minbleicsetcond(&state, (double)(0), (double)(0), eps, 0, _state);
}
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
state.f = ae_sqr(state.x.ptr.p_double[0]+1, _state)+ae_sqr(state.x.ptr.p_double[1]+1, _state)+10000*ae_machineepsilon*ae_randomreal(_state);
state.g.ptr.p_double[0] = 2*(state.x.ptr.p_double[0]+1);
state.g.ptr.p_double[1] = 2*(state.x.ptr.p_double[1]+1);
}
}
minbleicresults(&state, &xf, &rep, _state);
if( (rep.terminationtype<=0||ae_fp_neq(xf.ptr.p_double[0],(double)(0)))||ae_fp_neq(xf.ptr.p_double[1],(double)(0)) )
{
*err = ae_true;
ae_frame_leave(_state);
return;
}
}
}
/*
* Deterministic variation of the previous problem.
*
* Consider following problem:
* * boundary constraints x>=0, y>=0
* * starting point (x0,y0)=(10*MachineEpsilon,1.0)
* / (x+1)^2 + (y+1)^2, for (x,y)<>(x0,y0)
* * f(x,y) = |
* \ (x+1)^2 + (y+1)^2 - 0.1, for (x,y)=(x0,y0)
*
* Such problem contains deterministic numerical noise (-0.1 at
* starting point). Without noise its solution is easy to find.
* However, presence of the noise makes it hard to solve:
* * our first step must be done towards (x1,y1) = (0,1-some_small_value),
* but such step will increase function valye by approximately 0.1 -
* instead of decreasing it.
*
* Naive implementation of BLEIC should fail on such problem. However,
* our improved implementation should solve it correctly. We test
* several variations of inner stopping criteria.
*/
for(pass=1; pass<=passcount; pass++)
{
eps = 1.0E-9;
ae_vector_set_length(&x, 2, _state);
ae_vector_set_length(&bl, 2, _state);
ae_vector_set_length(&bu, 2, _state);
x.ptr.p_double[0] = 10*ae_machineepsilon;
x.ptr.p_double[1] = 1.0;
bl.ptr.p_double[0] = 0.0;
bu.ptr.p_double[0] = _state->v_posinf;
bl.ptr.p_double[1] = 0.0;
bu.ptr.p_double[1] = _state->v_posinf;
for(ckind=0; ckind<=2; ckind++)
{
minbleiccreate(2, &x, &state, _state);
minbleicsetbc(&state, &bl, &bu, _state);
if( ckind==0 )
{
minbleicsetcond(&state, eps, (double)(0), (double)(0), 0, _state);
}
if( ckind==1 )
{
minbleicsetcond(&state, (double)(0), eps, (double)(0), 0, _state);
}
if( ckind==2 )
{
minbleicsetcond(&state, (double)(0), (double)(0), eps, 0, _state);
}
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
state.f = ae_sqr(state.x.ptr.p_double[0]+1, _state)+ae_sqr(state.x.ptr.p_double[1]+1, _state);
if( ae_fp_eq(state.x.ptr.p_double[0],x.ptr.p_double[0])&&ae_fp_eq(state.x.ptr.p_double[1],x.ptr.p_double[1]) )
{
state.f = state.f-0.1;
}
state.g.ptr.p_double[0] = 2*(state.x.ptr.p_double[0]+1);
state.g.ptr.p_double[1] = 2*(state.x.ptr.p_double[1]+1);
}
}
minbleicresults(&state, &xf, &rep, _state);
if( (rep.terminationtype<=0||ae_fp_neq(xf.ptr.p_double[0],(double)(0)))||ae_fp_neq(xf.ptr.p_double[1],(double)(0)) )
{
*err = ae_true;
ae_frame_leave(_state);
return;
}
}
}
/*
* Test integrity checks for NAN/INF:
* * algorithm solves optimization problem, which is normal for some time (quadratic)
* * after 5-th step we choose random component of gradient and consistently spoil
* it by NAN or INF.
* * we check that correct termination code is returned (-8)
*/
n = 100;
for(pass=1; pass<=10; pass++)
{
spoiliteration = 5;
stopiteration = 8;
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
/*
* Gradient can be spoiled by +INF, -INF, NAN
*/
spoilvar = hqrnduniformi(&rs, n, _state);
i = hqrnduniformi(&rs, 3, _state);
spoilval = _state->v_nan;
if( i==0 )
{
spoilval = _state->v_neginf;
}
if( i==1 )
{
spoilval = _state->v_posinf;
}
}
else
{
/*
* Function value can be spoiled only by NAN
* (+INF can be recognized as legitimate value during optimization)
*/
spoilvar = -1;
spoilval = _state->v_nan;
}
spdmatrixrndcond(n, 1.0E5, &fulla, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
minbleiccreate(n, &x0, &state, _state);
minbleicsetcond(&state, 0.0, 0.0, 0.0, stopiteration, _state);
minbleicsetxrep(&state, ae_true, _state);
k = -1;
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.g.ptr.p_double[i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.f = state.f+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.g.ptr.p_double[i] = state.g.ptr.p_double[i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
if( k>=spoiliteration )
{
if( spoilvar<0 )
{
state.f = spoilval;
}
else
{
state.g.ptr.p_double[spoilvar] = spoilval;
}
}
continue;
}
if( state.xupdated )
{
inc(&k, _state);
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minbleicresults(&state, &x1, &rep, _state);
ae_set_error_flag(err, rep.terminationtype!=-8, __FILE__, __LINE__, "testminbleicunit.ap:1603");
}
/*
* Check algorithm ability to handle request for termination:
* * to terminate with correct return code = 8
* * to return point which was "current" at the moment of termination
*
* NOTE: we solve problem with "corrupted" preconditioner which makes it hard
* to converge in less than StopCallIdx iterations
*/
for(pass=1; pass<=50; pass++)
{
n = 3;
ss = (double)(100);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&xlast, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 6+ae_randomreal(_state);
}
ae_vector_set_length(&s, 3, _state);
s.ptr.p_double[0] = 0.00001;
s.ptr.p_double[1] = 0.00001;
s.ptr.p_double[2] = 10000.0;
stopcallidx = ae_randominteger(20, _state);
maxits = 25;
minbleiccreate(n, &x, &state, _state);
minbleicsetcond(&state, (double)(0), (double)(0), (double)(0), maxits, _state);
minbleicsetxrep(&state, ae_true, _state);
minbleicsetprecdiag(&state, &s, _state);
callidx = 0;
terminationrequested = ae_false;
ae_v_move(&xlast.ptr.p_double[0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1));
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
state.f = ss*ae_sqr(ae_exp(state.x.ptr.p_double[0], _state)-2, _state)+ae_sqr(state.x.ptr.p_double[1], _state)+ae_sqr(state.x.ptr.p_double[2]-state.x.ptr.p_double[0], _state);
state.g.ptr.p_double[0] = 2*ss*(ae_exp(state.x.ptr.p_double[0], _state)-2)*ae_exp(state.x.ptr.p_double[0], _state)+2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0])*(-1);
state.g.ptr.p_double[1] = 2*state.x.ptr.p_double[1];
state.g.ptr.p_double[2] = 2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0]);
if( callidx==stopcallidx )
{
minbleicrequesttermination(&state, _state);
terminationrequested = ae_true;
}
inc(&callidx, _state);
continue;
}
if( state.xupdated )
{
if( !terminationrequested )
{
ae_v_move(&xlast.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minbleicresults(&state, &x, &rep, _state);
ae_set_error_flag(err, rep.terminationtype!=8, __FILE__, __LINE__, "testminbleicunit.ap:1661");
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(err, ae_fp_neq(x.ptr.p_double[i],xlast.ptr.p_double[i]), __FILE__, __LINE__, "testminbleicunit.ap:1663");
}
}
/*
* N-dimensional problem with Ne equality and Ni inequality constraints.
*
* Check that internal SActiveSet object uses efficient algorithm
* to determine initial point: it avoids expensive (N+Ni)-dimensional
* QP subproblem when initial point is feasible w.r.t. constraints.
*
* In order to do so we try to solve 5-dimensional QP problem with
* 2 equality constraints and 1000000 inequality constraints (+box
* constraints). Inefficient algorithm will simply fail to allocate
* enough memory, so we do not have to perform any checks here.
*/
n = 5;
nec = 2;
nic = 1000000;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
for(scaletype=0; scaletype<=1; scaletype++)
{
/*
* Generate problem
*/
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = hqrnduniformr(&rs, _state);
bl.ptr.p_double[i] = x.ptr.p_double[i]-hqrnduniformr(&rs, _state)*hqrnduniformi(&rs, 2, _state);
bu.ptr.p_double[i] = x.ptr.p_double[i]+hqrnduniformr(&rs, _state)*hqrnduniformi(&rs, 2, _state);
}
ae_matrix_set_length(&c, nec+nic, n+1, _state);
ae_vector_set_length(&ct, nec+nic, _state);
for(i=0; i<=nec+nic-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
v = v+c.ptr.pp_double[i][j]*x.ptr.p_double[j];
}
c.ptr.pp_double[i][n] = v;
if( i=c'*x0, with c=A*x0
* * run BLEIC algorithm from initial point x0 for target function f=0.5*x'*A*x
* and check that it stops at x0 (less than 1E-12 away from it)
*/
n = 20;
for(pass=0; pass<=20000; pass++)
{
spdmatrixrndcond(n, 1.0E3, &fulla, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
fulla.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j]*1.0E9;
}
}
ae_vector_set_length(&x0, n, _state);
v = (double)(0);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrnduniformr(&rs, _state);
v = v+ae_sqr(x0.ptr.p_double[i], _state);
}
ae_assert(ae_fp_greater(v,(double)(0)), "MinBLEIC: integrity check failed in the unit test", _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = x0.ptr.p_double[i]/ae_sqrt(v, _state);
}
ae_matrix_set_length(&c, 1, n+1, _state);
ae_vector_set_length(&ct, 1, _state);
ct.ptr.p_int[0] = 1;
c.ptr.pp_double[0][n] = (double)(0);
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&fulla.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1));
c.ptr.pp_double[0][i] = v;
c.ptr.pp_double[0][n] = c.ptr.pp_double[0][n]+v*x0.ptr.p_double[i];
}
ae_assert(ae_fp_greater(c.ptr.pp_double[0][n],(double)(0)), "MinBLEIC: integrity check failed in the unit test", _state);
minbleiccreate(n, &x0, &state, _state);
minbleicsetlc(&state, &c, &ct, 1, _state);
minbleicsetcond(&state, 0.0, (double)(0), 1.0E-15, 0, _state);
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&fulla.ptr.pp_double[i][0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
state.f = state.f+0.5*v*state.x.ptr.p_double[i];
state.g.ptr.p_double[i] = v;
}
}
}
minbleicresults(&state, &xf, &rep, _state);
ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminbleicunit.ap:1819");
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(x0.ptr.p_double[i]-xf.ptr.p_double[i], _state),1.0E-12), __FILE__, __LINE__, "testminbleicunit.ap:1821");
}
}
ae_frame_leave(_state);
}
/*************************************************************************
This function tests convergence properties.
We solve several simple problems with different combinations of constraints
On failure sets Err to True (leaves it unchanged otherwise)
*************************************************************************/
static void testminbleicunit_testconv(ae_bool* err, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t passcount;
ae_int_t pass;
ae_vector bl;
ae_vector bu;
ae_vector x;
ae_vector b;
ae_vector tmp;
ae_vector g;
ae_vector xf;
ae_vector xs0;
ae_vector xs1;
ae_matrix a;
ae_matrix c;
ae_matrix ce;
ae_vector ct;
ae_vector nonnegative;
minbleicstate state;
double epsg;
double epsfeas;
double tol;
minbleicreport rep;
snnlssolver nnls;
ae_int_t m;
ae_int_t n;
ae_int_t k;
ae_int_t i;
ae_int_t j;
double v;
double vv;
ae_int_t preckind;
ae_int_t akind;
ae_int_t shiftkind;
ae_int_t bscale;
double tolconstr;
double f0;
double f1;
ae_int_t ccnt;
hqrndstate rs;
ae_frame_make(_state, &_frame_block);
memset(&bl, 0, sizeof(bl));
memset(&bu, 0, sizeof(bu));
memset(&x, 0, sizeof(x));
memset(&b, 0, sizeof(b));
memset(&tmp, 0, sizeof(tmp));
memset(&g, 0, sizeof(g));
memset(&xf, 0, sizeof(xf));
memset(&xs0, 0, sizeof(xs0));
memset(&xs1, 0, sizeof(xs1));
memset(&a, 0, sizeof(a));
memset(&c, 0, sizeof(c));
memset(&ce, 0, sizeof(ce));
memset(&ct, 0, sizeof(ct));
memset(&nonnegative, 0, sizeof(nonnegative));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&nnls, 0, sizeof(nnls));
memset(&rs, 0, sizeof(rs));
ae_vector_init(&bl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
ae_vector_init(&g, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xf, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xs0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xs1, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ce, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
ae_vector_init(&nonnegative, 0, DT_BOOL, _state, ae_true);
_minbleicstate_init(&state, _state, ae_true);
_minbleicreport_init(&rep, _state, ae_true);
_snnlssolver_init(&nnls, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
epsg = 1.0E-8;
epsfeas = 1.0E-8;
tol = 0.001;
passcount = 10;
/*
* Three closely connected problems:
* * 2-dimensional space
* * octagonal area bounded by:
* * -1<=x<=+1
* * -1<=y<=+1
* * x+y<=1.5
* * x-y<=1.5
* * -x+y<=1.5
* * -x-y<=1.5
* * several target functions:
* * f0=x+0.001*y, minimum at x=-1, y=-0.5
* * f1=(x+10)^2+y^2, minimum at x=-1, y=0
* * f2=(x+10)^2+(y-0.6)^2, minimum at x=-1, y=0.5
*/
ae_vector_set_length(&x, 2, _state);
ae_vector_set_length(&bl, 2, _state);
ae_vector_set_length(&bu, 2, _state);
ae_matrix_set_length(&c, 4, 3, _state);
ae_vector_set_length(&ct, 4, _state);
bl.ptr.p_double[0] = (double)(-1);
bl.ptr.p_double[1] = (double)(-1);
bu.ptr.p_double[0] = (double)(1);
bu.ptr.p_double[1] = (double)(1);
c.ptr.pp_double[0][0] = (double)(1);
c.ptr.pp_double[0][1] = (double)(1);
c.ptr.pp_double[0][2] = 1.5;
ct.ptr.p_int[0] = -1;
c.ptr.pp_double[1][0] = (double)(1);
c.ptr.pp_double[1][1] = (double)(-1);
c.ptr.pp_double[1][2] = 1.5;
ct.ptr.p_int[1] = -1;
c.ptr.pp_double[2][0] = (double)(-1);
c.ptr.pp_double[2][1] = (double)(1);
c.ptr.pp_double[2][2] = 1.5;
ct.ptr.p_int[2] = -1;
c.ptr.pp_double[3][0] = (double)(-1);
c.ptr.pp_double[3][1] = (double)(-1);
c.ptr.pp_double[3][2] = 1.5;
ct.ptr.p_int[3] = -1;
for(pass=1; pass<=passcount; pass++)
{
/*
* f0
*/
x.ptr.p_double[0] = 0.2*ae_randomreal(_state)-0.1;
x.ptr.p_double[1] = 0.2*ae_randomreal(_state)-0.1;
minbleiccreate(2, &x, &state, _state);
minbleicsetbc(&state, &bl, &bu, _state);
minbleicsetlc(&state, &c, &ct, 4, _state);
minbleicsetcond(&state, epsg, 0.0, 0.0, 0, _state);
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
state.f = state.x.ptr.p_double[0]+0.001*state.x.ptr.p_double[1];
state.g.ptr.p_double[0] = (double)(1);
state.g.ptr.p_double[1] = 0.001;
}
}
minbleicresults(&state, &x, &rep, _state);
if( rep.terminationtype>0 )
{
*err = *err||ae_fp_greater(ae_fabs(x.ptr.p_double[0]+1, _state),tol);
*err = *err||ae_fp_greater(ae_fabs(x.ptr.p_double[1]+0.5, _state),tol);
}
else
{
*err = ae_true;
}
/*
* f1
*/
x.ptr.p_double[0] = 0.2*ae_randomreal(_state)-0.1;
x.ptr.p_double[1] = 0.2*ae_randomreal(_state)-0.1;
minbleiccreate(2, &x, &state, _state);
minbleicsetbc(&state, &bl, &bu, _state);
minbleicsetlc(&state, &c, &ct, 4, _state);
minbleicsetcond(&state, epsg, 0.0, 0.0, 0, _state);
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
state.f = ae_sqr(state.x.ptr.p_double[0]+10, _state)+ae_sqr(state.x.ptr.p_double[1], _state);
state.g.ptr.p_double[0] = 2*(state.x.ptr.p_double[0]+10);
state.g.ptr.p_double[1] = 2*state.x.ptr.p_double[1];
}
}
minbleicresults(&state, &x, &rep, _state);
if( rep.terminationtype>0 )
{
*err = *err||ae_fp_greater(ae_fabs(x.ptr.p_double[0]+1, _state),tol);
*err = *err||ae_fp_greater(ae_fabs(x.ptr.p_double[1], _state),tol);
}
else
{
*err = ae_true;
}
/*
* f2
*/
x.ptr.p_double[0] = 0.2*ae_randomreal(_state)-0.1;
x.ptr.p_double[1] = 0.2*ae_randomreal(_state)-0.1;
minbleiccreate(2, &x, &state, _state);
minbleicsetbc(&state, &bl, &bu, _state);
minbleicsetlc(&state, &c, &ct, 4, _state);
minbleicsetcond(&state, epsg, 0.0, 0.0, 0, _state);
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
state.f = ae_sqr(state.x.ptr.p_double[0]+10, _state)+ae_sqr(state.x.ptr.p_double[1]-0.6, _state);
state.g.ptr.p_double[0] = 2*(state.x.ptr.p_double[0]+10);
state.g.ptr.p_double[1] = 2*(state.x.ptr.p_double[1]-0.6);
}
}
minbleicresults(&state, &x, &rep, _state);
if( rep.terminationtype>0 )
{
*err = *err||ae_fp_greater(ae_fabs(x.ptr.p_double[0]+1, _state),tol);
*err = *err||ae_fp_greater(ae_fabs(x.ptr.p_double[1]-0.5, _state),tol);
}
else
{
*err = ae_true;
}
}
/*
* Degenerate optimization problem with excessive constraints.
*
* * N=3..10, M=N div 3, K = 2*N
* * f(x) = 0.5*|A*x-b|^2, where A is MxN random matrix, b is Mx1 random vector
* * bound constraint:
* a) Ci=x[i]=Ci for i=0..M-1
* b) 0<=x[i]<=1 for i=M..N-1
* * linear constraints (for fixed feasible xf and random ai):
* a) ai*x = ai*xf for i=0..M-1
* b) ai*x <= ai*xf+random(0.1,1.0) for i=M..K-1
* * preconditioner is chosen at random (we just want to be
* sure that preconditioning won't prevent us from detecting
* infeasible point):
* a) unit preconditioner
* b) random diagonal-based preconditioner
* c) random scale-based preconditioner
* * we choose two random initial points from interior of the area
* given by bound constraints.
*
* We do not know analytic solution of this problem, and we do not need
* to solve it :) we just perform two restarts from two different initial
* points and check that both solutions give approximately same function
* value.
*/
for(preckind=0; preckind<=2; preckind++)
{
for(n=3; n<=10; n++)
{
/*
* Generate problem
*/
m = n/3;
k = 2*n;
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&xs0, n, _state);
ae_vector_set_length(&xs1, n, _state);
ae_vector_set_length(&xf, n, _state);
for(i=0; i<=n-1; i++)
{
if( i=-2; bscale--)
{
/*
* Generate A, B and initial point
*/
ae_matrix_set_length(&a, n, n, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = ae_pow((double)(10), (double)(bscale), _state)*hqrndnormal(&rs, _state);
x.ptr.p_double[i] = hqrnduniformr(&rs, _state)-0.5;
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
if( akind==1 )
{
/*
* Dense well conditioned SPD
*/
spdmatrixrndcond(n, 50.0, &a, _state);
}
if( akind==2 )
{
/*
* Dense well conditioned indefinite
*/
smatrixrndcond(n, 50.0, &a, _state);
}
if( akind==3 )
{
/*
* Low rank
*/
ae_vector_set_length(&tmp, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
for(k=1; k<=ae_minint(3, n-1, _state); k++)
{
for(i=0; i<=n-1; i++)
{
tmp.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
v = hqrndnormal(&rs, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j];
}
}
}
}
/*
* Generate constraints
*/
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
for(i=0; i<=n-1; i++)
{
bl.ptr.p_double[i] = -1.0;
bu.ptr.p_double[i] = 1.0;
}
ccnt = ae_round(ae_pow((double)(2), (double)(n), _state), _state);
ae_matrix_set_length(&c, ccnt, n+1, _state);
ae_vector_set_length(&ct, ccnt, _state);
for(i=0; i<=ccnt-1; i++)
{
ct.ptr.p_int[i] = -1;
k = i;
c.ptr.pp_double[i][n] = ae_sign((double)(shiftkind), _state)*ae_pow((double)(10), ae_fabs((double)(shiftkind), _state), _state)*ae_machineepsilon;
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = (double)(2*(k%2)-1);
c.ptr.pp_double[i][n] = c.ptr.pp_double[i][n]+c.ptr.pp_double[i][j]*c.ptr.pp_double[i][j];
k = k/2;
}
}
/*
* Create and optimize
*/
minbleiccreate(n, &x, &state, _state);
minbleicsetbc(&state, &bl, &bu, _state);
minbleicsetlc(&state, &c, &ct, ccnt, _state);
minbleicsetcond(&state, 1.0E-9, 0.0, 0.0, 0, _state);
while(minbleiciteration(&state, _state))
{
ae_assert(state.needfg, "Assertion failed", _state);
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+state.x.ptr.p_double[i]*b.ptr.p_double[i];
state.g.ptr.p_double[i] = b.ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
state.f = state.f+0.5*state.x.ptr.p_double[i]*v;
state.g.ptr.p_double[i] = state.g.ptr.p_double[i]+v;
}
}
minbleicresults(&state, &xs0, &rep, _state);
ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminbleicunit.ap:2341");
if( *err )
{
ae_frame_leave(_state);
return;
}
/*
* Evaluate gradient at solution and test
*/
vv = 0.0;
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xs0.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = v+b.ptr.p_double[i];
if( ae_fp_less_eq(xs0.ptr.p_double[i],bl.ptr.p_double[i]+tolconstr)&&ae_fp_greater(v,(double)(0)) )
{
v = 0.0;
}
if( ae_fp_greater_eq(xs0.ptr.p_double[i],bu.ptr.p_double[i]-tolconstr)&&ae_fp_less(v,(double)(0)) )
{
v = 0.0;
}
vv = vv+ae_sqr(v, _state);
}
vv = ae_sqrt(vv, _state);
ae_set_error_flag(err, ae_fp_greater(vv,1.0E-5), __FILE__, __LINE__, "testminbleicunit.ap:2365");
}
}
}
}
/*
* Convex/nonconvex optimization problem with combination of
* box and linear constraints:
*
* * N=2..8
* * f = 0.5*x'*A*x+b'*x
* * b has normally distributed entries with scale 10^BScale
* * several kinds of A are tried: zero, well conditioned SPD,
* well conditioned indefinite, low rank
* * box constraints: x[i] in [-1,+1]
* * initial point x0 = [0 0 ... 0 0]
* * CCnt=min(3,N-1) general linear constraints of form (c,x)=0.
* random mix of equality/inequality constraints is tried.
* x0 is guaranteed to be feasible.
*
* We check that constrained gradient is close to zero at solution.
* Inequality constraint is considered active if distance to boundary
* is less than TolConstr. We use nonnegative least squares solver
* in order to compute constrained gradient.
*/
tolconstr = 1.0E-8;
for(n=2; n<=8; n++)
{
for(akind=0; akind<=3; akind++)
{
for(bscale=0; bscale>=-2; bscale--)
{
/*
* Generate A, B and initial point
*/
ae_matrix_set_length(&a, n, n, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = ae_pow((double)(10), (double)(bscale), _state)*hqrndnormal(&rs, _state);
x.ptr.p_double[i] = 0.0;
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
if( akind==1 )
{
/*
* Dense well conditioned SPD
*/
spdmatrixrndcond(n, 50.0, &a, _state);
}
if( akind==2 )
{
/*
* Dense well conditioned indefinite
*/
smatrixrndcond(n, 50.0, &a, _state);
}
if( akind==3 )
{
/*
* Low rank
*/
ae_vector_set_length(&tmp, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
for(k=1; k<=ae_minint(3, n-1, _state); k++)
{
for(i=0; i<=n-1; i++)
{
tmp.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
v = hqrndnormal(&rs, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j];
}
}
}
}
/*
* Generate constraints
*/
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
for(i=0; i<=n-1; i++)
{
bl.ptr.p_double[i] = -1.0;
bu.ptr.p_double[i] = 1.0;
}
ccnt = ae_minint(3, n-1, _state);
ae_matrix_set_length(&c, ccnt, n+1, _state);
ae_vector_set_length(&ct, ccnt, _state);
for(i=0; i<=ccnt-1; i++)
{
ct.ptr.p_int[i] = hqrnduniformi(&rs, 3, _state)-1;
c.ptr.pp_double[i][n] = 0.0;
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5;
}
}
/*
* Create and optimize
*/
minbleiccreate(n, &x, &state, _state);
minbleicsetbc(&state, &bl, &bu, _state);
minbleicsetlc(&state, &c, &ct, ccnt, _state);
minbleicsetcond(&state, 1.0E-9, 0.0, 0.0, 0, _state);
while(minbleiciteration(&state, _state))
{
ae_assert(state.needfg, "Assertion failed", _state);
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+state.x.ptr.p_double[i]*b.ptr.p_double[i];
state.g.ptr.p_double[i] = b.ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
state.f = state.f+0.5*state.x.ptr.p_double[i]*v;
state.g.ptr.p_double[i] = state.g.ptr.p_double[i]+v;
}
}
minbleicresults(&state, &xs0, &rep, _state);
ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminbleicunit.ap:2487");
if( *err )
{
ae_frame_leave(_state);
return;
}
/*
* 1. evaluate unconstrained gradient at solution
*
* 2. calculate constrained gradient (NNLS solver is used
* to evaluate gradient subject to active constraints).
* In order to do this we form CE matrix, matrix of active
* constraints (columns store constraint vectors). Then
* we try to approximate gradient vector by columns of CE,
* subject to non-negativity restriction placed on variables
* corresponding to inequality constraints.
*
* Residual from such regression is a constrained gradient vector.
*/
ae_vector_set_length(&g, n, _state);
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xs0.ptr.p_double[0], 1, ae_v_len(0,n-1));
g.ptr.p_double[i] = v+b.ptr.p_double[i];
}
ae_matrix_set_length(&ce, n, n+ccnt, _state);
ae_vector_set_length(&nonnegative, n+ccnt, _state);
k = 0;
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(err, ae_fp_less(xs0.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testminbleicunit.ap:2515");
ae_set_error_flag(err, ae_fp_greater(xs0.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testminbleicunit.ap:2516");
if( ae_fp_less_eq(xs0.ptr.p_double[i],bl.ptr.p_double[i]+tolconstr) )
{
for(j=0; j<=n-1; j++)
{
ce.ptr.pp_double[j][k] = 0.0;
}
ce.ptr.pp_double[i][k] = 1.0;
nonnegative.ptr.p_bool[k] = ae_true;
inc(&k, _state);
continue;
}
if( ae_fp_greater_eq(xs0.ptr.p_double[i],bu.ptr.p_double[i]-tolconstr) )
{
for(j=0; j<=n-1; j++)
{
ce.ptr.pp_double[j][k] = 0.0;
}
ce.ptr.pp_double[i][k] = -1.0;
nonnegative.ptr.p_bool[k] = ae_true;
inc(&k, _state);
continue;
}
}
for(i=0; i<=ccnt-1; i++)
{
v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &xs0.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = v-c.ptr.pp_double[i][n];
ae_set_error_flag(err, ct.ptr.p_int[i]==0&&ae_fp_greater(ae_fabs(v, _state),tolconstr), __FILE__, __LINE__, "testminbleicunit.ap:2540");
ae_set_error_flag(err, ct.ptr.p_int[i]>0&&ae_fp_less(v,-tolconstr), __FILE__, __LINE__, "testminbleicunit.ap:2541");
ae_set_error_flag(err, ct.ptr.p_int[i]<0&&ae_fp_greater(v,tolconstr), __FILE__, __LINE__, "testminbleicunit.ap:2542");
if( ct.ptr.p_int[i]==0 )
{
for(j=0; j<=n-1; j++)
{
ce.ptr.pp_double[j][k] = c.ptr.pp_double[i][j];
}
nonnegative.ptr.p_bool[k] = ae_false;
inc(&k, _state);
continue;
}
if( (ct.ptr.p_int[i]>0&&ae_fp_less_eq(v,tolconstr))||(ct.ptr.p_int[i]<0&&ae_fp_greater_eq(v,-tolconstr)) )
{
for(j=0; j<=n-1; j++)
{
ce.ptr.pp_double[j][k] = ae_sign((double)(ct.ptr.p_int[i]), _state)*c.ptr.pp_double[i][j];
}
nonnegative.ptr.p_bool[k] = ae_true;
inc(&k, _state);
continue;
}
}
snnlsinit(0, 0, 0, &nnls, _state);
snnlssetproblem(&nnls, &ce, &g, 0, k, n, _state);
for(i=0; i<=k-1; i++)
{
if( !nonnegative.ptr.p_bool[i] )
{
snnlsdropnnc(&nnls, i, _state);
}
}
snnlssolve(&nnls, &tmp, _state);
for(i=0; i<=k-1; i++)
{
for(j=0; j<=n-1; j++)
{
g.ptr.p_double[j] = g.ptr.p_double[j]-tmp.ptr.p_double[i]*ce.ptr.pp_double[j][i];
}
}
vv = ae_v_dotproduct(&g.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,n-1));
vv = ae_sqrt(vv, _state);
ae_set_error_flag(err, ae_fp_greater(vv,1.0E-5), __FILE__, __LINE__, "testminbleicunit.ap:2571");
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
This function tests preconditioning
On failure sets Err to True (leaves it unchanged otherwise)
*************************************************************************/
static void testminbleicunit_testpreconditioning(ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t pass;
ae_int_t n;
ae_vector x;
ae_vector x0;
ae_int_t i;
ae_int_t k;
ae_matrix v;
ae_matrix c;
ae_vector ct;
ae_vector bl;
ae_vector bu;
ae_vector vd;
ae_vector d;
ae_vector units;
ae_vector s;
ae_int_t cntb1;
ae_int_t cntb2;
ae_int_t cntg1;
ae_int_t cntg2;
double epsg;
ae_vector diagh;
minbleicstate state;
minbleicreport rep;
ae_int_t ckind;
ae_int_t fk;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&x0, 0, sizeof(x0));
memset(&v, 0, sizeof(v));
memset(&c, 0, sizeof(c));
memset(&ct, 0, sizeof(ct));
memset(&bl, 0, sizeof(bl));
memset(&bu, 0, sizeof(bu));
memset(&vd, 0, sizeof(vd));
memset(&d, 0, sizeof(d));
memset(&units, 0, sizeof(units));
memset(&s, 0, sizeof(s));
memset(&diagh, 0, sizeof(diagh));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
ae_vector_init(&bl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&vd, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&units, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&diagh, 0, DT_REAL, _state, ae_true);
_minbleicstate_init(&state, _state, ae_true);
_minbleicreport_init(&rep, _state, ae_true);
/*
* Preconditioner test 1.
*
* If
* * B1 is default preconditioner with unit scale
* * G1 is diagonal preconditioner based on approximate diagonal of Hessian matrix
* * B2 is default preconditioner with non-unit scale S[i]=1/sqrt(h[i])
* * G2 is scale-based preconditioner with non-unit scale S[i]=1/sqrt(h[i])
* then B1 is worse than G1, B2 is worse than G2.
* "Worse" means more iterations to converge.
*
* Test problem setup:
* * f(x) = sum( ((i*i+1)*x[i])^2, i=0..N-1)
* * constraints:
* 0) absent
* 1) boundary only
* 2) linear equality only
* 3) combination of boundary and linear equality constraints
*
* N - problem size
* K - number of repeated passes (should be large enough to average out random factors)
*/
k = 100;
epsg = 1.0E-8;
for(n=10; n<=10; n++)
{
for(ckind=0; ckind<=3; ckind++)
{
fk = 1;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&units, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = (double)(0);
units.ptr.p_double[i] = (double)(1);
}
minbleiccreate(n, &x, &state, _state);
minbleicsetcond(&state, epsg, 0.0, 0.0, 0, _state);
if( ckind==1||ckind==3 )
{
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
for(i=0; i<=n-1; i++)
{
bl.ptr.p_double[i] = (double)(-1);
bu.ptr.p_double[i] = (double)(1);
}
minbleicsetbc(&state, &bl, &bu, _state);
}
if( ckind==2||ckind==3 )
{
ae_matrix_set_length(&c, 1, n+1, _state);
ae_vector_set_length(&ct, 1, _state);
ct.ptr.p_int[0] = ae_randominteger(3, _state)-1;
for(i=0; i<=n-1; i++)
{
c.ptr.pp_double[0][i] = 2*ae_randomreal(_state)-1;
}
c.ptr.pp_double[0][n] = (double)(0);
minbleicsetlc(&state, &c, &ct, 1, _state);
}
/*
* Test it with default preconditioner VS. perturbed diagonal preconditioner
*/
minbleicsetprecdefault(&state, _state);
minbleicsetscale(&state, &units, _state);
cntb1 = 0;
for(pass=0; pass<=k-1; pass++)
{
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
minbleicrestartfrom(&state, &x, _state);
while(minbleiciteration(&state, _state))
{
testminbleicunit_calciip2(&state, n, fk, _state);
}
minbleicresults(&state, &x, &rep, _state);
cntb1 = cntb1+rep.inneriterationscount;
*err = *err||rep.terminationtype<=0;
}
ae_vector_set_length(&diagh, n, _state);
for(i=0; i<=n-1; i++)
{
diagh.ptr.p_double[i] = 2*ae_pow((double)(i*i+1), (double)(2*fk), _state)*(0.8+0.4*ae_randomreal(_state));
}
minbleicsetprecdiag(&state, &diagh, _state);
minbleicsetscale(&state, &units, _state);
cntg1 = 0;
for(pass=0; pass<=k-1; pass++)
{
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
minbleicrestartfrom(&state, &x, _state);
while(minbleiciteration(&state, _state))
{
testminbleicunit_calciip2(&state, n, fk, _state);
}
minbleicresults(&state, &x, &rep, _state);
cntg1 = cntg1+rep.inneriterationscount;
*err = *err||rep.terminationtype<=0;
}
*err = *err||cntb1=0, __FILE__, __LINE__, "testminbleicunit.ap:3117");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx>=0, __FILE__, __LINE__, "testminbleicunit.ap:3118");
ae_set_error_flag(wereerrors, ogrep.nonc1test0positive, __FILE__, __LINE__, "testminbleicunit.ap:3119");
ae_set_error_flag(wereerrors, ogrep.nonc1test1positive, __FILE__, __LINE__, "testminbleicunit.ap:3120");
/*
* Test gradient checking functionality, try various
* defect types:
* * accidental zeroing of some gradient component
* * accidental addition of 1.0 to some component
* * accidental multiplication by 2.0
* Try distorting both target and constraints.
*/
diffstep = 0.001;
n = 10;
for(skind=0; skind<=1; skind++)
{
for(defecttype=-1; defecttype<=2; defecttype++)
{
varidx = hqrnduniformi(&rs, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&s, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = ae_pow((double)(10), skind*(30*hqrnduniformr(&rs, _state)-15), _state);
x0.ptr.p_double[i] = (1.0+0.1*i)*s.ptr.p_double[i];
j = hqrnduniformi(&rs, 3, _state);
bndl.ptr.p_double[i] = -100*s.ptr.p_double[i];
bndu.ptr.p_double[i] = 100*s.ptr.p_double[i];
if( j==1 )
{
bndl.ptr.p_double[i] = x0.ptr.p_double[i];
}
if( j==2 )
{
bndu.ptr.p_double[i] = x0.ptr.p_double[i];
}
}
spdmatrixrndcond(n, 1.0E3, &a, _state);
spdmatrixrndcond(n, 1.0E3, &a1, _state);
minbleiccreate(n, &x0, &state, _state);
minbleicoptguardgradient(&state, diffstep, _state);
minbleicsetcond(&state, (double)(0), (double)(0), 1.0E-9, 10, _state);
minbleicsetscale(&state, &s, _state);
minbleicsetbc(&state, &bndl, &bndu, _state);
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(wereerrors, ae_fp_less(state.x.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminbleicunit.ap:3167");
ae_set_error_flag(wereerrors, ae_fp_greater(state.x.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminbleicunit.ap:3168");
}
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.f = state.f+0.5*(state.x.ptr.p_double[i]/s.ptr.p_double[i])*v;
state.g.ptr.p_double[i] = v;
}
if( defecttype==0 )
{
state.g.ptr.p_double[varidx] = (double)(0);
}
if( defecttype==1 )
{
state.g.ptr.p_double[varidx] = state.g.ptr.p_double[varidx]+1;
}
if( defecttype==2 )
{
state.g.ptr.p_double[varidx] = state.g.ptr.p_double[varidx]*2;
}
for(i=0; i<=n-1; i++)
{
state.g.ptr.p_double[i] = state.g.ptr.p_double[i]/s.ptr.p_double[i];
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minbleicresults(&state, &x1, &rep, _state);
minbleicoptguardresults(&state, &ogrep, _state);
/*
* Check that something is returned
*/
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminbleicunit.ap:3201");
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3202");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Compute reference values for true and spoiled Jacobian at X0
*/
ae_set_error_flag(wereerrors, !isfinitevector(&ogrep.badgradxbase, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3209");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_matrix_set_length(&jactrue, 1, n, _state);
ae_matrix_set_length(&jacdefect, 1, n, _state);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+ogrep.badgradxbase.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
jactrue.ptr.pp_double[0][i] = v;
jacdefect.ptr.pp_double[0][i] = v;
}
if( defecttype==0 )
{
jacdefect.ptr.pp_double[0][varidx] = (double)(0);
}
if( defecttype==1 )
{
jacdefect.ptr.pp_double[0][varidx] = jacdefect.ptr.pp_double[0][varidx]+1;
}
if( defecttype==2 )
{
jacdefect.ptr.pp_double[0][varidx] = jacdefect.ptr.pp_double[0][varidx]*2;
}
for(i=0; i<=n-1; i++)
{
jactrue.ptr.pp_double[0][i] = jactrue.ptr.pp_double[0][i]/s.ptr.p_double[i];
jacdefect.ptr.pp_double[0][i] = jacdefect.ptr.pp_double[0][i]/s.ptr.p_double[i];
}
/*
* Check OptGuard report
*/
ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgraduser, 1, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3237");
ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgradnum, 1, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3238");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
if( defecttype>=0 )
{
ae_set_error_flag(wereerrors, !ogrep.badgradsuspected, __FILE__, __LINE__, "testminbleicunit.ap:3243");
ae_set_error_flag(wereerrors, ogrep.badgradfidx!=0, __FILE__, __LINE__, "testminbleicunit.ap:3244");
ae_set_error_flag(wereerrors, ogrep.badgradvidx!=varidx, __FILE__, __LINE__, "testminbleicunit.ap:3245");
}
else
{
ae_set_error_flag(wereerrors, ogrep.badgradsuspected, __FILE__, __LINE__, "testminbleicunit.ap:3249");
ae_set_error_flag(wereerrors, ogrep.badgradfidx!=-1, __FILE__, __LINE__, "testminbleicunit.ap:3250");
ae_set_error_flag(wereerrors, ogrep.badgradvidx!=-1, __FILE__, __LINE__, "testminbleicunit.ap:3251");
}
for(j=0; j<=n-1; j++)
{
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jactrue.ptr.pp_double[0][j]-ogrep.badgradnum.ptr.pp_double[0][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testminbleicunit.ap:3255");
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jacdefect.ptr.pp_double[0][j]-ogrep.badgraduser.ptr.pp_double[0][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testminbleicunit.ap:3256");
}
}
}
/*
* A test for detection of C1 continuity violations in the target.
*
* Target function is a sum of |(x,c_i)| for i=1..N.
* No constraints is present.
* Analytic gradient is provided.
*
* OptGuard should be able to detect violations in more than
* 99.9% of runs; it means that 100 runs should have no more than 4
* failures in all cases (even after multiple repeated tests; according
* to the binomial distribution quantiles).
*
* We select some N and perform exhaustive search for this N.
*/
passcount = 100;
maxfails = 4;
maxc1test0fails = 10;
maxc1test1fails = 10;
n = 1+hqrnduniformi(&rs, 10, _state);
failurecounter = 0;
c1test0fails = 0;
c1test1fails = 0;
avgstr0len = (double)(0);
avglng0len = (double)(0);
avgstr1len = (double)(0);
avglng1len = (double)(0);
for(pass=1; pass<=passcount; pass++)
{
/*
* Formulate problem
*/
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
/*
* Create and try to solve
*/
minbleiccreate(n, &x0, &state, _state);
minbleicsetcond(&state, (double)(0), (double)(0), 1.0E-9, 50, _state);
minbleicsetscale(&state, &s, _state);
minbleicoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminbleicunit_maxoptguardlevel, _state), _state);
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.g.ptr.p_double[i] = (double)(0);
}
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.f = state.f+ae_fabs(v, _state);
v = (double)(ae_sign(v, _state));
for(j=0; j<=n-1; j++)
{
state.g.ptr.p_double[j] = state.g.ptr.p_double[j]+v*a.ptr.pp_double[i][j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minbleicresults(&state, &x1, &rep, _state);
minbleicoptguardresults(&state, &ogrep, _state);
/*
* Check basic properties of the solution
*/
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3337");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminbleicunit.ap:3338");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Check generic OptGuard report: distinguish between "hard"
* failures which result in immediate termination
* (C0 violation being reported) and "soft" ones
* (C1 violation is NOT reported) which accumulate
* until we exhaust limit.
*/
ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminbleicunit.ap:3349");
ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminbleicunit.ap:3350");
failed = ae_false;
failed = failed||optguardallclear(&ogrep, _state);
failed = failed||!ogrep.nonc1suspected;
failed = failed||ogrep.nonc1fidx!=0;
if( failed )
{
inc(&failurecounter, _state);
}
/*
* Check C1 continuity test #0
*/
minbleicoptguardnonc1test0results(&state, &ognonc1test0strrep, &ognonc1test0lngrep, _state);
minbleicoptguardnonc1test1results(&state, &ognonc1test1strrep, &ognonc1test1lngrep, _state);
if( ogrep.nonc1test0positive )
{
ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminbleicunit.ap:3365");
ae_set_error_flag(wereerrors, !ognonc1test0strrep.positive, __FILE__, __LINE__, "testminbleicunit.ap:3366");
ae_set_error_flag(wereerrors, !ognonc1test0lngrep.positive, __FILE__, __LINE__, "testminbleicunit.ap:3367");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testminbleicunit.ap:3368");
testminbleicunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0strrep, &a, n, _state);
testminbleicunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0lngrep, &a, n, _state);
avgstr0len = avgstr0len+(double)ognonc1test0strrep.cnt/(double)passcount;
avglng0len = avglng0len+(double)ognonc1test0lngrep.cnt/(double)passcount;
}
else
{
ae_set_error_flag(wereerrors, ognonc1test0strrep.positive, __FILE__, __LINE__, "testminbleicunit.ap:3376");
ae_set_error_flag(wereerrors, ognonc1test0lngrep.positive, __FILE__, __LINE__, "testminbleicunit.ap:3377");
testminbleicunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0strrep, &a, n, _state);
testminbleicunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0lngrep, &a, n, _state);
inc(&c1test0fails, _state);
}
if( ogrep.nonc1test1positive )
{
ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminbleicunit.ap:3384");
ae_set_error_flag(wereerrors, !ognonc1test1strrep.positive, __FILE__, __LINE__, "testminbleicunit.ap:3385");
ae_set_error_flag(wereerrors, !ognonc1test1lngrep.positive, __FILE__, __LINE__, "testminbleicunit.ap:3386");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testminbleicunit.ap:3387");
testminbleicunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1strrep, &a, n, _state);
testminbleicunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1lngrep, &a, n, _state);
avgstr1len = avgstr1len+(double)ognonc1test1strrep.cnt/(double)passcount;
avglng1len = avglng1len+(double)ognonc1test1lngrep.cnt/(double)passcount;
}
else
{
ae_set_error_flag(wereerrors, ognonc1test1strrep.positive, __FILE__, __LINE__, "testminbleicunit.ap:3395");
ae_set_error_flag(wereerrors, ognonc1test1lngrep.positive, __FILE__, __LINE__, "testminbleicunit.ap:3396");
testminbleicunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1strrep, &a, n, _state);
testminbleicunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1lngrep, &a, n, _state);
inc(&c1test1fails, _state);
}
}
ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testminbleicunit.ap:3403");
ae_set_error_flag(wereerrors, c1test0fails>maxc1test0fails, __FILE__, __LINE__, "testminbleicunit.ap:3404");
ae_set_error_flag(wereerrors, c1test1fails>maxc1test1fails, __FILE__, __LINE__, "testminbleicunit.ap:3405");
ae_set_error_flag(wereerrors, ae_fp_less_eq(avglng0len,avgstr0len), __FILE__, __LINE__, "testminbleicunit.ap:3406");
ae_set_error_flag(wereerrors, ae_fp_less_eq(avglng1len,avgstr1len), __FILE__, __LINE__, "testminbleicunit.ap:3407");
/*
* Detection of C1 continuity violations in the target under numerical differentiation:
* * target function is a sum of |(x,c_i)| for i=1..N.
* * no constraints is present.
* * analytic gradient is provided.
*
* OptGuard should always be able to detect violations in more than
* 99% of runs (note: reduced strength when compared with analytic gradient);
* it means that 100 runs should have no more than 10 failures in all cases
* (even after multiple repeated tests; according to the binomial distribution
* quantiles).
*
* We select some N and perform exhaustive search for this N.
*/
diffstep = 0.0001;
passcount = 100;
maxfails = 10;
n = 1+hqrnduniformi(&rs, 10, _state);
failurecounter = 0;
for(pass=1; pass<=passcount; pass++)
{
/*
* Formulate problem
*/
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = 0.01*ae_pow((double)(2), 0.33*hqrndnormal(&rs, _state), _state);
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
/*
* Create and try to solve
*/
minbleiccreatef(n, &x0, diffstep, &state, _state);
minbleicsetcond(&state, (double)(0), (double)(0), 1.0E-9, 50, _state);
minbleicoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminbleicunit_maxoptguardlevel, _state), _state);
while(minbleiciteration(&state, _state))
{
if( state.needf )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.f = state.f+ae_fabs(v, _state);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minbleicresults(&state, &x1, &rep, _state);
minbleicoptguardresults(&state, &ogrep, _state);
/*
* Check basic properties of the solution
*/
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3472");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminbleicunit.ap:3473");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Check OptGuard report: distinguish between "hard"
* failures which result in immediate termination
* (C0 violation being reported) and "soft" ones
* (C1 violation is NOT reported) which accumulate
* until we exhaust limit.
*/
ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminbleicunit.ap:3484");
ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminbleicunit.ap:3485");
failed = ae_false;
failed = failed||optguardallclear(&ogrep, _state);
failed = failed||!ogrep.nonc1suspected;
failed = failed||ogrep.nonc1fidx!=0;
if( failed )
{
inc(&failurecounter, _state);
}
}
ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testminbleicunit.ap:3493");
/*
* Make sure than no false positives are reported for larger
* problems where numerical noise can be an issue:
* * N=100 dimensions
* * positive-definite quadratic programming problem
* * upper limit on iterations count, MaxIts=25
* We simply test that OptGuard does not return error code.
*/
n = 100;
spdmatrixrndcond(n, 1.0E2, &a, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
x0.ptr.p_double[i] = ae_pow(2.0, hqrndnormal(&rs, _state), _state);
}
minbleiccreate(n, &x0, &state, _state);
minbleicoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminbleicunit_maxoptguardlevel, _state), _state);
minbleicsetcond(&state, (double)(0), (double)(0), 1.0E-9, 25, _state);
while(minbleiciteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.g.ptr.p_double[i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.f = state.f+0.5*state.x.ptr.p_double[i]*a.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.g.ptr.p_double[i] = state.g.ptr.p_double[i]+a.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minbleicresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3536");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminbleicunit.ap:3537");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
minbleicoptguardresults(&state, &ogrep, _state);
ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminbleicunit.ap:3541");
ae_frame_leave(_state);
}
/*************************************************************************
This function tests report of "non-C1" test #0 for task #0
given by matrix A.
On failure sets error flag.
*************************************************************************/
static void testminbleicunit_testoptguardc1test0reportfortask0(ae_bool* err,
optguardnonc1test0report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
double vv;
double va;
double vb;
ae_bool hasc1discontinuities;
if( rep->positive )
{
/*
* Check positive report, first checks
*/
ae_set_error_flag(err, rep->fidx!=0, __FILE__, __LINE__, "testminbleicunit.ap:3568");
ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testminbleicunit.ap:3569");
ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testminbleicunit.ap:3570");
ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testminbleicunit.ap:3571");
ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testminbleicunit.ap:3572");
ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testminbleicunit.ap:3573");
ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testminbleicunit.ap:3574");
ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testminbleicunit.ap:3575");
ae_set_error_flag(err, rep->f.cnt!=rep->cnt, __FILE__, __LINE__, "testminbleicunit.ap:3576");
ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3577");
ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3578");
ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testminbleicunit.ap:3579");
ae_set_error_flag(err, !isfinitevector(&rep->f, rep->cnt, _state), __FILE__, __LINE__, "testminbleicunit.ap:3580");
if( *err )
{
return;
}
/*
* Check consistency of X0, D, Stp and F
*/
for(k=0; k<=rep->cnt-2; k++)
{
ae_set_error_flag(err, ae_fp_greater_eq(rep->stp.ptr.p_double[k],rep->stp.ptr.p_double[k+1]), __FILE__, __LINE__, "testminbleicunit.ap:3588");
}
for(k=0; k<=rep->cnt-1; k++)
{
v = (double)(0);
for(i=0; i<=n-1; i++)
{
vv = (double)(0);
for(j=0; j<=n-1; j++)
{
vv = vv+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[k]);
}
v = v+ae_fabs(vv, _state);
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-rep->f.ptr.p_double[k], _state),1.0E-6*ae_maxreal(ae_fabs(v, _state), (double)(1), _state)), __FILE__, __LINE__, "testminbleicunit.ap:3601");
}
/*
* Check that interval [#StpIdxA,#StpIdxB] contains at least one discontinuity
*/
hasc1discontinuities = ae_false;
for(i=0; i<=n-1; i++)
{
va = (double)(0);
vb = (double)(0);
for(j=0; j<=n-1; j++)
{
va = va+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxa]);
vb = vb+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxb]);
}
hasc1discontinuities = hasc1discontinuities||ae_sign(va, _state)!=ae_sign(vb, _state);
}
ae_set_error_flag(err, !hasc1discontinuities, __FILE__, __LINE__, "testminbleicunit.ap:3619");
}
else
{
/*
* Check negative report: fields must be empty
*/
ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testminbleicunit.ap:3626");
ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testminbleicunit.ap:3627");
ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testminbleicunit.ap:3628");
ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testminbleicunit.ap:3629");
ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testminbleicunit.ap:3630");
ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testminbleicunit.ap:3631");
ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testminbleicunit.ap:3632");
ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testminbleicunit.ap:3633");
ae_set_error_flag(err, rep->f.cnt!=0, __FILE__, __LINE__, "testminbleicunit.ap:3634");
}
}
/*************************************************************************
This function tests report of "non-C1" test #1 for task #0
given by matrix A.
On failure sets error flag.
*************************************************************************/
static void testminbleicunit_testoptguardc1test1reportfortask0(ae_bool* err,
optguardnonc1test1report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
double vv;
double va;
double vb;
ae_bool tooclose;
ae_bool hasc1discontinuities;
if( rep->positive )
{
/*
* Check positive report, first checks
*/
ae_set_error_flag(err, rep->fidx!=0, __FILE__, __LINE__, "testminbleicunit.ap:3662");
ae_set_error_flag(err, rep->vidx<0, __FILE__, __LINE__, "testminbleicunit.ap:3663");
ae_set_error_flag(err, rep->vidx>n, __FILE__, __LINE__, "testminbleicunit.ap:3664");
ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testminbleicunit.ap:3665");
ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testminbleicunit.ap:3666");
ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testminbleicunit.ap:3667");
ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testminbleicunit.ap:3668");
ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testminbleicunit.ap:3669");
ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testminbleicunit.ap:3670");
ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testminbleicunit.ap:3671");
ae_set_error_flag(err, rep->g.cnt!=rep->cnt, __FILE__, __LINE__, "testminbleicunit.ap:3672");
ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3673");
ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testminbleicunit.ap:3674");
ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testminbleicunit.ap:3675");
ae_set_error_flag(err, !isfinitevector(&rep->g, rep->cnt, _state), __FILE__, __LINE__, "testminbleicunit.ap:3676");
if( *err )
{
return;
}
/*
* Check consistency of X0, D, Stp and G
*/
for(k=0; k<=rep->cnt-2; k++)
{
ae_set_error_flag(err, ae_fp_greater_eq(rep->stp.ptr.p_double[k],rep->stp.ptr.p_double[k+1]), __FILE__, __LINE__, "testminbleicunit.ap:3684");
}
for(k=0; k<=rep->cnt-1; k++)
{
v = (double)(0);
tooclose = ae_false;
for(i=0; i<=n-1; i++)
{
vv = (double)(0);
for(j=0; j<=n-1; j++)
{
vv = vv+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[k]);
}
v = v+ae_sign(vv, _state)*a->ptr.pp_double[i][rep->vidx];
tooclose = tooclose||ae_fp_less(ae_fabs(vv, _state),1.0E-4);
}
if( !tooclose )
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-rep->g.ptr.p_double[k], _state),1.0E-6*ae_maxreal(ae_fabs(v, _state), (double)(1), _state)), __FILE__, __LINE__, "testminbleicunit.ap:3698");
}
}
/*
* Check that interval [#StpIdxA,#StpIdxB] contains at least one discontinuity
*/
tooclose = ae_false;
hasc1discontinuities = ae_false;
for(i=0; i<=n-1; i++)
{
va = (double)(0);
vb = (double)(0);
for(j=0; j<=n-1; j++)
{
va = va+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxa]);
vb = vb+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxb]);
}
tooclose = (tooclose||ae_fp_less(ae_fabs(va, _state),1.0E-8))||ae_fp_less(ae_fabs(vb, _state),1.0E-8);
hasc1discontinuities = hasc1discontinuities||ae_sign(va, _state)!=ae_sign(vb, _state);
}
if( !tooclose )
{
ae_set_error_flag(err, !hasc1discontinuities, __FILE__, __LINE__, "testminbleicunit.ap:3719");
}
}
else
{
/*
* Check negative report: fields must be empty
*/
ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testminbleicunit.ap:3726");
ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testminbleicunit.ap:3727");
ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testminbleicunit.ap:3728");
ae_set_error_flag(err, rep->vidx!=-1, __FILE__, __LINE__, "testminbleicunit.ap:3729");
ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testminbleicunit.ap:3730");
ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testminbleicunit.ap:3731");
ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testminbleicunit.ap:3732");
ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testminbleicunit.ap:3733");
ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testminbleicunit.ap:3734");
ae_set_error_flag(err, rep->g.cnt!=0, __FILE__, __LINE__, "testminbleicunit.ap:3735");
}
}
static void testminqpunit_bcqptest(ae_bool* wereerrors, ae_state *_state);
static ae_bool testminqpunit_ecqptest(ae_state *_state);
static void testminqpunit_icqptest(ae_bool* err, ae_state *_state);
static void testminqpunit_generallcqptest(ae_bool* errorflag,
ae_state *_state);
static ae_bool testminqpunit_specialicqptests(ae_state *_state);
static void testminqpunit_denseaultests(ae_bool* errorflag,
ae_state *_state);
static void testminqpunit_ipmtests(ae_bool* errorflag, ae_state *_state);
static void testminqpunit_spectests(ae_bool* errorflag, ae_state *_state);
static double testminqpunit_projectedantigradnorm(ae_int_t n,
/* Real */ ae_vector* x,
/* Real */ ae_vector* g,
/* Real */ ae_vector* bndl,
/* Real */ ae_vector* bndu,
ae_state *_state);
static void testminqpunit_testbcgradandfeasibility(/* Real */ ae_matrix* a,
/* Real */ ae_vector* b,
/* Real */ ae_vector* bndl,
/* Real */ ae_vector* bndu,
ae_int_t n,
/* Real */ ae_vector* x,
double eps,
ae_bool* errorflag,
ae_state *_state);
static ae_int_t testminqpunit_setrandomalgoallmodern(minqpstate* s,
double* bctol,
double* lctol,
ae_state *_state);
static void testminqpunit_setrandomalgononconvex(minqpstate* s,
ae_state *_state);
static void testminqpunit_setrandomalgosemidefinite(minqpstate* s,
double* bctol,
double* lctol,
ae_state *_state);
static void testminqpunit_setrandomalgobc(minqpstate* s, ae_state *_state);
static void testminqpunit_setrandomalgoconvexlc(minqpstate* s,
ae_state *_state);
static void testminqpunit_setrandomalgononconvexlc(minqpstate* s,
ae_state *_state);
static void testminqpunit_densetosparse(/* Real */ ae_matrix* a,
ae_int_t n,
sparsematrix* s,
ae_state *_state);
static void testminqpunit_randomlysplitlc(/* Real */ ae_matrix* rawc,
/* Integer */ ae_vector* rawct,
ae_int_t rawccnt,
ae_int_t n,
sparsematrix* sparsec,
/* Integer */ ae_vector* sparsect,
ae_int_t* sparseccnt,
/* Real */ ae_matrix* densec,
/* Integer */ ae_vector* densect,
ae_int_t* denseccnt,
hqrndstate* rs,
ae_state *_state);
static void testminqpunit_randomlysplitandsetlclegacy(/* Real */ ae_matrix* rawc,
/* Integer */ ae_vector* rawct,
ae_int_t rawccnt,
ae_int_t n,
minqpstate* state,
hqrndstate* rs,
ae_state *_state);
static void testminqpunit_randomlysplitandsetlc2(/* Real */ ae_matrix* rawc,
/* Real */ ae_vector* rawcl,
/* Real */ ae_vector* rawcu,
ae_int_t rawccnt,
ae_int_t n,
minqpstate* state,
hqrndstate* rs,
ae_state *_state);
static void testminqpunit_randomlyselectconvertandsetquadraticterm(/* Real */ ae_matrix* a,
ae_int_t n,
minqpstate* state,
hqrndstate* rs,
ae_state *_state);
static double testminqpunit_getconstraintrcond(/* Real */ ae_matrix* c,
ae_int_t k,
ae_int_t n,
ae_state *_state);
static double testminqpunit_quadratictarget(/* Real */ ae_matrix* a,
/* Real */ ae_vector* b,
ae_int_t n,
/* Real */ ae_vector* x,
ae_state *_state);
ae_bool testminqp(ae_bool silent, ae_state *_state)
{
ae_bool simpleerrors;
ae_bool func1errors;
ae_bool func2errors;
ae_bool bcqperrors;
ae_bool ecqperrors;
ae_bool icqperrors;
ae_bool lcqperrors;
ae_bool quickqperrors;
ae_bool bleicerrors;
ae_bool denseaulerrors;
ae_bool ipmerrors;
ae_bool specerrors;
ae_bool waserrors;
ae_bool result;
/*
* The VERY basic tests for Cholesky and BLEIC
*/
simpleerrors = simpletest(_state);
func1errors = functest1(_state);
func2errors = functest2(_state);
/*
* Solver-specific tests
*/
denseaulerrors = ae_false;
ipmerrors = ae_false;
quickqperrors = quickqptests(_state);
bleicerrors = bleictests(_state);
testminqpunit_denseaultests(&denseaulerrors, _state);
testminqpunit_ipmtests(&ipmerrors, _state);
/*
*
*/
icqperrors = ae_false;
lcqperrors = ae_false;
bcqperrors = ae_false;
testminqpunit_bcqptest(&bcqperrors, _state);
ecqperrors = testminqpunit_ecqptest(_state);
testminqpunit_icqptest(&icqperrors, _state);
icqperrors = icqperrors||testminqpunit_specialicqptests(_state);
testminqpunit_generallcqptest(&lcqperrors, _state);
specerrors = ae_false;
testminqpunit_spectests(&specerrors, _state);
/*
* report
*/
waserrors = ((((((((((simpleerrors||func1errors)||func2errors)||bcqperrors)||ecqperrors)||icqperrors)||lcqperrors)||quickqperrors)||bleicerrors)||denseaulerrors)||ipmerrors)||specerrors;
if( !silent )
{
printf("TESTING MinQP\n");
printf("BASIC TESTS:\n");
printf("* SimpleTest: ");
if( simpleerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* Func1Test: ");
if( func1errors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* Func2Test: ");
if( func2errors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("GENERIC QP TESTS:\n");
printf("* box constrained: ");
if( bcqperrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* linearly constrained: ");
if( (ecqperrors||icqperrors)||lcqperrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("SOLVER-SPECIFIC TESTS:\n");
printf("* QuickQP solver tests: ");
if( quickqperrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* BLEIC solver tests: ");
if( bleicerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* DENSE-AUL solver tests: ");
if( denseaulerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* IPM solver tests: ");
if( ipmerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("SPECIAL PROPERTIES: ");
if( specerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
return result;
}
/*************************************************************************
Function to test: 'MinQPCreate', 'MinQPSetQuadraticTerm', 'MinQPSetBC',
'MinQPSetOrigin', 'MinQPSetStartingPoint', 'MinQPOptimize', 'MinQPResults'.
Test problem:
A = diag(aii), aii>0 (random)
b = 0
random bounds (either no bounds, one bound, two bounds av_neginf;
ub.ptr.p_double[j] = _state->v_posinf;
}
else
{
if( infd==1 )
{
db.ptr.p_double[j] = _state->v_neginf;
ub.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb;
}
else
{
if( infd==2 )
{
db.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb;
ub.ptr.p_double[j] = _state->v_posinf;
}
else
{
if( infd==3 )
{
db.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb;
ub.ptr.p_double[j] = db.ptr.p_double[j]+maxstb*ae_randomreal(_state)+0.01;
}
else
{
db.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb;
ub.ptr.p_double[j] = db.ptr.p_double[j];
}
}
}
}
}
minqpsetbc(&state, &db, &ub, _state);
/*
*initialization for shifting
*initial value for 'XORi'
*and searching true results
*/
for(j=0; j<=sn-1; j++)
{
xori.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb;
tx.ptr.p_double[j] = boundval(xori.ptr.p_double[j], db.ptr.p_double[j], ub.ptr.p_double[j], _state);
}
minqpsetorigin(&state, &xori, _state);
/*
*initialization for starting point
*/
for(j=0; j<=sn-1; j++)
{
stx.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb;
}
minqpsetstartingpoint(&state, &stx, _state);
/*
*optimize and get result
*/
minqpoptimize(&state, _state);
minqpresults(&state, &x, &rep, _state);
for(j=0; j<=sn-1; j++)
{
if( ae_fp_greater(ae_fabs(tx.ptr.p_double[j]-x.ptr.p_double[j], _state),eps)||(ae_fp_less(x.ptr.p_double[j],db.ptr.p_double[j])||ae_fp_greater(x.ptr.p_double[j],ub.ptr.p_double[j])) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Function to test: 'MinQPCreate', 'MinQPSetLinearTerm', 'MinQPSetQuadraticTerm',
'MinQPSetOrigin', 'MinQPSetStartingPoint', 'MinQPOptimize', 'MinQPResults'.
Test problem:
A = positive-definite matrix, obtained by 'SPDMatrixRndCond' function
b <> 0
without bounds
random start point
dimension - from 1 to 5.
*************************************************************************/
ae_bool functest1(ae_state *_state)
{
ae_frame _frame_block;
minqpstate state;
ae_int_t nexp;
ae_int_t msn;
ae_int_t sn;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_matrix a;
ae_vector ub;
ae_vector db;
ae_vector x;
ae_vector tx;
ae_vector stx;
ae_vector xori;
ae_vector xoric;
minqpreport rep;
double eps;
ae_vector b;
ae_int_t c2;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&state, 0, sizeof(state));
memset(&a, 0, sizeof(a));
memset(&ub, 0, sizeof(ub));
memset(&db, 0, sizeof(db));
memset(&x, 0, sizeof(x));
memset(&tx, 0, sizeof(tx));
memset(&stx, 0, sizeof(stx));
memset(&xori, 0, sizeof(xori));
memset(&xoric, 0, sizeof(xoric));
memset(&rep, 0, sizeof(rep));
memset(&b, 0, sizeof(b));
_minqpstate_init(&state, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ub, 0, DT_REAL, _state, ae_true);
ae_vector_init(&db, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&stx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xori, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xoric, 0, DT_REAL, _state, ae_true);
_minqpreport_init(&rep, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
eps = 0.001;
msn = 5;
c2 = 1000;
nexp = 1000;
for(sn=1; sn<=msn; sn++)
{
ae_vector_set_length(&b, sn, _state);
ae_vector_set_length(&tx, sn, _state);
ae_vector_set_length(&xori, sn, _state);
ae_vector_set_length(&xoric, sn, _state);
ae_vector_set_length(&stx, sn, _state);
for(i=0; i<=nexp; i++)
{
/*
*create simmetric matrix 'A'
*/
spdmatrixrndcond(sn, ae_exp(ae_randomreal(_state)*ae_log((double)(c2), _state), _state), &a, _state);
minqpcreate(sn, &state, _state);
testminqpunit_setrandomalgobc(&state, _state);
minqpsetquadraticterm(&state, &a, ae_false, _state);
for(j=0; j<=sn-1; j++)
{
xoric.ptr.p_double[j] = 2*ae_randomreal(_state)-1;
}
/*
*create linear part
*/
for(j=0; j<=sn-1; j++)
{
b.ptr.p_double[j] = (double)(0);
for(k=0; k<=sn-1; k++)
{
b.ptr.p_double[j] = b.ptr.p_double[j]-xoric.ptr.p_double[k]*a.ptr.pp_double[k][j];
}
}
minqpsetlinearterm(&state, &b, _state);
/*
*initialization for shifting
*initial value for 'XORi'
*and searching true results
*/
for(j=0; j<=sn-1; j++)
{
xori.ptr.p_double[j] = 2*ae_randomreal(_state)-1;
tx.ptr.p_double[j] = xori.ptr.p_double[j]+xoric.ptr.p_double[j];
}
minqpsetorigin(&state, &xori, _state);
/*
*initialization for starting point
*/
for(j=0; j<=sn-1; j++)
{
stx.ptr.p_double[j] = 2*ae_randomreal(_state)-1;
}
minqpsetstartingpoint(&state, &stx, _state);
/*
*optimize and get result
*/
minqpoptimize(&state, _state);
minqpresults(&state, &x, &rep, _state);
for(j=0; j<=sn-1; j++)
{
if( ae_fp_greater(ae_fabs(tx.ptr.p_double[j]-x.ptr.p_double[j], _state),eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Function to test: 'MinQPCreate', 'MinQPSetLinearTerm', 'MinQPSetQuadraticTerm',
'MinQPSetBC', 'MinQPSetOrigin', 'MinQPSetStartingPoint', 'MinQPOptimize',
'MinQPResults'.
Test problem:
A = positive-definite matrix, obtained by 'SPDMatrixRndCond' function
b <> 0
boundary constraints
random start point
dimension - from 1 to 5.
*************************************************************************/
ae_bool functest2(ae_state *_state)
{
ae_frame _frame_block;
minqpstate state;
ae_int_t nexp;
ae_int_t msn;
ae_int_t sn;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_matrix a;
ae_vector ub;
ae_vector db;
ae_vector x;
ae_vector tmpx;
double maxstb;
ae_vector stx;
ae_vector xori;
ae_vector xoric;
ae_int_t infd;
minqpreport rep;
double maxnb;
double minnb;
double eps;
ae_vector b;
ae_vector g;
ae_vector c;
ae_vector y0;
ae_vector y1;
ae_int_t c2;
double anti;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&state, 0, sizeof(state));
memset(&a, 0, sizeof(a));
memset(&ub, 0, sizeof(ub));
memset(&db, 0, sizeof(db));
memset(&x, 0, sizeof(x));
memset(&tmpx, 0, sizeof(tmpx));
memset(&stx, 0, sizeof(stx));
memset(&xori, 0, sizeof(xori));
memset(&xoric, 0, sizeof(xoric));
memset(&rep, 0, sizeof(rep));
memset(&b, 0, sizeof(b));
memset(&g, 0, sizeof(g));
memset(&c, 0, sizeof(c));
memset(&y0, 0, sizeof(y0));
memset(&y1, 0, sizeof(y1));
_minqpstate_init(&state, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ub, 0, DT_REAL, _state, ae_true);
ae_vector_init(&db, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmpx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&stx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xori, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xoric, 0, DT_REAL, _state, ae_true);
_minqpreport_init(&rep, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&g, 0, DT_REAL, _state, ae_true);
ae_vector_init(&c, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y1, 0, DT_REAL, _state, ae_true);
eps = 0.001;
msn = 5;
c2 = 1000;
maxstb = (double)(10);
nexp = 1000;
maxnb = (double)(1000);
minnb = (double)(-1000);
for(sn=1; sn<=msn; sn++)
{
ae_vector_set_length(&tmpx, sn, _state);
ae_vector_set_length(&b, sn, _state);
ae_vector_set_length(&c, sn, _state);
ae_vector_set_length(&g, sn, _state);
ae_vector_set_length(&xori, sn, _state);
ae_vector_set_length(&xoric, sn, _state);
ae_vector_set_length(&stx, sn, _state);
ae_vector_set_length(&db, sn, _state);
ae_vector_set_length(&ub, sn, _state);
ae_vector_set_length(&y0, sn, _state);
ae_vector_set_length(&y1, sn, _state);
for(i=0; i<=nexp; i++)
{
/*
*create simmetric matrix 'A'
*/
spdmatrixrndcond(sn, ae_exp(ae_randomreal(_state)*ae_log((double)(c2), _state), _state), &a, _state);
minqpcreate(sn, &state, _state);
testminqpunit_setrandomalgobc(&state, _state);
minqpsetquadraticterm(&state, &a, ae_false, _state);
for(j=0; j<=sn-1; j++)
{
xoric.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb;
}
/*
*create linear part
*/
for(j=0; j<=sn-1; j++)
{
b.ptr.p_double[j] = (double)(0);
for(k=0; k<=sn-1; k++)
{
b.ptr.p_double[j] = b.ptr.p_double[j]-xoric.ptr.p_double[k]*a.ptr.pp_double[k][j];
}
}
minqpsetlinearterm(&state, &b, _state);
for(j=0; j<=sn-1; j++)
{
infd = ae_randominteger(4, _state);
if( infd==0 )
{
db.ptr.p_double[j] = _state->v_neginf;
ub.ptr.p_double[j] = _state->v_posinf;
}
else
{
if( infd==1 )
{
db.ptr.p_double[j] = _state->v_neginf;
ub.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb;
}
else
{
if( infd==2 )
{
db.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb;
ub.ptr.p_double[j] = _state->v_posinf;
}
else
{
db.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb;
ub.ptr.p_double[j] = db.ptr.p_double[j]+maxstb*ae_randomreal(_state)+0.01;
}
}
}
}
minqpsetbc(&state, &db, &ub, _state);
/*
*initialization for shifting
*initial value for 'XORi'
*and searching true results
*/
for(j=0; j<=sn-1; j++)
{
xori.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb;
}
minqpsetorigin(&state, &xori, _state);
for(j=0; j<=sn-1; j++)
{
c.ptr.p_double[j] = (double)(0);
for(k=0; k<=sn-1; k++)
{
c.ptr.p_double[j] = c.ptr.p_double[j]-xori.ptr.p_double[k]*a.ptr.pp_double[k][j];
}
}
/*
*initialization for starting point
*/
for(j=0; j<=sn-1; j++)
{
stx.ptr.p_double[j] = (maxnb-minnb)*ae_randomreal(_state)+minnb;
}
minqpsetstartingpoint(&state, &stx, _state);
/*
*optimize and get result
*/
minqpoptimize(&state, _state);
minqpresults(&state, &x, &rep, _state);
rmatrixmv(sn, sn, &a, 0, 0, 0, &x, 0, &y0, 0, _state);
for(j=0; j<=sn-1; j++)
{
g.ptr.p_double[j] = y0.ptr.p_double[j]+c.ptr.p_double[j]+b.ptr.p_double[j];
}
anti = testminqpunit_projectedantigradnorm(sn, &x, &g, &db, &ub, _state);
for(j=0; j<=sn-1; j++)
{
if( ae_fp_greater(ae_fabs(anti, _state),eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
ConsoleTest.
*************************************************************************/
ae_bool consoletest(ae_state *_state)
{
ae_frame _frame_block;
minqpstate state;
ae_int_t nexp;
ae_int_t msn;
ae_int_t sn;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_matrix a;
ae_vector ub;
ae_vector db;
ae_vector x;
ae_vector stx;
ae_vector xori;
ae_vector xoric;
minqpreport rep;
double eps;
ae_vector b;
ae_vector g;
ae_vector y0;
ae_vector y1;
double c;
double anti;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&state, 0, sizeof(state));
memset(&a, 0, sizeof(a));
memset(&ub, 0, sizeof(ub));
memset(&db, 0, sizeof(db));
memset(&x, 0, sizeof(x));
memset(&stx, 0, sizeof(stx));
memset(&xori, 0, sizeof(xori));
memset(&xoric, 0, sizeof(xoric));
memset(&rep, 0, sizeof(rep));
memset(&b, 0, sizeof(b));
memset(&g, 0, sizeof(g));
memset(&y0, 0, sizeof(y0));
memset(&y1, 0, sizeof(y1));
_minqpstate_init(&state, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ub, 0, DT_REAL, _state, ae_true);
ae_vector_init(&db, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&stx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xori, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xoric, 0, DT_REAL, _state, ae_true);
_minqpreport_init(&rep, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&g, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y1, 0, DT_REAL, _state, ae_true);
eps = 0.001;
msn = 2;
nexp = 0;
for(sn=2; sn<=msn; sn++)
{
ae_vector_set_length(&b, sn, _state);
ae_vector_set_length(&g, sn, _state);
ae_vector_set_length(&xori, sn, _state);
ae_vector_set_length(&xoric, sn, _state);
ae_vector_set_length(&stx, sn, _state);
ae_vector_set_length(&db, sn, _state);
ae_vector_set_length(&ub, sn, _state);
ae_vector_set_length(&y0, sn, _state);
ae_vector_set_length(&y1, sn, _state);
for(i=0; i<=nexp; i++)
{
/*
*create simmetric matrix 'A'
*/
ae_matrix_set_length(&a, sn, sn, _state);
for(j=0; j<=sn-1; j++)
{
for(k=0; k<=sn-1; k++)
{
if( j==k )
{
a.ptr.pp_double[j][k] = (double)(1);
}
else
{
a.ptr.pp_double[j][k] = (double)(0);
}
printf("%0.5f ",
(double)(a.ptr.pp_double[j][k]));
}
printf("\n");
}
minqpcreate(sn, &state, _state);
testminqpunit_setrandomalgobc(&state, _state);
minqpsetquadraticterm(&state, &a, ae_false, _state);
for(j=0; j<=sn-1; j++)
{
xoric.ptr.p_double[j] = (double)(1);
printf("XoriC=%0.5f \n",
(double)(xoric.ptr.p_double[j]));
}
/*
*create linear part
*/
for(j=0; j<=sn-1; j++)
{
b.ptr.p_double[j] = (double)(0);
for(k=0; k<=sn-1; k++)
{
b.ptr.p_double[j] = b.ptr.p_double[j]-xoric.ptr.p_double[k]*a.ptr.pp_double[k][j];
}
printf("B[%0d]=%0.5f\n",
(int)(j),
(double)(b.ptr.p_double[j]));
}
minqpsetlinearterm(&state, &b, _state);
for(j=0; j<=sn-1; j++)
{
db.ptr.p_double[j] = (double)(10);
ub.ptr.p_double[j] = (double)(20);
}
minqpsetbc(&state, &db, &ub, _state);
/*
*initialization for shifting
*initial value for 'XORi'
*and searching true results
*/
for(j=0; j<=sn-1; j++)
{
xori.ptr.p_double[j] = (double)(1);
}
minqpsetorigin(&state, &xori, _state);
/*
*optimize and get result
*/
minqpoptimize(&state, _state);
minqpresults(&state, &x, &rep, _state);
rmatrixmv(sn, sn, &a, 0, 0, 0, &x, 0, &y0, 0, _state);
rmatrixmv(sn, sn, &a, 0, 0, 0, &x, 0, &y1, 0, _state);
for(j=0; j<=sn-1; j++)
{
c = (double)(0);
for(k=0; k<=sn-1; k++)
{
c = c-xori.ptr.p_double[k]*a.ptr.pp_double[k][j];
}
g.ptr.p_double[j] = b.ptr.p_double[j]+c+y0.ptr.p_double[j]+y1.ptr.p_double[j];
}
anti = testminqpunit_projectedantigradnorm(sn, &x, &b, &db, &ub, _state);
printf("SN=%0d\n",
(int)(sn));
printf("NEXP=%0d\n",
(int)(i));
printf("TermType=%0d\n",
(int)(rep.terminationtype));
for(j=0; j<=sn-1; j++)
{
printf("X[%0d]=%0.5f;\n",
(int)(j),
(double)(x.ptr.p_double[j]));
printf("DB[%0d]=%0.5f; UB[%0d]=%0.5f\n",
(int)(j),
(double)(db.ptr.p_double[j]),
(int)(j),
(double)(ub.ptr.p_double[j]));
printf("XORi[%0d]=%0.5f; XORiC[%0d]=%0.5f;\n",
(int)(j),
(double)(xori.ptr.p_double[j]),
(int)(j),
(double)(xoric.ptr.p_double[j]));
printf("Anti[%0d]=%0.5f;\n",
(int)(j),
(double)(anti));
if( ae_fp_greater(ae_fabs(anti, _state),eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function performs tests specific for QuickQP solver
Returns True on failure.
*************************************************************************/
ae_bool quickqptests(ae_state *_state)
{
ae_frame _frame_block;
minqpstate state;
minqpreport rep;
ae_int_t n;
ae_int_t pass;
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
double g;
double gnorm;
ae_bool flag;
ae_int_t origintype;
ae_int_t scaletype;
ae_bool isupper;
ae_bool issparse;
ae_int_t itscnt;
ae_vector nlist;
ae_int_t nidx;
ae_matrix a;
ae_matrix za;
ae_matrix fulla;
ae_matrix halfa;
ae_matrix c;
sparsematrix sa;
ae_vector ct;
ae_vector b;
ae_vector zb;
ae_vector bndl;
ae_vector bndu;
ae_vector x0;
ae_vector x1;
ae_vector xend0;
ae_vector xend1;
ae_vector xori;
ae_vector xz;
ae_vector s;
double eps;
hqrndstate rs;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&nlist, 0, sizeof(nlist));
memset(&a, 0, sizeof(a));
memset(&za, 0, sizeof(za));
memset(&fulla, 0, sizeof(fulla));
memset(&halfa, 0, sizeof(halfa));
memset(&c, 0, sizeof(c));
memset(&sa, 0, sizeof(sa));
memset(&ct, 0, sizeof(ct));
memset(&b, 0, sizeof(b));
memset(&zb, 0, sizeof(zb));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&xend0, 0, sizeof(xend0));
memset(&xend1, 0, sizeof(xend1));
memset(&xori, 0, sizeof(xori));
memset(&xz, 0, sizeof(xz));
memset(&s, 0, sizeof(s));
memset(&rs, 0, sizeof(rs));
_minqpstate_init(&state, _state, ae_true);
_minqpreport_init(&rep, _state, ae_true);
ae_vector_init(&nlist, 0, DT_INT, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&za, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&fulla, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&halfa, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
_sparsematrix_init(&sa, _state, ae_true);
ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&zb, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xend0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xend1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xori, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xz, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
result = ae_false;
hqrndrandomize(&rs, _state);
/*
* Convex unconstrained test:
* * N dimensions
* * positive-definite A
* * algorithm randomly choose dense or sparse A, and for
* sparse matrix it randomly choose format.
* * random B with normal entries
* * initial point is random, feasible
* * random origin (zero or non-zero) and scale (unit or
* non-unit) are generated
*/
eps = 1.0E-5;
for(n=1; n<=10; n++)
{
for(pass=1; pass<=10; pass++)
{
/*
* Generate problem
*/
origintype = hqrnduniformi(&rs, 2, _state);
scaletype = hqrnduniformi(&rs, 2, _state);
isupper = ae_fp_less(hqrnduniformr(&rs, _state),0.5);
issparse = ae_fp_less(hqrnduniformr(&rs, _state),0.5);
spdmatrixrndcond(n, 1.0E3, &fulla, _state);
ae_matrix_set_length(&halfa, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (j>=i&&isupper)||(j<=i&&!isupper) )
{
halfa.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j];
}
else
{
halfa.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5;
}
}
}
testminqpunit_densetosparse(&halfa, n, &sa, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xori, n, _state);
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
if( origintype==0 )
{
xori.ptr.p_double[i] = (double)(0);
}
else
{
xori.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
if( scaletype==0 )
{
s.ptr.p_double[i] = (double)(1);
}
else
{
s.ptr.p_double[i] = ae_exp(0.5*hqrndnormal(&rs, _state), _state);
}
}
/*
* Solve problem
*/
minqpcreate(n, &state, _state);
minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, 0, ae_fp_greater(hqrnduniformr(&rs, _state),0.5), _state);
minqpsetlinearterm(&state, &b, _state);
if( issparse )
{
minqpsetquadratictermsparse(&state, &sa, isupper, _state);
}
else
{
minqpsetquadraticterm(&state, &halfa, isupper, _state);
}
if( origintype!=0 )
{
minqpsetorigin(&state, &xori, _state);
}
if( scaletype!=0 )
{
minqpsetscale(&state, &s, _state);
}
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:5685");
if( rep.terminationtype<=0 )
{
ae_frame_leave(_state);
return result;
}
/*
* Test - calculate constrained gradient at solution,
* check its norm.
*/
gnorm = 0.0;
for(i=0; i<=n-1; i++)
{
g = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
g = g+fulla.ptr.pp_double[i][j]*(x1.ptr.p_double[j]-xori.ptr.p_double[j]);
}
gnorm = gnorm+ae_sqr(g, _state);
}
gnorm = ae_sqrt(gnorm, _state);
ae_set_error_flag(&result, ae_fp_greater(gnorm,eps), __FILE__, __LINE__, "testminqpunit.ap:5703");
}
}
/*
* Convex test:
* * N dimensions
* * random number (0..N) of random boundary constraints
* * positive-definite A
* * algorithm randomly choose dense or sparse A, and for
* sparse matrix it randomly choose format.
* * random B with normal entries
* * initial point is random, feasible
* * random origin (zero or non-zero) and scale (unit or
* non-unit) are generated
*/
eps = 1.0E-5;
for(n=1; n<=10; n++)
{
for(pass=1; pass<=10; pass++)
{
/*
* Generate problem
*/
origintype = hqrnduniformi(&rs, 2, _state);
scaletype = hqrnduniformi(&rs, 2, _state);
isupper = ae_fp_less(hqrnduniformr(&rs, _state),0.5);
issparse = ae_fp_less(hqrnduniformr(&rs, _state),0.5);
spdmatrixrndcond(n, 1.0E3, &fulla, _state);
ae_matrix_set_length(&halfa, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (j>=i&&isupper)||(j<=i&&!isupper) )
{
halfa.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j];
}
else
{
halfa.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5;
}
}
}
testminqpunit_densetosparse(&halfa, n, &sa, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xori, n, _state);
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
bndl.ptr.p_double[i] = _state->v_neginf;
bndu.ptr.p_double[i] = _state->v_posinf;
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
if( origintype==0 )
{
xori.ptr.p_double[i] = (double)(0);
}
else
{
xori.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
if( scaletype==0 )
{
s.ptr.p_double[i] = (double)(1);
}
else
{
s.ptr.p_double[i] = ae_exp(0.5*hqrndnormal(&rs, _state), _state);
}
j = hqrnduniformi(&rs, 5, _state);
if( j==0 )
{
bndl.ptr.p_double[i] = (double)(0);
x0.ptr.p_double[i] = ae_fabs(x0.ptr.p_double[i], _state);
}
if( j==1 )
{
bndu.ptr.p_double[i] = (double)(0);
x0.ptr.p_double[i] = -ae_fabs(x0.ptr.p_double[i], _state);
}
if( j==2 )
{
bndl.ptr.p_double[i] = hqrndnormal(&rs, _state);
bndu.ptr.p_double[i] = bndl.ptr.p_double[i];
x0.ptr.p_double[i] = bndl.ptr.p_double[i];
}
if( j==3 )
{
bndl.ptr.p_double[i] = -0.1;
bndu.ptr.p_double[i] = 0.1;
x0.ptr.p_double[i] = 0.2*hqrnduniformr(&rs, _state)-0.1;
}
}
/*
* Solve problem
*/
minqpcreate(n, &state, _state);
minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, 0, ae_fp_greater(hqrnduniformr(&rs, _state),0.5), _state);
minqpsetlinearterm(&state, &b, _state);
if( issparse )
{
minqpsetquadratictermsparse(&state, &sa, isupper, _state);
}
else
{
minqpsetquadraticterm(&state, &halfa, isupper, _state);
}
if( origintype!=0 )
{
minqpsetorigin(&state, &xori, _state);
}
if( scaletype!=0 )
{
minqpsetscale(&state, &s, _state);
}
minqpsetbc(&state, &bndl, &bndu, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:5800");
if( rep.terminationtype<=0 )
{
ae_frame_leave(_state);
return result;
}
/*
* Test - calculate constrained gradient at solution,
* check its norm.
*/
gnorm = 0.0;
for(i=0; i<=n-1; i++)
{
g = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
g = g+fulla.ptr.pp_double[i][j]*(x1.ptr.p_double[j]-xori.ptr.p_double[j]);
}
if( ae_fp_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i])&&ae_fp_greater(g,(double)(0)) )
{
g = (double)(0);
}
if( ae_fp_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i])&&ae_fp_less(g,(double)(0)) )
{
g = (double)(0);
}
gnorm = gnorm+ae_sqr(g, _state);
ae_set_error_flag(&result, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:5820");
ae_set_error_flag(&result, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:5821");
}
gnorm = ae_sqrt(gnorm, _state);
ae_set_error_flag(&result, ae_fp_greater(gnorm,eps), __FILE__, __LINE__, "testminqpunit.ap:5824");
}
}
/*
* Strongly non-convex test:
* * N dimensions, N>=2
* * box constraints, x[i] in [-1,+1]
* * A = A0-0.5*I, where A0 is SPD with unit norm and smallest
* singular value equal to 1.0E-3, I is identity matrix
* * random B with normal entries
* * initial point is random, feasible
*
* We perform two tests:
* * unconstrained problem must be recognized as unbounded
* * constrained problem can be successfully solved
*
* NOTE: it is important to have N>=2, because formula for A
* can be applied only to matrix with at least two
* singular values
*/
eps = 1.0E-5;
for(n=2; n<=10; n++)
{
for(pass=1; pass<=10; pass++)
{
/*
* Generate problem
*/
spdmatrixrndcond(n, 1.0E3, &fulla, _state);
for(i=0; i<=n-1; i++)
{
fulla.ptr.pp_double[i][i] = fulla.ptr.pp_double[i][i]-0.5;
}
isupper = ae_fp_less(hqrnduniformr(&rs, _state),0.5);
ae_matrix_set_length(&halfa, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (j>=i&&isupper)||(j<=i&&!isupper) )
{
halfa.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j];
}
else
{
halfa.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5;
}
}
}
testminqpunit_densetosparse(&halfa, n, &sa, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
bndl.ptr.p_double[i] = (double)(-1);
bndu.ptr.p_double[i] = (double)(1);
x0.ptr.p_double[i] = 2*hqrnduniformr(&rs, _state)-1;
}
/*
* Solve problem:
* * without constraints we expect failure
* * with constraints algorithm must succeed
*/
minqpcreate(n, &state, _state);
minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, 0, ae_fp_greater(hqrnduniformr(&rs, _state),0.5), _state);
minqpsetlinearterm(&state, &b, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minqpsetquadraticterm(&state, &halfa, isupper, _state);
}
else
{
minqpsetquadratictermsparse(&state, &sa, isupper, _state);
}
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype!=-4, __FILE__, __LINE__, "testminqpunit.ap:5889");
minqpsetbc(&state, &bndl, &bndu, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:5893");
if( rep.terminationtype<=0 )
{
ae_frame_leave(_state);
return result;
}
/*
* Test - calculate constrained gradient at solution,
* check its norm.
*/
gnorm = 0.0;
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&fulla.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1));
g = v+b.ptr.p_double[i];
if( ae_fp_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i])&&ae_fp_greater(g,(double)(0)) )
{
g = (double)(0);
}
if( ae_fp_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i])&&ae_fp_less(g,(double)(0)) )
{
g = (double)(0);
}
gnorm = gnorm+ae_sqr(g, _state);
ae_set_error_flag(&result, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:5912");
ae_set_error_flag(&result, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:5913");
}
gnorm = ae_sqrt(gnorm, _state);
ae_set_error_flag(&result, ae_fp_greater(gnorm,eps), __FILE__, __LINE__, "testminqpunit.ap:5916");
}
}
/*
* Basic semi-definite test:
* * N dimensions, N>=2
* * box constraints, x[i] in [-1,+1]
* [ 1 1 ... 1 1 ]
* * A = [ ... ... ... ], with one (random) diagonal entry set to -1
* [ 1 1 ... 1 1 ]
* * random B with normal entries
* * initial point is random, feasible
*
* We perform two tests:
* * unconstrained problem must be recognized as unbounded
* * constrained problem must be recognized as bounded and
* successfully solved
*
* Both problems require subtle programming when we work
* with semidefinite QP.
*
* NOTE: unlike BLEIC-QP algorthm, QQP may detect unboundedness
* of the problem when started from any x0, with any b.
* BLEIC-based solver requires carefully chosen x0 and b
* to find direction of zero curvature, but this solver
* can find it from any point.
*/
ae_vector_set_length(&nlist, 12, _state);
nlist.ptr.p_int[0] = 2;
nlist.ptr.p_int[1] = 3;
nlist.ptr.p_int[2] = 4;
nlist.ptr.p_int[3] = 5;
nlist.ptr.p_int[4] = 6;
nlist.ptr.p_int[5] = 7;
nlist.ptr.p_int[6] = 8;
nlist.ptr.p_int[7] = 9;
nlist.ptr.p_int[8] = 10;
nlist.ptr.p_int[9] = 20;
nlist.ptr.p_int[10] = 40;
nlist.ptr.p_int[11] = 80;
eps = 1.0E-5;
for(nidx=0; nidx<=nlist.cnt-1; nidx++)
{
for(pass=1; pass<=10; pass++)
{
/*
* Generate problem
*/
n = nlist.ptr.p_int[nidx];
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
do
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
while(ae_fp_eq(b.ptr.p_double[i],(double)(0)));
bndl.ptr.p_double[i] = (double)(-1);
bndu.ptr.p_double[i] = (double)(1);
x0.ptr.p_double[i] = 2*hqrnduniformr(&rs, _state)-1;
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 1.0;
}
}
j = hqrnduniformi(&rs, n, _state);
a.ptr.pp_double[j][j] = -1.0;
testminqpunit_densetosparse(&a, n, &sa, _state);
/*
* Solve problem:
* * without constraints we expect failure
* * with constraints algorithm must succeed
*/
minqpcreate(n, &state, _state);
minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, 0, ae_fp_greater(hqrnduniformr(&rs, _state),0.5), _state);
minqpsetlinearterm(&state, &b, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minqpsetquadraticterm(&state, &a, ae_true, _state);
}
else
{
minqpsetquadratictermsparse(&state, &sa, ae_true, _state);
}
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype!=-4, __FILE__, __LINE__, "testminqpunit.ap:5999");
minqpsetbc(&state, &bndl, &bndu, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:6003");
if( rep.terminationtype<=0 )
{
ae_frame_leave(_state);
return result;
}
/*
* Test - calculate constrained gradient at solution,
* check its norm.
*/
gnorm = 0.0;
for(i=0; i<=n-1; i++)
{
g = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
g = g+a.ptr.pp_double[i][j]*x1.ptr.p_double[j];
}
if( ae_fp_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i])&&ae_fp_greater(g,(double)(0)) )
{
g = (double)(0);
}
if( ae_fp_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i])&&ae_fp_less(g,(double)(0)) )
{
g = (double)(0);
}
gnorm = gnorm+ae_sqr(g, _state);
ae_set_error_flag(&result, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6024");
ae_set_error_flag(&result, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6025");
}
gnorm = ae_sqrt(gnorm, _state);
ae_set_error_flag(&result, ae_fp_greater(gnorm,eps), __FILE__, __LINE__, "testminqpunit.ap:6028");
}
}
/*
* Linear (zero-quadratic) test:
* * N dimensions, N>=1
* * box constraints, x[i] in [-1,+1]
* * A = 0
* * random B with normal entries
* * initial point is random, feasible
*
* We perform two tests:
* * unconstrained problem must be recognized as unbounded
* * constrained problem can be successfully solved
*
* NOTE: we may explicitly set zero A, or assume that by
* default it is zero. During test we will try both
* ways.
*/
eps = 1.0E-5;
for(n=1; n<=10; n++)
{
for(pass=1; pass<=10; pass++)
{
/*
* Generate problem
*/
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
do
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
while(ae_fp_eq(b.ptr.p_double[i],(double)(0)));
bndl.ptr.p_double[i] = (double)(-1);
bndu.ptr.p_double[i] = (double)(1);
x0.ptr.p_double[i] = 2*hqrnduniformr(&rs, _state)-1;
}
/*
* Solve problem:
* * without constraints we expect failure
* * with constraints algorithm must succeed
*/
minqpcreate(n, &state, _state);
minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, 0, ae_fp_greater(hqrnduniformr(&rs, _state),0.5), _state);
minqpsetlinearterm(&state, &b, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
minqpsetquadraticterm(&state, &a, ae_true, _state);
}
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype!=-4, __FILE__, __LINE__, "testminqpunit.ap:6086");
minqpsetbc(&state, &bndl, &bndu, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:6090");
if( rep.terminationtype<=0 )
{
ae_frame_leave(_state);
return result;
}
/*
* Test - calculate constrained gradient at solution,
* check its norm.
*/
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(&result, ae_fp_greater(b.ptr.p_double[i],(double)(0))&&ae_fp_greater(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6100");
ae_set_error_flag(&result, ae_fp_less(b.ptr.p_double[i],(double)(0))&&ae_fp_less(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6101");
}
}
}
/*
* Test for Newton phase of QQP algorithm - we test that Newton
* phase can find good solution within one step. In order to do
* so we:
* * solve convex QP problem (dense or sparse)
* * with K<=N equality-only constraints ai=x=bi
* * with number of outer iterations limited to just 1
* * and with CG phase turned off (we modify internal structures
* of the QQP solver in order to make it)
*/
eps = 1.0E-5;
for(pass=1; pass<=10; pass++)
{
/*
* Generate problem
*/
n = 50+hqrnduniformi(&rs, 51, _state);
spdmatrixrndcond(n, 1.0E3, &a, _state);
testminqpunit_densetosparse(&a, n, &sa, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
bndl.ptr.p_double[i] = _state->v_neginf;
bndu.ptr.p_double[i] = _state->v_posinf;
}
else
{
bndl.ptr.p_double[i] = hqrndnormal(&rs, _state);
bndu.ptr.p_double[i] = bndl.ptr.p_double[i];
}
}
/*
* Solve problem
*
* NOTE: we modify internal structures of QQP solver in order
* to deactivate CG phase
*/
minqpcreate(n, &state, _state);
minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, 1, ae_true, _state);
state.qqpsettingsuser.cgphase = ae_false;
minqpsetlinearterm(&state, &b, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minqpsetquadraticterm(&state, &a, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), _state);
}
else
{
minqpsetquadratictermsparse(&state, &sa, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), _state);
}
minqpsetbc(&state, &bndl, &bndu, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:6161");
if( rep.terminationtype<=0 )
{
ae_frame_leave(_state);
return result;
}
/*
* Test - calculate constrained gradient at solution,
* check its norm.
*/
gnorm = 0.0;
for(i=0; i<=n-1; i++)
{
g = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
g = g+a.ptr.pp_double[i][j]*x1.ptr.p_double[j];
}
if( ae_fp_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i])&&ae_fp_greater(g,(double)(0)) )
{
g = (double)(0);
}
if( ae_fp_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i])&&ae_fp_less(g,(double)(0)) )
{
g = (double)(0);
}
gnorm = gnorm+ae_sqr(g, _state);
ae_set_error_flag(&result, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6181");
ae_set_error_flag(&result, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6182");
}
gnorm = ae_sqrt(gnorm, _state);
ae_set_error_flag(&result, ae_fp_greater(gnorm,eps), __FILE__, __LINE__, "testminqpunit.ap:6185");
}
/*
* Test for Newton phase of QQP algorithm - we test that Newton
* updates work correctly, i.e. that CNewtonUpdate() internal
* function correctly updates inverse Hessian matrix.
*
* To test it we:
* * solve ill conditioned convex QP problem
* * with unconstrained solution XZ whose components are within [-0.5,+0.5]
* * with one inequality constraint X[k]>=5
* * with initial point such that:
* * X0[i] = 100 for i<>k
* * X0[k] = 5+1.0E-5
* * with number of outer iterations limited to just 1
* * and with CG phase turned off (we modify internal structures
* of the QQP solver in order to make it)
*
* The idea is that single Newton step is not enough to find solution,
* but with just one update we can move exactly to the solution.
*
* We perform two tests:
* * first one with State.QQP.NewtMaxIts set to 1, in order to
* make sure that algorithm fails with just one iteration
* * second one with State.QQP.NewtMaxIts set to 2, in order to
* make sure that algorithm converges when it can perform update
*/
eps = 1.0E-5;
for(pass=1; pass<=10; pass++)
{
/*
* Generate problem
*/
n = 20+hqrnduniformi(&rs, 20, _state);
spdmatrixrndcond(n, 1.0E5, &a, _state);
testminqpunit_densetosparse(&a, n, &sa, _state);
sparseconverttocrs(&sa, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xz, n, _state);
for(i=0; i<=n-1; i++)
{
xz.ptr.p_double[i] = hqrnduniformr(&rs, _state)-0.5;
x0.ptr.p_double[i] = (double)(100);
bndl.ptr.p_double[i] = _state->v_neginf;
bndu.ptr.p_double[i] = _state->v_posinf;
}
k = hqrnduniformi(&rs, n, _state);
x0.ptr.p_double[k] = 5.00001;
bndl.ptr.p_double[k] = 5.0;
sparsemv(&sa, &xz, &b, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = -b.ptr.p_double[i];
}
/*
* Create solver
*/
minqpcreate(n, &state, _state);
minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, 1, ae_true, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetquadraticterm(&state, &a, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), _state);
minqpsetbc(&state, &bndl, &bndu, _state);
minqpsetstartingpoint(&state, &x0, _state);
/*
* Solve problem. First time, with no Newton updates.
* It must fail.
*
* NOTE: we modify internal structures of QQP solver in order
* to deactivate CG phase and turn off Newton updates.
*/
state.qqpsettingsuser.cgphase = ae_false;
state.qqpsettingsuser.cnphase = ae_true;
state.qqpsettingsuser.cnmaxupdates = 0;
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:6264");
if( result )
{
ae_frame_leave(_state);
return result;
}
flag = ae_false;
testminqpunit_testbcgradandfeasibility(&a, &b, &bndl, &bndu, n, &x1, eps, &flag, _state);
ae_set_error_flag(&result, !flag, __FILE__, __LINE__, "testminqpunit.ap:6269");
/*
* Now with Newton updates - it must succeeed.
*/
state.qqpsettingsuser.cgphase = ae_false;
state.qqpsettingsuser.cnmaxupdates = n;
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:6278");
if( result )
{
ae_frame_leave(_state);
return result;
}
flag = ae_false;
testminqpunit_testbcgradandfeasibility(&a, &b, &bndl, &bndu, n, &x1, eps, &flag, _state);
ae_set_error_flag(&result, flag, __FILE__, __LINE__, "testminqpunit.ap:6283");
}
/*
* Check that problem with general constraints results in
* correct error code (-5 should be returned).
*/
ae_matrix_set_length(&c, 1, 3, _state);
ae_vector_set_length(&ct, 1, _state);
c.ptr.pp_double[0][0] = 1.0;
c.ptr.pp_double[0][1] = 1.0;
c.ptr.pp_double[0][2] = 2.0;
ct.ptr.p_int[0] = 0;
minqpcreate(2, &state, _state);
minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, 0, ae_fp_greater(hqrnduniformr(&rs, _state),0.5), _state);
minqpsetlc(&state, &c, &ct, 1, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype!=-5, __FILE__, __LINE__, "testminqpunit.ap:6301");
/*
* Test sparse functionality. QQP solver must perform
* same steps independently of matrix type (dense or sparse).
*
* We generate random unconstrained test problem and solve it
* twice - first time we solve dense version, second time -
* sparse version is solved.
*
* During this test we:
* * use stringent stopping criteria (one outer iteration)
* * turn off Newton phase of the algorithm to slow down
* convergence
*/
eps = 1.0E-3;
itscnt = 1;
n = 20;
isupper = ae_fp_greater(ae_randomreal(_state),0.5);
spdmatrixrndcond(n, 1.0E3, &za, _state);
sparsecreate(n, n, 0, &sa, _state);
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( j>=i&&isupper )
{
sparseset(&sa, i, j, za.ptr.pp_double[i][j], _state);
a.ptr.pp_double[i][j] = za.ptr.pp_double[i][j];
}
if( j<=i&&!isupper )
{
sparseset(&sa, i, j, za.ptr.pp_double[i][j], _state);
a.ptr.pp_double[i][j] = za.ptr.pp_double[i][j];
}
}
}
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = randomnormal(_state);
s.ptr.p_double[i] = ae_pow(10.0, randomnormal(_state)/10, _state);
}
minqpcreate(n, &state, _state);
minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, itscnt, ae_false, _state);
minqpsetscale(&state, &s, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetquadraticterm(&state, &a, isupper, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend0, &rep, _state);
minqpcreate(n, &state, _state);
minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, itscnt, ae_false, _state);
minqpsetscale(&state, &s, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetquadratictermsparse(&state, &sa, isupper, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend1, &rep, _state);
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(xend0.ptr.p_double[i]-xend1.ptr.p_double[i], _state),eps), __FILE__, __LINE__, "testminqpunit.ap:6419");
}
/*
* Test scale-invariance. QQP performs same steps on scaled and
* unscaled problems (assuming that scale of the variables is known).
*
* We generate random scale matrix S and random well-conditioned and
* well scaled matrix A. Then we solve two problems:
*
* (1) f = 0.5*x'*A*x+b'*x
* (identity scale matrix is used)
*
* and
*
* (2) f = 0.5*y'*(inv(S)*A*inv(S))*y + (inv(S)*b)'*y
* (scale matrix S is used)
*
* Solution process is started from X=0, we perform ItsCnt=1 outer
* iterations with Newton phase turned off (to slow down convergence;
* we want to prevent algorithm from converging to exact solution which
* is exactly same for both problems; the idea is to test that same
* intermediate tests are taken).
*
* As result, we must get S*x=y
*/
eps = 1.0E-3;
itscnt = 1;
n = 100;
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = ae_pow(10.0, randomnormal(_state)/10, _state);
}
spdmatrixrndcond(n, 1.0E3, &a, _state);
ae_matrix_set_length(&za, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
za.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]);
}
}
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&zb, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = randomnormal(_state);
zb.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i];
}
minqpcreate(n, &state, _state);
minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, itscnt, ae_false, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetquadraticterm(&state, &a, ae_true, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend0, &rep, _state);
minqpcreate(n, &state, _state);
minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, itscnt, ae_false, _state);
minqpsetlinearterm(&state, &zb, _state);
minqpsetquadraticterm(&state, &za, ae_true, _state);
minqpsetscale(&state, &s, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend1, &rep, _state);
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(s.ptr.p_double[i]*xend0.ptr.p_double[i]-xend1.ptr.p_double[i], _state),eps), __FILE__, __LINE__, "testminqpunit.ap:6476");
}
/*
* Test that QQP can efficiently use sparse matrices (i.e. it is
* not disguised version of some dense QP solver). In order to test
* it we create very large and very sparse problem (diagonal matrix
* with N=40.000) and perform 10 iterations of QQP solver.
*
* In case QP solver uses some form of dense linear algebra to solve
* this problem, it will take TOO much time to solve it. And we will
* notice it by EXTREME slowdown during testing.
*/
n = 40000;
sparsecreate(n, n, 0, &sa, _state);
for(i=0; i<=n-1; i++)
{
sparseset(&sa, i, i, ae_pow(10.0, -3*ae_randomreal(_state), _state), _state);
}
ae_vector_set_length(&b, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = randomnormal(_state);
}
minqpcreate(n, &state, _state);
minqpsetalgoquickqp(&state, 0.0, 0.0, 0.0, 10, ae_fp_greater(hqrnduniformr(&rs, _state),0.5), _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetquadratictermsparse(&state, &sa, ae_true, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend0, &rep, _state);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function performs tests specific for BLEIC solver
Returns True on error, False on success.
*************************************************************************/
ae_bool bleictests(ae_state *_state)
{
ae_frame _frame_block;
minqpstate state;
minqpreport rep;
ae_vector nlist;
ae_int_t nidx;
ae_matrix a;
ae_matrix za;
ae_matrix c;
ae_vector b;
ae_vector zb;
ae_vector bndl;
ae_vector bndu;
ae_vector s;
ae_vector x;
ae_vector ct;
sparsematrix sa;
ae_int_t n;
ae_vector x0;
ae_vector x1;
hqrndstate rs;
ae_int_t i;
ae_int_t j;
ae_int_t pass;
ae_vector xend0;
ae_vector xend1;
double eps;
double v;
double g;
double gnorm;
ae_int_t itscnt;
ae_bool isupper;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&nlist, 0, sizeof(nlist));
memset(&a, 0, sizeof(a));
memset(&za, 0, sizeof(za));
memset(&c, 0, sizeof(c));
memset(&b, 0, sizeof(b));
memset(&zb, 0, sizeof(zb));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(&s, 0, sizeof(s));
memset(&x, 0, sizeof(x));
memset(&ct, 0, sizeof(ct));
memset(&sa, 0, sizeof(sa));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&rs, 0, sizeof(rs));
memset(&xend0, 0, sizeof(xend0));
memset(&xend1, 0, sizeof(xend1));
_minqpstate_init(&state, _state, ae_true);
_minqpreport_init(&rep, _state, ae_true);
ae_vector_init(&nlist, 0, DT_INT, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&za, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&zb, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
_sparsematrix_init(&sa, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
ae_vector_init(&xend0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xend1, 0, DT_REAL, _state, ae_true);
result = ae_false;
hqrndrandomize(&rs, _state);
/*
* Test sparse functionality. BLEIC-based solver must perform
* same steps independently of matrix type (dense or sparse).
*
* We generate random unconstrained test problem and solve it
* twice - first time we solve dense version, second time -
* sparse version is solved.
*/
eps = 1.0E-3;
itscnt = 5;
n = 20;
isupper = ae_fp_greater(ae_randomreal(_state),0.5);
spdmatrixrndcond(n, 1.0E3, &za, _state);
sparsecreate(n, n, 0, &sa, _state);
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( j>=i&&isupper )
{
sparseset(&sa, i, j, za.ptr.pp_double[i][j], _state);
a.ptr.pp_double[i][j] = za.ptr.pp_double[i][j];
}
if( j<=i&&!isupper )
{
sparseset(&sa, i, j, za.ptr.pp_double[i][j], _state);
a.ptr.pp_double[i][j] = za.ptr.pp_double[i][j];
}
}
}
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = randomnormal(_state);
s.ptr.p_double[i] = ae_pow(10.0, randomnormal(_state)/10, _state);
}
minqpcreate(n, &state, _state);
minqpsetalgobleic(&state, 0.0, 0.0, 0.0, itscnt, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetquadraticterm(&state, &a, isupper, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend0, &rep, _state);
minqpcreate(n, &state, _state);
minqpsetalgobleic(&state, 0.0, 0.0, 0.0, itscnt, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetquadratictermsparse(&state, &sa, isupper, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend1, &rep, _state);
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(xend0.ptr.p_double[i]-xend1.ptr.p_double[i], _state),eps), __FILE__, __LINE__, "testminqpunit.ap:6591");
}
/*
* Test scale-invariance. BLEIC performs same steps on scaled and
* unscaled problems (assuming that scale of the variables is known).
*
* We generate random scale matrix S and random well-conditioned and
* well scaled matrix A. Then we solve two problems:
*
* (1) f = 0.5*x'*A*x+b'*x
* (identity scale matrix is used)
*
* and
*
* (2) f = 0.5*y'*(inv(S)*A*inv(S))*y + (inv(S)*b)'*y
* (scale matrix S is used)
*
* Solution process is started from X=0, we perform ItsCnt=5 steps.
* As result, we must get S*x=y
*/
eps = 1.0E-3;
itscnt = 5;
n = 20;
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = ae_pow(10.0, randomnormal(_state)/10, _state);
}
spdmatrixrndcond(n, 1.0E3, &a, _state);
ae_matrix_set_length(&za, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
za.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]);
}
}
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&zb, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = randomnormal(_state);
zb.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i];
}
minqpcreate(n, &state, _state);
minqpsetalgobleic(&state, 0.0, 0.0, 0.0, itscnt, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetquadraticterm(&state, &a, ae_true, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend0, &rep, _state);
minqpcreate(n, &state, _state);
minqpsetalgobleic(&state, 0.0, 0.0, 0.0, itscnt, _state);
minqpsetlinearterm(&state, &zb, _state);
minqpsetquadraticterm(&state, &za, ae_true, _state);
minqpsetscale(&state, &s, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend1, &rep, _state);
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(s.ptr.p_double[i]*xend0.ptr.p_double[i]-xend1.ptr.p_double[i], _state),eps), __FILE__, __LINE__, "testminqpunit.ap:6644");
}
/*
* Test that BLEIC can efficiently use sparse matrices (i.e. it is
* not disguised version of some dense QP solver). In order to test
* it we create very large and very sparse problem (diagonal matrix
* with N=20.000) and perform 10 iterations of BLEIC-based QP solver.
*
* In case QP solver uses some form of dense linear algebra to solve
* this problem, it will take TOO much time to solve it. And we will
* notice it by EXTREME slowdown during testing.
*/
n = 20000;
sparsecreate(n, n, 0, &sa, _state);
for(i=0; i<=n-1; i++)
{
sparseset(&sa, i, i, ae_pow(10.0, -3*ae_randomreal(_state), _state), _state);
}
ae_vector_set_length(&b, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = randomnormal(_state);
}
minqpcreate(n, &state, _state);
minqpsetalgobleic(&state, 0.0, 0.0, 0.0, 10, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetquadratictermsparse(&state, &sa, ae_true, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend0, &rep, _state);
/*
* Special semi-definite test:
* * N dimensions, N>=2 (important!)
* * box constraints, x[i] in [-1,+1]
* [ 1 1 ... 1 1 ]
* * A = [ ... ... ... ]
* [ 1 1 ... 1 1 ]
* * random B such that SUM(b[i])=0.0 (important!)
* * initial point x0 is chosen in such way that SUM(x[i])=0.0
* (important!)
*
* We perform two tests:
* * unconstrained problem must be recognized as unbounded
* (when starting from x0!)
* * constrained problem must be recognized as bounded
* and successfully solved
*
* Both problems require subtle programming when we work
* with semidefinite QP.
*
* NOTE: it is very important to have N>=2 (otherwise problem
* will be bounded from below even without boundary
* constraints) and to have x0/b0 such that sum of
* components is zero (such x0 is exact minimum of x'*A*x,
* which allows algorithm to find direction of zero curvature
* at the very first step). If x0/b are chosen in other way,
* algorithm may be unable to find direction of zero
* curvature and will cycle forever, slowly decreasing
* function value at each iteration.
* This is major difference from similar test for QQP solver -
* QQP can find direction of zero curvature from almost any
* point due to internal CG solver which favors such directions.
* BLEIC uses LBFGS, which is less able to find direction of
* zero curvature.
*/
ae_vector_set_length(&nlist, 12, _state);
nlist.ptr.p_int[0] = 2;
nlist.ptr.p_int[1] = 3;
nlist.ptr.p_int[2] = 4;
nlist.ptr.p_int[3] = 5;
nlist.ptr.p_int[4] = 6;
nlist.ptr.p_int[5] = 7;
nlist.ptr.p_int[6] = 8;
nlist.ptr.p_int[7] = 9;
nlist.ptr.p_int[8] = 10;
nlist.ptr.p_int[9] = 20;
nlist.ptr.p_int[10] = 40;
nlist.ptr.p_int[11] = 80;
eps = 1.0E-5;
for(nidx=0; nidx<=nlist.cnt-1; nidx++)
{
for(pass=1; pass<=10; pass++)
{
/*
* Generate problem
*/
n = nlist.ptr.p_int[nidx];
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
do
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
while(ae_fp_eq(b.ptr.p_double[i],(double)(0)));
bndl.ptr.p_double[i] = (double)(-1);
bndu.ptr.p_double[i] = (double)(1);
x0.ptr.p_double[i] = 2*hqrnduniformr(&rs, _state)-1;
}
v = 0.0;
for(i=0; i<=n-1; i++)
{
v = v+x0.ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = x0.ptr.p_double[i]-v/n;
}
v = 0.0;
for(i=0; i<=n-1; i++)
{
v = v+b.ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = b.ptr.p_double[i]-v/n;
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 1.0;
}
}
testminqpunit_densetosparse(&a, n, &sa, _state);
/*
* Solve problem:
* * without constraints we expect failure
* * with constraints algorithm must succeed
*/
minqpcreate(n, &state, _state);
minqpsetalgobleic(&state, 0.0, 0.0, 0.0, 0, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetstartingpoint(&state, &x0, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minqpsetquadraticterm(&state, &a, ae_true, _state);
}
else
{
minqpsetquadratictermsparse(&state, &sa, ae_true, _state);
}
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype!=-4, __FILE__, __LINE__, "testminqpunit.ap:6772");
minqpsetbc(&state, &bndl, &bndu, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:6776");
if( rep.terminationtype<=0 )
{
ae_frame_leave(_state);
return result;
}
/*
* Test - calculate constrained gradient at solution,
* check its norm.
*/
gnorm = 0.0;
for(i=0; i<=n-1; i++)
{
g = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
g = g+a.ptr.pp_double[i][j]*x1.ptr.p_double[j];
}
if( ae_fp_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i])&&ae_fp_greater(g,(double)(0)) )
{
g = (double)(0);
}
if( ae_fp_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i])&&ae_fp_less(g,(double)(0)) )
{
g = (double)(0);
}
gnorm = gnorm+ae_sqr(g, _state);
ae_set_error_flag(&result, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6796");
ae_set_error_flag(&result, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6797");
}
gnorm = ae_sqrt(gnorm, _state);
ae_set_error_flag(&result, ae_fp_greater(gnorm,eps), __FILE__, __LINE__, "testminqpunit.ap:6800");
}
}
/*
* Test that BLEIC-based QP solver can solve non-convex problems
* which are bounded from below on the feasible set:
*
* min -||x||^2 s.t. x[i] in [-1,+1]
*
* We also test ability of the solver to detect unbounded problems
* (we remove one of the constraints and repeat solution process).
*/
n = 20;
eps = 1.0E-14;
sparsecreate(n, n, 0, &sa, _state);
for(i=0; i<=n-1; i++)
{
sparseset(&sa, i, i, (double)(-1), _state);
}
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x, n, _state);
for(i=0; i<=n-1; i++)
{
bndl.ptr.p_double[i] = (double)(-1);
bndu.ptr.p_double[i] = (double)(1);
x.ptr.p_double[i] = ae_randomreal(_state)-0.5;
}
minqpcreate(n, &state, _state);
minqpsetalgobleic(&state, eps, 0.0, 0.0, 0, _state);
minqpsetquadratictermsparse(&state, &sa, ae_true, _state);
minqpsetbc(&state, &bndl, &bndu, _state);
minqpsetstartingpoint(&state, &x, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend0, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:6833");
if( rep.terminationtype>0 )
{
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(&result, ae_fp_neq(xend0.ptr.p_double[i],(double)(-1))&&ae_fp_neq(xend0.ptr.p_double[i],(double)(1)), __FILE__, __LINE__, "testminqpunit.ap:6836");
}
}
i = ae_randominteger(n, _state);
bndl.ptr.p_double[i] = _state->v_neginf;
bndu.ptr.p_double[i] = _state->v_posinf;
minqpsetbc(&state, &bndl, &bndu, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend0, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype!=-4, __FILE__, __LINE__, "testminqpunit.ap:6843");
/*
* Test that BLEIC-based QP solver can solve non-convex problems
* which are bounded from below on the feasible set:
*
* min -||x||^2 s.t. x[i] in [-1,+1],
* with inequality constraints handled as general linear ones
*
* We also test ability of the solver to detect unbounded problems
* (we remove last pair of constraints and try to solve modified
* problem).
*/
n = 20;
eps = 1.0E-14;
sparsecreate(n, n, 0, &sa, _state);
for(i=0; i<=n-1; i++)
{
sparseset(&sa, i, i, (double)(-1), _state);
}
ae_matrix_set_length(&c, 2*n, n+1, _state);
ae_vector_set_length(&ct, 2*n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n; j++)
{
c.ptr.pp_double[2*i+0][j] = (double)(0);
c.ptr.pp_double[2*i+1][j] = (double)(0);
}
c.ptr.pp_double[2*i+0][i] = 1.0;
c.ptr.pp_double[2*i+0][n] = 1.0;
ct.ptr.p_int[2*i+0] = -1;
c.ptr.pp_double[2*i+1][i] = 1.0;
c.ptr.pp_double[2*i+1][n] = -1.0;
ct.ptr.p_int[2*i+1] = 1;
}
ae_vector_set_length(&x, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = ae_randomreal(_state)-0.5;
}
minqpcreate(n, &state, _state);
minqpsetalgobleic(&state, eps, 0.0, 0.0, 0, _state);
minqpsetquadratictermsparse(&state, &sa, ae_true, _state);
minqpsetlc(&state, &c, &ct, 2*n, _state);
minqpsetstartingpoint(&state, &x, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend0, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:6888");
if( rep.terminationtype>0 )
{
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(xend0.ptr.p_double[i]+1, _state),100*ae_machineepsilon)&&ae_fp_greater(ae_fabs(xend0.ptr.p_double[i]-1, _state),100*ae_machineepsilon), __FILE__, __LINE__, "testminqpunit.ap:6891");
}
}
minqpsetlc(&state, &c, &ct, 2*(n-1), _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend0, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype!=-4, __FILE__, __LINE__, "testminqpunit.ap:6895");
/*
* Test that BLEIC-based QP solver can solve QP problems with
* zero quadratic term:
*
* min b'*x s.t. x[i] in [-1,+1]
*
* It means that QP solver can be used as linear programming solver
* (altough performance of such solver is worse than that of specialized
* LP solver).
*
* NOTE: we perform this test twice - first time without explicitly setting
* quadratic term (we test that default quadratic term is zero), and
* second time - with explicitly set quadratic term.
*/
n = 20;
sparsecreate(n, n, 0, &sa, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&b, n, _state);
for(i=0; i<=n-1; i++)
{
bndl.ptr.p_double[i] = (double)(-1);
bndu.ptr.p_double[i] = (double)(1);
b.ptr.p_double[i] = randomnormal(_state);
}
minqpcreate(n, &state, _state);
minqpsetalgobleic(&state, eps, 0.0, 0.0, 0, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetbc(&state, &bndl, &bndu, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend0, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:6929");
if( rep.terminationtype>0 )
{
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(&result, ae_fp_greater(b.ptr.p_double[i],(double)(0))&&ae_fp_neq(xend0.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6933");
ae_set_error_flag(&result, ae_fp_less(b.ptr.p_double[i],(double)(0))&&ae_fp_neq(xend0.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6934");
}
}
minqpcreate(n, &state, _state);
minqpsetalgobleic(&state, eps, 0.0, 0.0, 0, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetbc(&state, &bndl, &bndu, _state);
minqpsetquadratictermsparse(&state, &sa, ae_true, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend0, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:6943");
if( rep.terminationtype>0 )
{
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(&result, ae_fp_greater(b.ptr.p_double[i],(double)(0))&&ae_fp_neq(xend0.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6947");
ae_set_error_flag(&result, ae_fp_less(b.ptr.p_double[i],(double)(0))&&ae_fp_neq(xend0.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:6948");
}
}
/*
* Test specific problem sent by V.Semenenko, which resulted in
* the initinite loop in FindFeasiblePoint (before fix). We do
* not test results returned by solver - simply being able to
* stop is enough for this test.
*
* NOTE: it is important that modifications to problem are applied
* sequentially. Test fails after 100-5000 such modifications.
* One modification is not enough to cause failure.
*/
n = 3;
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
a.ptr.pp_double[0][0] = 1.222990;
a.ptr.pp_double[1][1] = 1.934900;
a.ptr.pp_double[2][2] = 0.603924;
ae_vector_set_length(&b, n, _state);
b.ptr.p_double[0] = -4.97245;
b.ptr.p_double[1] = -9.09039;
b.ptr.p_double[2] = -4.63856;
ae_matrix_set_length(&c, 8, n+1, _state);
for(i=0; i<=c.rows-1; i++)
{
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = 0.0;
}
}
c.ptr.pp_double[0][0] = (double)(1);
c.ptr.pp_double[0][n] = 4.94298;
c.ptr.pp_double[1][0] = (double)(1);
c.ptr.pp_double[1][n] = 4.79981;
c.ptr.pp_double[2][1] = (double)(1);
c.ptr.pp_double[2][n] = -0.4848;
c.ptr.pp_double[3][1] = (double)(1);
c.ptr.pp_double[3][n] = -0.73804;
c.ptr.pp_double[4][2] = (double)(1);
c.ptr.pp_double[4][n] = 0.575729;
c.ptr.pp_double[5][2] = (double)(1);
c.ptr.pp_double[5][n] = 0.458645;
c.ptr.pp_double[6][0] = (double)(1);
c.ptr.pp_double[6][2] = (double)(-1);
c.ptr.pp_double[6][n] = -0.0546574;
c.ptr.pp_double[7][0] = (double)(1);
c.ptr.pp_double[7][2] = (double)(-1);
c.ptr.pp_double[7][n] = -0.5900440;
ae_vector_set_length(&ct, 8, _state);
ct.ptr.p_int[0] = -1;
ct.ptr.p_int[1] = 1;
ct.ptr.p_int[2] = -1;
ct.ptr.p_int[3] = 1;
ct.ptr.p_int[4] = -1;
ct.ptr.p_int[5] = 1;
ct.ptr.p_int[6] = -1;
ct.ptr.p_int[7] = 1;
ae_vector_set_length(&s, n, _state);
s.ptr.p_double[0] = 0.143171;
s.ptr.p_double[1] = 0.253240;
s.ptr.p_double[2] = 0.117084;
ae_vector_set_length(&x0, n, _state);
x0.ptr.p_double[0] = 3.51126;
x0.ptr.p_double[1] = 4.05731;
x0.ptr.p_double[2] = 6.63307;
for(pass=1; pass<=10000; pass++)
{
/*
* Apply random distortion
*/
for(j=0; j<=n-1; j++)
{
b.ptr.p_double[j] = b.ptr.p_double[j]+(2*hqrnduniformi(&rs, 2, _state)-1)*0.1;
}
for(j=0; j<=6-1; j++)
{
c.ptr.pp_double[j][n] = c.ptr.pp_double[j][n]+(2*hqrnduniformi(&rs, 2, _state)-1)*0.1;
}
/*
* Solve
*/
minqpcreate(3, &state, _state);
minqpsetquadraticterm(&state, &a, ae_true, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetlc(&state, &c, &ct, 8, _state);
minqpsetalgobleic(&state, 0.0, 0.0, 0.0, 0, _state);
minqpsetstartingpoint(&state, &x0, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function tests bound constrained quadratic programming algorithm.
On failure sets error flag.
*************************************************************************/
static void testminqpunit_bcqptest(ae_bool* wereerrors, ae_state *_state)
{
ae_frame _frame_block;
minqpstate state;
minqpreport rep;
ae_int_t n;
ae_int_t pass;
ae_int_t i;
ae_int_t j;
double v;
double g;
double gnorm;
ae_int_t origintype;
ae_int_t scaletype;
ae_bool isupper;
ae_bool issparse;
double bctol;
double lctol;
ae_matrix a;
ae_matrix fulla;
ae_matrix halfa;
ae_matrix c;
sparsematrix sa;
ae_vector ct;
ae_vector b;
ae_vector bndl;
ae_vector bndu;
ae_vector gtrial;
double vl;
double vu;
ae_vector x0;
ae_vector x1;
ae_vector xori;
ae_vector xz;
ae_vector s;
double eps;
hqrndstate rs;
ae_int_t solvertype;
ae_frame_make(_state, &_frame_block);
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&a, 0, sizeof(a));
memset(&fulla, 0, sizeof(fulla));
memset(&halfa, 0, sizeof(halfa));
memset(&c, 0, sizeof(c));
memset(&sa, 0, sizeof(sa));
memset(&ct, 0, sizeof(ct));
memset(&b, 0, sizeof(b));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(>rial, 0, sizeof(gtrial));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&xori, 0, sizeof(xori));
memset(&xz, 0, sizeof(xz));
memset(&s, 0, sizeof(s));
memset(&rs, 0, sizeof(rs));
_minqpstate_init(&state, _state, ae_true);
_minqpreport_init(&rep, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&fulla, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&halfa, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
_sparsematrix_init(&sa, _state, ae_true);
ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
ae_vector_init(>rial, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xori, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xz, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Convex test:
* * N dimensions
* * random number (0..N) of random boundary constraints
* * positive-definite A
* * algorithm randomly choose dense or sparse A, and for
* sparse matrix it randomly choose format.
* * random B with normal entries
* * initial point is random, feasible
* * random origin (zero or non-zero) and scale (unit or
* non-unit) are generated
*/
eps = 1.0E-3;
for(n=1; n<=10; n++)
{
for(pass=1; pass<=10; pass++)
{
/*
* Generate problem
*/
origintype = hqrnduniformi(&rs, 2, _state);
scaletype = hqrnduniformi(&rs, 2, _state);
isupper = ae_fp_less(hqrnduniformr(&rs, _state),0.5);
issparse = ae_fp_less(hqrnduniformr(&rs, _state),0.5);
spdmatrixrndcond(n, 1.0E3, &fulla, _state);
ae_matrix_set_length(&halfa, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (j>=i&&isupper)||(j<=i&&!isupper) )
{
halfa.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j];
}
else
{
halfa.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5;
}
}
}
testminqpunit_densetosparse(&halfa, n, &sa, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xori, n, _state);
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
bndl.ptr.p_double[i] = _state->v_neginf;
bndu.ptr.p_double[i] = _state->v_posinf;
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
if( origintype==0 )
{
xori.ptr.p_double[i] = (double)(0);
}
else
{
xori.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
if( scaletype==0 )
{
s.ptr.p_double[i] = (double)(1);
}
else
{
s.ptr.p_double[i] = ae_exp(0.5*hqrndnormal(&rs, _state), _state);
}
j = hqrnduniformi(&rs, 5, _state);
if( j==0 )
{
bndl.ptr.p_double[i] = (double)(0);
x0.ptr.p_double[i] = ae_fabs(x0.ptr.p_double[i], _state);
}
if( j==1 )
{
bndu.ptr.p_double[i] = (double)(0);
x0.ptr.p_double[i] = -ae_fabs(x0.ptr.p_double[i], _state);
}
if( j==2 )
{
bndl.ptr.p_double[i] = hqrndnormal(&rs, _state);
bndu.ptr.p_double[i] = bndl.ptr.p_double[i];
x0.ptr.p_double[i] = bndl.ptr.p_double[i];
}
if( j==3 )
{
bndl.ptr.p_double[i] = -0.1;
bndu.ptr.p_double[i] = 0.1;
x0.ptr.p_double[i] = 0.2*hqrnduniformr(&rs, _state)-0.1;
}
}
/*
* Solve problem
*/
minqpcreate(n, &state, _state);
solvertype = testminqpunit_setrandomalgoallmodern(&state, &bctol, &lctol, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetstartingpoint(&state, &x0, _state);
if( issparse )
{
minqpsetquadratictermsparse(&state, &sa, isupper, _state);
}
else
{
minqpsetquadraticterm(&state, &halfa, isupper, _state);
}
if( origintype!=0 )
{
minqpsetorigin(&state, &xori, _state);
}
if( scaletype!=0 )
{
minqpsetscale(&state, &s, _state);
}
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minqpsetbc(&state, &bndl, &bndu, _state);
}
else
{
for(i=0; i<=n-1; i++)
{
minqpsetbci(&state, i, bndl.ptr.p_double[i], bndu.ptr.p_double[i], _state);
}
}
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:882");
ae_set_error_flag(wereerrors, x1.cnt=i&&isupper)||(j<=i&&!isupper) )
{
halfa.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j];
}
else
{
halfa.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5;
}
}
}
testminqpunit_densetosparse(&halfa, n, &sa, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xori, n, _state);
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
if( origintype==0 )
{
xori.ptr.p_double[i] = (double)(0);
}
else
{
xori.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
if( scaletype==0 )
{
s.ptr.p_double[i] = (double)(1);
}
else
{
s.ptr.p_double[i] = ae_exp(0.5*hqrndnormal(&rs, _state), _state);
}
}
vl = _state->v_neginf;
vu = _state->v_posinf;
j = hqrnduniformi(&rs, 5, _state);
if( j==0 )
{
vl = (double)(0);
}
if( j==1 )
{
vu = (double)(0);
}
if( j==2 )
{
vl = hqrndnormal(&rs, _state);
vu = vl;
}
if( j==3 )
{
vl = -0.1-ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
vu = 0.1+ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
}
/*
* Solve problem
*/
minqpcreate(n, &state, _state);
testminqpunit_setrandomalgoallmodern(&state, &bctol, &lctol, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetstartingpoint(&state, &x0, _state);
if( issparse )
{
minqpsetquadratictermsparse(&state, &sa, isupper, _state);
}
else
{
minqpsetquadraticterm(&state, &halfa, isupper, _state);
}
if( origintype!=0 )
{
minqpsetorigin(&state, &xori, _state);
}
if( scaletype!=0 )
{
minqpsetscale(&state, &s, _state);
}
minqpsetbcall(&state, vl, vu, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:1017");
if( rep.terminationtype<=0 )
{
ae_frame_leave(_state);
return;
}
/*
* Test - calculate constrained gradient at solution,
* check its norm.
*/
gnorm = 0.0;
for(i=0; i<=n-1; i++)
{
g = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
g = g+fulla.ptr.pp_double[i][j]*(x1.ptr.p_double[j]-xori.ptr.p_double[j]);
}
if( ae_fp_less_eq(x1.ptr.p_double[i],vl+bctol)&&ae_fp_greater(g,(double)(0)) )
{
g = (double)(0);
}
if( ae_fp_greater_eq(x1.ptr.p_double[i],vu-bctol)&&ae_fp_less(g,(double)(0)) )
{
g = (double)(0);
}
gnorm = gnorm+ae_sqr(g, _state);
ae_set_error_flag(wereerrors, ae_fp_less(x1.ptr.p_double[i],vl), __FILE__, __LINE__, "testminqpunit.ap:1037");
ae_set_error_flag(wereerrors, ae_fp_greater(x1.ptr.p_double[i],vu), __FILE__, __LINE__, "testminqpunit.ap:1038");
}
gnorm = ae_sqrt(gnorm, _state);
ae_set_error_flag(wereerrors, ae_fp_greater(gnorm,eps), __FILE__, __LINE__, "testminqpunit.ap:1041");
}
}
/*
* Semidefinite test:
* * N dimensions
* * nonnegativity constraints
* * A = [ 1 1 ... 1 1 ; 1 1 ... 1 1 ; .... ; 1 1 ... 1 1 ]
* * algorithm randomly choose dense or sparse A, and for
* sparse matrix it randomly choose format.
* * random B with normal entries
* * initial point is random, feasible
*/
eps = 1.0E-4;
for(n=1; n<=10; n++)
{
for(pass=1; pass<=10; pass++)
{
/*
* Generate problem
*/
isupper = ae_fp_less(hqrnduniformr(&rs, _state),0.5);
issparse = ae_fp_less(hqrnduniformr(&rs, _state),0.5);
ae_matrix_set_length(&fulla, n, n, _state);
ae_matrix_set_length(&halfa, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
fulla.ptr.pp_double[i][j] = 1.0;
if( (j>=i&&isupper)||(j<=i&&!isupper) )
{
halfa.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j];
}
else
{
halfa.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5;
}
}
}
testminqpunit_densetosparse(&halfa, n, &sa, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
bndl.ptr.p_double[i] = 0.0;
bndu.ptr.p_double[i] = _state->v_posinf;
x0.ptr.p_double[i] = (double)(hqrnduniformi(&rs, 2, _state));
}
/*
* Solve problem
*/
minqpcreate(n, &state, _state);
testminqpunit_setrandomalgosemidefinite(&state, &bctol, &lctol, _state);
minqpsetstartingpoint(&state, &x0, _state);
minqpsetlinearterm(&state, &b, _state);
if( issparse )
{
minqpsetquadratictermsparse(&state, &sa, isupper, _state);
}
else
{
minqpsetquadraticterm(&state, &halfa, isupper, _state);
}
minqpsetbc(&state, &bndl, &bndu, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:1101");
if( rep.terminationtype<=0 )
{
ae_frame_leave(_state);
return;
}
/*
* Test - calculate constrained gradient at solution,
* check its norm.
*/
gnorm = 0.0;
for(i=0; i<=n-1; i++)
{
g = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
g = g+fulla.ptr.pp_double[i][j]*x1.ptr.p_double[j];
}
if( ae_fp_less_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i]+bctol)&&ae_fp_greater(g,(double)(0)) )
{
g = (double)(0);
}
if( ae_fp_greater_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i]-bctol)&&ae_fp_less(g,(double)(0)) )
{
g = (double)(0);
}
gnorm = gnorm+ae_sqr(g, _state);
ae_set_error_flag(wereerrors, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:1121");
ae_set_error_flag(wereerrors, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:1122");
}
gnorm = ae_sqrt(gnorm, _state);
ae_set_error_flag(wereerrors, ae_fp_greater(gnorm,eps), __FILE__, __LINE__, "testminqpunit.ap:1125");
}
}
/*
* Non-convex test:
* * N dimensions, N>=2
* * box constraints, x[i] in [-1,+1]
* * A = A0-0.5*I, where A0 is SPD with unit norm and smallest
* singular value equal to 1.0E-3, I is identity matrix
* * random B with normal entries
* * initial point is random, feasible
*
* We perform two tests:
* * unconstrained problem must be recognized as unbounded
* * constrained problem can be successfully solved
*
* NOTE: it is important to have N>=2, because formula for A
* can be applied only to matrix with at least two
* singular values
*/
eps = 1.0E-4;
for(n=2; n<=10; n++)
{
for(pass=1; pass<=10; pass++)
{
/*
* Generate problem
*/
spdmatrixrndcond(n, 1.0E3, &fulla, _state);
for(i=0; i<=n-1; i++)
{
fulla.ptr.pp_double[i][i] = fulla.ptr.pp_double[i][i]-0.5;
}
isupper = ae_fp_less(hqrnduniformr(&rs, _state),0.5);
ae_matrix_set_length(&halfa, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (j>=i&&isupper)||(j<=i&&!isupper) )
{
halfa.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j];
}
else
{
halfa.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5;
}
}
}
testminqpunit_densetosparse(&halfa, n, &sa, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
bndl.ptr.p_double[i] = (double)(-1);
bndu.ptr.p_double[i] = (double)(1);
x0.ptr.p_double[i] = 2*hqrnduniformr(&rs, _state)-1;
}
/*
* Solve problem:
* * without constraints we expect failure
* * with constraints algorithm must succeed
*/
minqpcreate(n, &state, _state);
testminqpunit_setrandomalgononconvex(&state, _state);
minqpsetstartingpoint(&state, &x0, _state);
minqpsetlinearterm(&state, &b, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minqpsetquadraticterm(&state, &halfa, isupper, _state);
}
else
{
minqpsetquadratictermsparse(&state, &sa, isupper, _state);
}
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, rep.terminationtype!=-4, __FILE__, __LINE__, "testminqpunit.ap:1192");
minqpsetbc(&state, &bndl, &bndu, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:1196");
if( rep.terminationtype<=0 )
{
ae_frame_leave(_state);
return;
}
/*
* Test - calculate constrained gradient at solution,
* check its norm.
*/
gnorm = 0.0;
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&fulla.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1));
g = v+b.ptr.p_double[i];
if( ae_fp_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i])&&ae_fp_greater(g,(double)(0)) )
{
g = (double)(0);
}
if( ae_fp_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i])&&ae_fp_less(g,(double)(0)) )
{
g = (double)(0);
}
gnorm = gnorm+ae_sqr(g, _state);
ae_set_error_flag(wereerrors, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:1215");
ae_set_error_flag(wereerrors, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:1216");
}
gnorm = ae_sqrt(gnorm, _state);
ae_set_error_flag(wereerrors, ae_fp_greater(gnorm,eps), __FILE__, __LINE__, "testminqpunit.ap:1219");
}
}
/*
* Linear (zero-quadratic) test:
* * N dimensions, N>=1
* * box constraints, x[i] in [-1,+1]
* * A = 0
* * random B with normal entries
* * initial point is random, feasible
*
* We perform two tests:
* * unconstrained problem must be recognized as unbounded
* * constrained problem can be successfully solved
*
* NOTE: we may explicitly set zero A, or assume that by
* default it is zero. During test we will try both
* ways.
*/
eps = 1.0E-4;
for(n=1; n<=10; n++)
{
for(pass=1; pass<=10; pass++)
{
/*
* Generate problem
*/
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
do
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
while(ae_fp_eq(b.ptr.p_double[i],(double)(0)));
bndl.ptr.p_double[i] = (double)(-1);
bndu.ptr.p_double[i] = (double)(1);
x0.ptr.p_double[i] = 2*hqrnduniformr(&rs, _state)-1;
}
/*
* Solve problem:
* * without constraints we expect failure
* * with constraints algorithm must succeed
*/
minqpcreate(n, &state, _state);
testminqpunit_setrandomalgosemidefinite(&state, &bctol, &lctol, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetstartingpoint(&state, &x0, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
minqpsetquadraticterm(&state, &a, ae_true, _state);
}
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, rep.terminationtype!=-4, __FILE__, __LINE__, "testminqpunit.ap:1278");
minqpsetbc(&state, &bndl, &bndu, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:1282");
if( rep.terminationtype<=0 )
{
ae_frame_leave(_state);
return;
}
/*
* Test - calculate constrained gradient at solution,
* check its norm.
*/
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(wereerrors, ae_fp_greater(b.ptr.p_double[i],(double)(0))&&ae_fp_greater(x1.ptr.p_double[i],bndl.ptr.p_double[i]+bctol), __FILE__, __LINE__, "testminqpunit.ap:1292");
ae_set_error_flag(wereerrors, ae_fp_less(b.ptr.p_double[i],(double)(0))&&ae_fp_less(x1.ptr.p_double[i],bndu.ptr.p_double[i]-bctol), __FILE__, __LINE__, "testminqpunit.ap:1293");
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
This function tests equality constrained quadratic programming algorithm.
Returns True on errors.
*************************************************************************/
static ae_bool testminqpunit_ecqptest(ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t k;
ae_matrix a;
ae_matrix q;
ae_matrix c;
ae_matrix a2;
ae_vector b;
ae_vector b2;
ae_vector xstart;
ae_vector xstart2;
ae_vector xend;
ae_vector xend2;
ae_vector x0;
ae_vector x1;
ae_vector xd;
ae_vector xs;
ae_vector tmp;
ae_vector g;
ae_vector bndl;
ae_vector bndu;
ae_vector xorigin;
ae_vector ct;
double eps;
double theta;
double f0;
double f1;
minqpstate state;
minqpstate state2;
minqpreport rep;
ae_int_t i;
ae_int_t j;
ae_int_t pass;
ae_int_t rk;
double v;
ae_int_t aulits;
ae_bool waserrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&q, 0, sizeof(q));
memset(&c, 0, sizeof(c));
memset(&a2, 0, sizeof(a2));
memset(&b, 0, sizeof(b));
memset(&b2, 0, sizeof(b2));
memset(&xstart, 0, sizeof(xstart));
memset(&xstart2, 0, sizeof(xstart2));
memset(&xend, 0, sizeof(xend));
memset(&xend2, 0, sizeof(xend2));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&xd, 0, sizeof(xd));
memset(&xs, 0, sizeof(xs));
memset(&tmp, 0, sizeof(tmp));
memset(&g, 0, sizeof(g));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(&xorigin, 0, sizeof(xorigin));
memset(&ct, 0, sizeof(ct));
memset(&state, 0, sizeof(state));
memset(&state2, 0, sizeof(state2));
memset(&rep, 0, sizeof(rep));
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a2, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xstart, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xstart2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xend, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xend2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xd, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xs, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
ae_vector_init(&g, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xorigin, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
_minqpstate_init(&state, _state, ae_true);
_minqpstate_init(&state2, _state, ae_true);
_minqpreport_init(&rep, _state, ae_true);
waserrors = ae_false;
/*
* First test:
* * N*N identity A
* * K=0, where q is random unit vector
* * optimization problem has form 0.5*x'*A*x-(x1*A)*x,
* where x1 is some random vector
* * either:
* a) x1 is feasible => we must stop at x1
* b) x1 is infeasible => we must stop at the boundary q'*x=0 and
* projection of gradient onto q*x=0 must be zero
*
* NOTE: we make several passes because some specific kind of errors is rarely
* caught by this test, so we need several repetitions.
*/
eps = 1.0E-4;
for(n=2; n<=6; n++)
{
for(pass=0; pass<=4; pass++)
{
/*
* Generate problem: A, b, CMatrix, x0, XStart
*/
spdmatrixrndcond(n, ae_pow(10.0, 3*ae_randomreal(_state), _state), &a, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x1, n, _state);
ae_vector_set_length(&xstart, n, _state);
ae_matrix_set_length(&c, 1, n+1, _state);
ae_vector_set_length(&ct, 1, _state);
for(i=0; i<=n-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
xstart.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
do
{
v = (double)(0);
for(i=0; i<=n-1; i++)
{
c.ptr.pp_double[0][i] = 2*ae_randomreal(_state)-1;
v = v+ae_sqr(c.ptr.pp_double[0][i], _state);
}
v = ae_sqrt(v, _state);
}
while(ae_fp_eq(v,(double)(0)));
for(i=0; i<=n-1; i++)
{
c.ptr.pp_double[0][i] = c.ptr.pp_double[0][i]/v;
}
c.ptr.pp_double[0][n] = (double)(0);
ct.ptr.p_int[0] = 1;
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1));
b.ptr.p_double[i] = -v;
}
/*
* Create optimizer, solve
*/
minqpcreate(n, &state, _state);
testminqpunit_setrandomalgoconvexlc(&state, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetquadraticterm(&state, &a, ae_fp_greater(ae_randomreal(_state),0.5), _state);
minqpsetstartingpoint(&state, &xstart, _state);
minqpsetlc(&state, &c, &ct, 1, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend, &rep, _state);
/*
* Test
*/
if( rep.terminationtype<=0 )
{
ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminqpunit.ap:2156");
continue;
}
v = ae_v_dotproduct(&x1.ptr.p_double[0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1));
if( ae_fp_greater_eq(v,(double)(0)) )
{
/*
* X1 is feasible, compare target function values at XEnd and X1
*/
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(xend.ptr.p_double[i]-x1.ptr.p_double[i], _state),eps), __FILE__, __LINE__, "testminqpunit.ap:2169");
}
}
else
{
/*
* X1 is infeasible:
* * XEnd must be approximately feasible
* * gradient projection onto c'*x=0 must be zero
*/
v = ae_v_dotproduct(&xend.ptr.p_double[0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1));
ae_set_error_flag(err, ae_fp_less(v,-eps), __FILE__, __LINE__, "testminqpunit.ap:2179");
ae_vector_set_length(&g, n, _state);
ae_v_move(&g.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1));
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xend.ptr.p_double[0], 1, ae_v_len(0,n-1));
g.ptr.p_double[i] = g.ptr.p_double[i]+v;
}
v = ae_v_dotproduct(&g.ptr.p_double[0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1));
ae_v_subd(&g.ptr.p_double[0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1), v);
v = ae_v_dotproduct(&g.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,n-1));
ae_set_error_flag(err, ae_fp_greater(ae_sqrt(v, _state),eps), __FILE__, __LINE__, "testminqpunit.ap:2190");
}
}
}
/*
* Boundary and linear equality/inequality constrained QP problem,
* test for correct handling of non-zero XOrigin:
* * N*N SPD A with moderate condtion number (up to 100)
* * boundary constraints 0<=x[i]<=1
* * K0 )
{
ae_set_error_flag(err, ae_fp_less(v,c.ptr.pp_double[i][n]-eps), __FILE__, __LINE__, "testminqpunit.ap:2321");
}
if( ct.ptr.p_int[i]<0 )
{
ae_set_error_flag(err, ae_fp_greater(v,c.ptr.pp_double[i][n]+eps), __FILE__, __LINE__, "testminqpunit.ap:2323");
}
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(xend.ptr.p_double[i]-xend2.ptr.p_double[i], _state),eps), __FILE__, __LINE__, "testminqpunit.ap:2327");
ae_set_error_flag(err, ae_fp_less(xend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testminqpunit.ap:2328");
ae_set_error_flag(err, ae_fp_greater(xend.ptr.p_double[i],(double)(1)), __FILE__, __LINE__, "testminqpunit.ap:2329");
}
}
}
/*
* Boundary constraints vs linear ones:
* * N*N SPD A
* * optimization problem has form 0.5*x'*A*x-(x1*A)*x,
* where x1 is some random vector from [-1,+1]
* * K=2*N constraints of the form ai<=x[i] or x[i]<=b[i],
* with ai in [-1.0,-0.1], bi in [+0.1,+1.0]
* * initial point xstart is from [-1,+2]
* * we solve two related QP problems:
* a) one with constraints posed as boundary ones
* b) another one with same constraints posed as general linear ones
* both problems must have same solution.
* Here we test that boundary constrained and linear inequality constrained
* solvers give same results.
*/
eps = 1.0E-3;
for(n=1; n<=6; n++)
{
/*
* Generate problem: A, b, x0, XStart, C, CT
*/
spdmatrixrndcond(n, ae_pow(10.0, 3*ae_randomreal(_state), _state), &a, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x1, n, _state);
ae_vector_set_length(&xstart, n, _state);
ae_matrix_set_length(&c, 2*n, n+1, _state);
ae_vector_set_length(&ct, 2*n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
for(i=0; i<=n-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
xstart.ptr.p_double[i] = 3*ae_randomreal(_state)-1;
bndl.ptr.p_double[i] = -(0.1+0.9*ae_randomreal(_state));
bndu.ptr.p_double[i] = 0.1+0.9*ae_randomreal(_state);
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[2*i+0][j] = (double)(0);
c.ptr.pp_double[2*i+1][j] = (double)(0);
}
c.ptr.pp_double[2*i+0][i] = (double)(1);
c.ptr.pp_double[2*i+0][n] = bndl.ptr.p_double[i];
ct.ptr.p_int[2*i+0] = 1;
c.ptr.pp_double[2*i+1][i] = (double)(1);
c.ptr.pp_double[2*i+1][n] = bndu.ptr.p_double[i];
ct.ptr.p_int[2*i+1] = -1;
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1));
b.ptr.p_double[i] = -v;
}
/*
* Solve linear inequality constrained problem
*/
minqpcreate(n, &state, _state);
testminqpunit_setrandomalgoconvexlc(&state, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetquadraticterm(&state, &a, ae_fp_greater(ae_randomreal(_state),0.5), _state);
minqpsetstartingpoint(&state, &xstart, _state);
minqpsetlc(&state, &c, &ct, 2*n, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend, &rep, _state);
/*
* Solve boundary constrained problem
*/
minqpcreate(n, &state2, _state);
testminqpunit_setrandomalgoconvexlc(&state, _state);
minqpsetlinearterm(&state2, &b, _state);
minqpsetquadraticterm(&state2, &a, ae_fp_greater(ae_randomreal(_state),0.5), _state);
minqpsetstartingpoint(&state2, &xstart, _state);
minqpsetbc(&state2, &bndl, &bndu, _state);
minqpoptimize(&state2, _state);
minqpresults(&state2, &xend2, &rep2, _state);
/*
* Calculate gradient, check projection
*/
if( rep.terminationtype<=0||rep2.terminationtype<=0 )
{
ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminqpunit.ap:2417");
continue;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(err, ae_fp_less(xend.ptr.p_double[i],bndl.ptr.p_double[i]-eps), __FILE__, __LINE__, "testminqpunit.ap:2422");
ae_set_error_flag(err, ae_fp_greater(xend.ptr.p_double[i],bndu.ptr.p_double[i]+eps), __FILE__, __LINE__, "testminqpunit.ap:2423");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(xend.ptr.p_double[i]-xend2.ptr.p_double[i], _state),eps), __FILE__, __LINE__, "testminqpunit.ap:2424");
}
}
/*
* Boundary constraints posed as general linear ones:
* * no bound constraints
* * 2*N linear constraints 0 <= x[i] <= 1
* * preconditioner is chosen at random (we just want to be
* sure that preconditioning won't prevent us from converging
* to the feasible point):
* * unit preconditioner
* * random diagonal-based preconditioner
* * random scale-based preconditioner
* * F(x) = |x-x0|^P, where P={2,4} and x0 is randomly selected from [-1,+2]^N
* * with such simple constraints and function it is easy to find
* analytic form of solution: S[i] = bound(x0[i], 0, 1).
* * however, we can't guarantee that solution is strictly feasible
* with respect to nonlinearity constraint, so we check
* for approximate feasibility.
*/
for(n=1; n<=5; n++)
{
/*
* Generate X, BL, BU.
*/
ae_matrix_set_length(&a, n, n, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&xstart, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_matrix_set_length(&c, 2*n, n+1, _state);
ae_vector_set_length(&ct, 2*n, _state);
for(i=0; i<=n-1; i++)
{
xstart.ptr.p_double[i] = ae_randomreal(_state);
x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1;
b.ptr.p_double[i] = -x0.ptr.p_double[i];
for(j=0; j<=n; j++)
{
c.ptr.pp_double[2*i+0][j] = (double)(0);
c.ptr.pp_double[2*i+1][j] = (double)(0);
}
c.ptr.pp_double[2*i+0][i] = (double)(1);
c.ptr.pp_double[2*i+0][n] = (double)(0);
ct.ptr.p_int[2*i+0] = 1;
c.ptr.pp_double[2*i+1][i] = (double)(1);
c.ptr.pp_double[2*i+1][n] = (double)(1);
ct.ptr.p_int[2*i+1] = -1;
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( i==j )
{
a.ptr.pp_double[i][j] = (double)(1);
}
else
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
}
/*
* Create and optimize
*/
minqpcreate(n, &state, _state);
testminqpunit_setrandomalgoconvexlc(&state, _state);
minqpsetlc(&state, &c, &ct, 2*n, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetquadraticterm(&state, &a, ae_fp_greater(ae_randomreal(_state),0.5), _state);
minqpsetstartingpoint(&state, &xstart, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminqpunit.ap:2493");
continue;
}
/*
* * compare solution with analytic one
* * check feasibility
*/
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(xend.ptr.p_double[i]-boundval(x0.ptr.p_double[i], 0.0, 1.0, _state), _state),0.05), __FILE__, __LINE__, "testminqpunit.ap:2503");
ae_set_error_flag(err, ae_fp_less(xend.ptr.p_double[i],0.0-1.0E-6), __FILE__, __LINE__, "testminqpunit.ap:2504");
ae_set_error_flag(err, ae_fp_greater(xend.ptr.p_double[i],1.0+1.0E-6), __FILE__, __LINE__, "testminqpunit.ap:2505");
}
}
/*
* Boundary and linear equality/inequality constrained QP problem with
* excessive constraints:
* * N*N SPD A with moderate condtion number (up to 100)
* * boundary constraints 0<=x[i]<=1
* * K=2*N equality/inequality constraints Q*x = Q*x0, where Q is random matrix,
* x0 is some random vector from the feasible hypercube (0.1<=x0[i]<=0.9)
* * optimization problem has form 0.5*x'*A*x-b*x,
* where b is some random vector
* * because constraints are excessive, the main problem is to find
* feasible point; usually, the only existing feasible point is solution,
* so we have to check only feasibility
*/
eps = 1.0E-4;
for(n=1; n<=6; n++)
{
/*
* Generate problem: A, b, BndL, BndU, CMatrix, x0, x1, XStart
*/
k = 2*n;
spdmatrixrndcond(n, ae_pow(10.0, 3*ae_randomreal(_state), _state), &a, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&x1, n, _state);
ae_vector_set_length(&xstart, n, _state);
ae_matrix_set_length(&c, k, n+1, _state);
ae_vector_set_length(&ct, k, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 0.1+0.8*ae_randomreal(_state);
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
bndl.ptr.p_double[i] = 0.0;
bndu.ptr.p_double[i] = 1.0;
xstart.ptr.p_double[i] = (double)(ae_randominteger(2, _state));
}
for(i=0; i<=k-1; i++)
{
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1));
ct.ptr.p_int[i] = ae_randominteger(3, _state)-1;
if( ct.ptr.p_int[i]==0 )
{
c.ptr.pp_double[i][n] = v;
}
if( ct.ptr.p_int[i]>0 )
{
c.ptr.pp_double[i][n] = v-1.0E-3;
}
if( ct.ptr.p_int[i]<0 )
{
c.ptr.pp_double[i][n] = v+1.0E-3;
}
}
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
/*
* Create optimizer, solve
*/
minqpcreate(n, &state, _state);
testminqpunit_setrandomalgoconvexlc(&state, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetquadraticterm(&state, &a, ae_fp_greater(ae_randomreal(_state),0.5), _state);
minqpsetstartingpoint(&state, &xstart, _state);
minqpsetbc(&state, &bndl, &bndu, _state);
minqpsetlc(&state, &c, &ct, k, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend, &rep, _state);
/*
* Check feasibility properties of the solution
*/
if( rep.terminationtype<=0 )
{
ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminqpunit.ap:2581");
continue;
}
for(i=0; i<=k-1; i++)
{
v = ae_v_dotproduct(&xend.ptr.p_double[0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
if( ct.ptr.p_int[i]==0 )
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-c.ptr.pp_double[i][n], _state),eps), __FILE__, __LINE__, "testminqpunit.ap:2588");
}
if( ct.ptr.p_int[i]>0 )
{
ae_set_error_flag(err, ae_fp_less(v,c.ptr.pp_double[i][n]-eps), __FILE__, __LINE__, "testminqpunit.ap:2590");
}
if( ct.ptr.p_int[i]<0 )
{
ae_set_error_flag(err, ae_fp_greater(v,c.ptr.pp_double[i][n]+eps), __FILE__, __LINE__, "testminqpunit.ap:2592");
}
}
}
/*
* General inequality constrained problem:
* * N*N SPD diagonal A with moderate condtion number
* * no boundary constraints
* * K=N inequality constraints C*x >= C*x0, where C is N*N well conditioned
* matrix, x0 is some random vector [-1,+1]
* * optimization problem has form 0.5*x'*A*x-b'*x,
* where b is random vector from [-1,+1]
* * using duality, we can obtain solution of QP problem as follows:
* a) intermediate problem min(0.5*y'*B*y + d'*y) s.t. y>=0
* is solved, where B = C*inv(A)*C', d = -(C*inv(A)*b + C*x0)
* b) after we got dual solution ys, we calculate primal solution
* xs = inv(A)*(C'*ys-b)
*/
eps = 1.0E-3;
for(n=1; n<=6; n++)
{
/*
* Generate problem
*/
ae_vector_set_length(&da, n, _state);
ae_matrix_set_length(&a, n, n, _state);
rmatrixrndcond(n, ae_pow(10.0, 2*ae_randomreal(_state), _state), &t2, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xstart, n, _state);
ae_matrix_set_length(&c, n, n+1, _state);
ae_vector_set_length(&ct, n, _state);
for(i=0; i<=n-1; i++)
{
da.ptr.p_double[i] = ae_exp(8*ae_randomreal(_state)-4, _state);
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
a.ptr.pp_double[i][i] = da.ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
xstart.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=n-1; i++)
{
ae_v_move(&c.ptr.pp_double[i][0], 1, &t2.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1));
c.ptr.pp_double[i][n] = v;
ct.ptr.p_int[i] = 1;
}
/*
* Solve primal problem, check feasibility
*/
minqpcreate(n, &state, _state);
testminqpunit_setrandomalgoconvexlc(&state, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetquadraticterm(&state, &a, ae_fp_greater(ae_randomreal(_state),0.5), _state);
minqpsetstartingpoint(&state, &xstart, _state);
minqpsetlc(&state, &c, &ct, n, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminqpunit.ap:2658");
continue;
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&xend.ptr.p_double[0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
ae_set_error_flag(err, ae_fp_less(v,c.ptr.pp_double[i][n]-eps), __FILE__, __LINE__, "testminqpunit.ap:2664");
}
/*
* Generate dual problem:
* * A2 stores new quadratic term
* * B2 stores new linear term
* * BndL/BndU store boundary constraints
*/
ae_matrix_set_length(&t3, n, n, _state);
ae_matrix_set_length(&a2, n, n, _state);
rmatrixtranspose(n, n, &c, 0, 0, &t3, 0, 0, _state);
for(i=0; i<=n-1; i++)
{
v = 1/ae_sqrt(da.ptr.p_double[i], _state);
ae_v_muld(&t3.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v);
}
rmatrixsyrk(n, n, 1.0, &t3, 0, 0, 2, 0.0, &a2, 0, 0, ae_true, _state);
ae_vector_set_length(&tmp0, n, _state);
ae_v_move(&tmp0.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1));
for(i=0; i<=n-1; i++)
{
tmp0.ptr.p_double[i] = tmp0.ptr.p_double[i]/da.ptr.p_double[i];
}
ae_vector_set_length(&b2, n, _state);
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &tmp0.ptr.p_double[0], 1, ae_v_len(0,n-1));
b2.ptr.p_double[i] = -(v+c.ptr.pp_double[i][n]);
}
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
for(i=0; i<=n-1; i++)
{
bndl.ptr.p_double[i] = 0.0;
bndu.ptr.p_double[i] = _state->v_posinf;
}
minqpcreate(n, &state2, _state);
testminqpunit_setrandomalgoconvexlc(&state, _state);
minqpsetlinearterm(&state2, &b2, _state);
minqpsetquadraticterm(&state2, &a2, ae_true, _state);
minqpsetbc(&state2, &bndl, &bndu, _state);
minqpoptimize(&state2, _state);
minqpresults(&state2, &xend2, &rep2, _state);
if( rep2.terminationtype<=0 )
{
ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminqpunit.ap:2719");
continue;
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&c.ptr.pp_double[0][i], c.stride, &xend2.ptr.p_double[0], 1, ae_v_len(0,n-1));
tmp0.ptr.p_double[i] = v-b.ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
tmp0.ptr.p_double[i] = tmp0.ptr.p_double[i]/da.ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(tmp0.ptr.p_double[i]-xend.ptr.p_double[i], _state),eps*ae_maxreal(ae_fabs(tmp0.ptr.p_double[i], _state), 1.0, _state)), __FILE__, __LINE__, "testminqpunit.ap:2732");
}
}
/*
* Boundary and linear equality/inequality constrained QP problem,
* test checks that different starting points yield same final point:
* * random N from [1..6], random K from [1..2*N]
* * N*N SPD A with moderate condtion number (up to 100)
* * boundary constraints 0<=x[i]<=1
* * K<2*N linear inequality constraints Q*x <= Q*x0, where
* Q is random K*N matrix, x0 is some random vector from the
* inner area of the feasible hypercube (0.1<=x0[i]<=0.9)
* * optimization problem has form 0.5*x'*A*x+b*x,
* where b is some random vector with -5<=b[i]<=+5
* * every component of the initial point XStart is random from [-2,+2]
* * we perform two starts from random different XStart and compare values
* of the target function (although final points may be slightly different,
* function values should match each other)
*/
eps = 1.0E-4;
for(pass=1; pass<=50; pass++)
{
/*
* Generate problem: N, K, A, b, BndL, BndU, CMatrix, x0, x1, XStart.
*/
n = ae_randominteger(5, _state)+2;
k = ae_randominteger(2*n, _state)+1;
spdmatrixrndcond(n, ae_pow(10.0, 2*ae_randomreal(_state), _state), &a, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&b2, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xstart, n, _state);
ae_vector_set_length(&xstart2, n, _state);
ae_matrix_set_length(&c, k, n+1, _state);
ae_vector_set_length(&ct, k, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 0.1+0.8*ae_randomreal(_state);
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
bndl.ptr.p_double[i] = 0.0;
bndu.ptr.p_double[i] = 1.0;
xstart.ptr.p_double[i] = 4*ae_randomreal(_state)-2;
xstart2.ptr.p_double[i] = 4*ae_randomreal(_state)-2;
}
for(i=0; i<=k-1; i++)
{
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1));
c.ptr.pp_double[i][n] = v;
ct.ptr.p_int[i] = ae_randominteger(3, _state)-1;
if( ct.ptr.p_int[i]<0 )
{
c.ptr.pp_double[i][n] = c.ptr.pp_double[i][n]+0.1;
}
if( ct.ptr.p_int[i]>0 )
{
c.ptr.pp_double[i][n] = c.ptr.pp_double[i][n]-0.1;
}
}
/*
* Solve with XStart
*/
minqpcreate(n, &state, _state);
testminqpunit_setrandomalgoconvexlc(&state, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetquadraticterm(&state, &a, ae_fp_greater(ae_randomreal(_state),0.5), _state);
minqpsetstartingpoint(&state, &xstart, _state);
minqpsetbc(&state, &bndl, &bndu, _state);
minqpsetlc(&state, &c, &ct, k, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminqpunit.ap:2806");
continue;
}
/*
* Solve with XStart2
*/
minqpsetstartingpoint(&state, &xstart2, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend2, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminqpunit.ap:2818");
continue;
}
/*
* Calculate function value and XEnd and XEnd2, compare solutions
*/
f0 = 0.0;
f1 = 0.0;
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
f0 = f0+0.5*xend.ptr.p_double[i]*a.ptr.pp_double[i][j]*xend.ptr.p_double[j];
f1 = f1+0.5*xend2.ptr.p_double[i]*a.ptr.pp_double[i][j]*xend2.ptr.p_double[j];
}
f0 = f0+xend.ptr.p_double[i]*b.ptr.p_double[i];
f1 = f1+xend2.ptr.p_double[i]*b.ptr.p_double[i];
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(f0-f1, _state),eps), __FILE__, __LINE__, "testminqpunit.ap:2837");
}
/*
* Convex/nonconvex optimization problem with excessive constraints:
*
* * N=2..5
* * f = 0.5*x'*A*x+b'*x
* * b has normally distributed entries with scale 10^BScale
* * several kinds of A are tried: zero, well conditioned SPD, well conditioned indefinite, low rank SPD, low rank indefinite
* * box constraints: x[i] in [-1,+1]
* * 2^N "excessive" general linear constraints (v_k,x)<=(v_k,v_k)+v_shift,
* where v_k is one of 2^N vertices of feasible hypercube, v_shift is
* a shift parameter:
* * with zero v_shift such constraints are degenerate (each vertex has
* N box constraints and one "redundant" linear constraint)
* * with positive v_shift linear constraint is always inactive
* * with small (about machine epsilon) but negative v_shift,
* constraint is close to degenerate - but not exactly
*
* We check that constrained gradient is close to zero at solution.
* Box constraint is considered active if distance to boundary is less
* than TolConstr.
*
* NOTE: TolConstr must be large enough so it won't conflict with
* perturbation introduced by v_shift
*/
tolconstr = 1.0E-3;
for(n=2; n<=5; n++)
{
for(akind=0; akind<=4; akind++)
{
for(shiftkind=-5; shiftkind<=1; shiftkind++)
{
for(bscale=0; bscale>=-2; bscale--)
{
/*
* Generate A, B and initial point
*/
ae_matrix_set_length(&a, n, n, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = ae_pow((double)(10), (double)(bscale), _state)*hqrndnormal(&rs, _state);
x.ptr.p_double[i] = hqrnduniformr(&rs, _state)-0.5;
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
isnonconvex = ae_false;
if( akind==1 )
{
/*
* Dense well conditioned SPD
*/
spdmatrixrndcond(n, 50.0, &a, _state);
}
if( akind==2 )
{
/*
* Dense well conditioned indefinite
*/
smatrixrndcond(n, 50.0, &a, _state);
isnonconvex = ae_true;
}
if( akind==3 )
{
/*
* Low rank semidefinite
*/
ae_vector_set_length(&tmp, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
for(k=1; k<=ae_minint(3, n-1, _state); k++)
{
for(i=0; i<=n-1; i++)
{
tmp.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
v = ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j];
}
}
}
}
if( akind==4 )
{
/*
* Low rank indefinite
*/
ae_vector_set_length(&tmp, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
for(k=1; k<=ae_minint(3, n-1, _state); k++)
{
for(i=0; i<=n-1; i++)
{
tmp.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
v = hqrndnormal(&rs, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j];
}
}
}
isnonconvex = ae_true;
}
/*
* Generate constraints
*/
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
for(i=0; i<=n-1; i++)
{
bl.ptr.p_double[i] = -1.0;
bu.ptr.p_double[i] = 1.0;
}
ccnt = ae_round(ae_pow((double)(2), (double)(n), _state), _state);
ae_matrix_set_length(&c, ccnt, n+1, _state);
ae_vector_set_length(&ct, ccnt, _state);
for(i=0; i<=ccnt-1; i++)
{
ct.ptr.p_int[i] = -1;
k = i;
c.ptr.pp_double[i][n] = ae_sign((double)(shiftkind), _state)*ae_pow((double)(10), ae_fabs((double)(shiftkind), _state), _state)*ae_machineepsilon;
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = (double)(2*(k%2)-1);
c.ptr.pp_double[i][n] = c.ptr.pp_double[i][n]+c.ptr.pp_double[i][j]*c.ptr.pp_double[i][j];
k = k/2;
}
}
/*
* Create and optimize
*/
minqpcreate(n, &state, _state);
minqpsetstartingpoint(&state, &x, _state);
if( isnonconvex )
{
testminqpunit_setrandomalgononconvexlc(&state, _state);
}
else
{
testminqpunit_setrandomalgoconvexlc(&state, _state);
}
minqpsetbc(&state, &bl, &bu, _state);
minqpsetlc(&state, &c, &ct, ccnt, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetquadraticterm(&state, &a, ae_fp_greater(ae_randomreal(_state),0.5), _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xs0, &rep, _state);
ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:2984");
if( *err )
{
ae_frame_leave(_state);
return;
}
/*
* Evaluate gradient at solution and test
*/
vv = 0.0;
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xs0.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = v+b.ptr.p_double[i];
if( ae_fp_less_eq(xs0.ptr.p_double[i],bl.ptr.p_double[i]+tolconstr)&&ae_fp_greater(v,(double)(0)) )
{
v = 0.0;
}
if( ae_fp_greater_eq(xs0.ptr.p_double[i],bu.ptr.p_double[i]-tolconstr)&&ae_fp_less(v,(double)(0)) )
{
v = 0.0;
}
vv = vv+ae_sqr(v, _state);
}
vv = ae_sqrt(vv, _state);
ae_set_error_flag(err, ae_fp_greater(vv,1.0E-3), __FILE__, __LINE__, "testminqpunit.ap:3008");
}
}
}
}
/*
* Convex/nonconvex optimization problem with combination of
* box and linear constraints:
*
* * N=2..8
* * f = 0.5*x'*A*x+b'*x
* * b has normally distributed entries with scale 10^BScale
* * several kinds of A are tried: zero, well conditioned SPD,
* well conditioned indefinite, low rank semidefinite, low rank indefinite
* * box constraints: x[i] in [-1,+1]
* * initial point x0 = [0 0 ... 0 0]
* * CCnt=min(3,N-1) general linear constraints of form (c,x)=0.
* random mix of equality/inequality constraints is tried.
* x0 is guaranteed to be feasible.
*
* We check that constrained gradient is close to zero at solution.
* Inequality constraint is considered active if distance to boundary
* is less than TolConstr. We use nonnegative least squares solver
* in order to compute constrained gradient.
*/
tolconstr = 1.0E-3;
for(n=2; n<=8; n++)
{
for(akind=0; akind<=4; akind++)
{
for(bscale=0; bscale>=-2; bscale--)
{
/*
* Generate A, B and initial point
*/
ae_matrix_set_length(&a, n, n, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = ae_pow((double)(10), (double)(bscale), _state)*hqrndnormal(&rs, _state);
x.ptr.p_double[i] = 0.0;
}
isnonconvex = ae_false;
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
if( akind==1 )
{
/*
* Dense well conditioned SPD
*/
spdmatrixrndcond(n, 50.0, &a, _state);
}
if( akind==2 )
{
/*
* Dense well conditioned indefinite
*/
smatrixrndcond(n, 50.0, &a, _state);
isnonconvex = ae_true;
}
if( akind==3 )
{
/*
* Low rank
*/
ae_vector_set_length(&tmp, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
for(k=1; k<=ae_minint(3, n-1, _state); k++)
{
for(i=0; i<=n-1; i++)
{
tmp.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
v = ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j];
}
}
}
}
if( akind==4 )
{
/*
* Low rank indefinite
*/
ae_vector_set_length(&tmp, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
for(k=1; k<=ae_minint(3, n-1, _state); k++)
{
for(i=0; i<=n-1; i++)
{
tmp.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
v = hqrndnormal(&rs, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j];
}
}
}
isnonconvex = ae_true;
}
/*
* Generate constraints
*/
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
for(i=0; i<=n-1; i++)
{
bl.ptr.p_double[i] = -1.0;
bu.ptr.p_double[i] = 1.0;
}
ccnt = ae_minint(3, n-1, _state);
ae_matrix_set_length(&c, ccnt, n+1, _state);
ae_vector_set_length(&ct, ccnt, _state);
for(i=0; i<=ccnt-1; i++)
{
ct.ptr.p_int[i] = hqrnduniformi(&rs, 3, _state)-1;
c.ptr.pp_double[i][n] = 0.0;
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5;
}
}
/*
* Create and optimize
*/
minqpcreate(n, &state, _state);
minqpsetstartingpoint(&state, &x, _state);
if( isnonconvex )
{
testminqpunit_setrandomalgononconvexlc(&state, _state);
}
else
{
testminqpunit_setrandomalgoconvexlc(&state, _state);
}
minqpsetbc(&state, &bl, &bu, _state);
minqpsetlc(&state, &c, &ct, ccnt, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetquadraticterm(&state, &a, ae_fp_greater(ae_randomreal(_state),0.5), _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xs0, &rep, _state);
ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:3143");
if( *err )
{
ae_frame_leave(_state);
return;
}
/*
* 1. evaluate unconstrained gradient at solution
*
* 2. calculate constrained gradient (NNLS solver is used
* to evaluate gradient subject to active constraints).
* In order to do this we form CE matrix, matrix of active
* constraints (columns store constraint vectors). Then
* we try to approximate gradient vector by columns of CE,
* subject to non-negativity restriction placed on variables
* corresponding to inequality constraints.
*
* Residual from such regression is a constrained gradient vector.
*/
ae_vector_set_length(&g, n, _state);
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xs0.ptr.p_double[0], 1, ae_v_len(0,n-1));
g.ptr.p_double[i] = v+b.ptr.p_double[i];
}
ae_matrix_set_length(&ce, n, n+ccnt, _state);
ae_vector_set_length(&nonnegative, n+ccnt, _state);
k = 0;
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(err, ae_fp_less(xs0.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:3171");
ae_set_error_flag(err, ae_fp_greater(xs0.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:3172");
if( ae_fp_less_eq(xs0.ptr.p_double[i],bl.ptr.p_double[i]+tolconstr) )
{
for(j=0; j<=n-1; j++)
{
ce.ptr.pp_double[j][k] = 0.0;
}
ce.ptr.pp_double[i][k] = 1.0;
nonnegative.ptr.p_bool[k] = ae_true;
inc(&k, _state);
continue;
}
if( ae_fp_greater_eq(xs0.ptr.p_double[i],bu.ptr.p_double[i]-tolconstr) )
{
for(j=0; j<=n-1; j++)
{
ce.ptr.pp_double[j][k] = 0.0;
}
ce.ptr.pp_double[i][k] = -1.0;
nonnegative.ptr.p_bool[k] = ae_true;
inc(&k, _state);
continue;
}
}
for(i=0; i<=ccnt-1; i++)
{
v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &xs0.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = v-c.ptr.pp_double[i][n];
ae_set_error_flag(err, ct.ptr.p_int[i]==0&&ae_fp_greater(ae_fabs(v, _state),tolconstr), __FILE__, __LINE__, "testminqpunit.ap:3196");
ae_set_error_flag(err, ct.ptr.p_int[i]>0&&ae_fp_less(v,-tolconstr), __FILE__, __LINE__, "testminqpunit.ap:3197");
ae_set_error_flag(err, ct.ptr.p_int[i]<0&&ae_fp_greater(v,tolconstr), __FILE__, __LINE__, "testminqpunit.ap:3198");
if( ct.ptr.p_int[i]==0 )
{
for(j=0; j<=n-1; j++)
{
ce.ptr.pp_double[j][k] = c.ptr.pp_double[i][j];
}
nonnegative.ptr.p_bool[k] = ae_false;
inc(&k, _state);
continue;
}
if( (ct.ptr.p_int[i]>0&&ae_fp_less_eq(v,tolconstr))||(ct.ptr.p_int[i]<0&&ae_fp_greater_eq(v,-tolconstr)) )
{
for(j=0; j<=n-1; j++)
{
ce.ptr.pp_double[j][k] = ae_sign((double)(ct.ptr.p_int[i]), _state)*c.ptr.pp_double[i][j];
}
nonnegative.ptr.p_bool[k] = ae_true;
inc(&k, _state);
continue;
}
}
snnlsinit(0, 0, 0, &nnls, _state);
snnlssetproblem(&nnls, &ce, &g, 0, k, n, _state);
for(i=0; i<=k-1; i++)
{
if( !nonnegative.ptr.p_bool[i] )
{
snnlsdropnnc(&nnls, i, _state);
}
}
snnlssolve(&nnls, &tmp, _state);
for(i=0; i<=k-1; i++)
{
for(j=0; j<=n-1; j++)
{
g.ptr.p_double[j] = g.ptr.p_double[j]-tmp.ptr.p_double[i]*ce.ptr.pp_double[j][i];
}
}
vv = ae_v_dotproduct(&g.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,n-1));
vv = ae_sqrt(vv, _state);
ae_set_error_flag(err, ae_fp_greater(vv,1.0E-3), __FILE__, __LINE__, "testminqpunit.ap:3227");
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
This function tests linearly constrained QP solvers.
On failure sets Err to True; on success leaves it unchanged.
*************************************************************************/
static void testminqpunit_generallcqptest(ae_bool* errorflag,
ae_state *_state)
{
ae_frame _frame_block;
hqrndstate rs;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t solvertype;
double v;
double vv;
ae_bool bflag;
ae_int_t pass;
ae_matrix rawa;
ae_matrix a;
sparsematrix sa;
ae_vector b;
ae_vector b2;
ae_vector xs;
ae_vector x0;
ae_vector x1;
ae_vector x2;
ae_vector xf;
ae_vector xorigin;
ae_vector s;
ae_vector da;
ae_vector xstart;
ae_vector g;
ae_vector gtrial;
ae_vector gs;
ae_vector tmp;
ae_vector tmp0;
ae_vector tmp1;
ae_vector tmp2;
ae_vector lagrange;
ae_vector bndl;
ae_vector bndu;
ae_matrix rawc;
ae_vector rawcl;
ae_vector rawcu;
ae_vector rawct;
ae_int_t rawccnt;
ae_matrix densec;
ae_vector densect;
ae_int_t denseccnt;
sparsematrix sparsec;
ae_vector sparsect;
ae_int_t sparseccnt;
ae_matrix activeset;
ae_vector activeeq;
ae_int_t nactive;
snnlssolver nnls;
double constraintsrcond;
ae_vector svdw;
ae_matrix svdu;
ae_matrix svdvt;
minqpstate state;
minqpreport rep;
minqpstate state2;
minqpreport rep2;
double f0;
double f1;
double xtol;
double ftol;
double gtol;
double tolconstr;
ae_int_t bscale;
ae_int_t akind;
ae_matrix ce;
ae_matrix q;
ae_matrix t2;
ae_matrix t3;
ae_matrix a2;
ae_vector lagbc;
ae_vector laglc;
ae_vector nonnegative;
double mx;
ae_int_t shiftkind;
ae_int_t nnz;
ae_bool issemidefinite;
ae_bool skiptest;
double bleicepsx;
double aulepsx;
double aulrho;
ae_int_t aulits;
double ipmeps;
ae_matrix kkt;
ae_vector kktright;
ae_frame_make(_state, &_frame_block);
memset(&rs, 0, sizeof(rs));
memset(&rawa, 0, sizeof(rawa));
memset(&a, 0, sizeof(a));
memset(&sa, 0, sizeof(sa));
memset(&b, 0, sizeof(b));
memset(&b2, 0, sizeof(b2));
memset(&xs, 0, sizeof(xs));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&x2, 0, sizeof(x2));
memset(&xf, 0, sizeof(xf));
memset(&xorigin, 0, sizeof(xorigin));
memset(&s, 0, sizeof(s));
memset(&da, 0, sizeof(da));
memset(&xstart, 0, sizeof(xstart));
memset(&g, 0, sizeof(g));
memset(>rial, 0, sizeof(gtrial));
memset(&gs, 0, sizeof(gs));
memset(&tmp, 0, sizeof(tmp));
memset(&tmp0, 0, sizeof(tmp0));
memset(&tmp1, 0, sizeof(tmp1));
memset(&tmp2, 0, sizeof(tmp2));
memset(&lagrange, 0, sizeof(lagrange));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(&rawc, 0, sizeof(rawc));
memset(&rawcl, 0, sizeof(rawcl));
memset(&rawcu, 0, sizeof(rawcu));
memset(&rawct, 0, sizeof(rawct));
memset(&densec, 0, sizeof(densec));
memset(&densect, 0, sizeof(densect));
memset(&sparsec, 0, sizeof(sparsec));
memset(&sparsect, 0, sizeof(sparsect));
memset(&activeset, 0, sizeof(activeset));
memset(&activeeq, 0, sizeof(activeeq));
memset(&nnls, 0, sizeof(nnls));
memset(&svdw, 0, sizeof(svdw));
memset(&svdu, 0, sizeof(svdu));
memset(&svdvt, 0, sizeof(svdvt));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&state2, 0, sizeof(state2));
memset(&rep2, 0, sizeof(rep2));
memset(&ce, 0, sizeof(ce));
memset(&q, 0, sizeof(q));
memset(&t2, 0, sizeof(t2));
memset(&t3, 0, sizeof(t3));
memset(&a2, 0, sizeof(a2));
memset(&lagbc, 0, sizeof(lagbc));
memset(&laglc, 0, sizeof(laglc));
memset(&nonnegative, 0, sizeof(nonnegative));
memset(&kkt, 0, sizeof(kkt));
memset(&kktright, 0, sizeof(kktright));
_hqrndstate_init(&rs, _state, ae_true);
ae_matrix_init(&rawa, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
_sparsematrix_init(&sa, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xs, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xf, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xorigin, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&da, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xstart, 0, DT_REAL, _state, ae_true);
ae_vector_init(&g, 0, DT_REAL, _state, ae_true);
ae_vector_init(>rial, 0, DT_REAL, _state, ae_true);
ae_vector_init(&gs, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&lagrange, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&rawc, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rawcl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rawcu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rawct, 0, DT_INT, _state, ae_true);
ae_matrix_init(&densec, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&densect, 0, DT_INT, _state, ae_true);
_sparsematrix_init(&sparsec, _state, ae_true);
ae_vector_init(&sparsect, 0, DT_INT, _state, ae_true);
ae_matrix_init(&activeset, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&activeeq, 0, DT_BOOL, _state, ae_true);
_snnlssolver_init(&nnls, _state, ae_true);
ae_vector_init(&svdw, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&svdu, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&svdvt, 0, 0, DT_REAL, _state, ae_true);
_minqpstate_init(&state, _state, ae_true);
_minqpreport_init(&rep, _state, ae_true);
_minqpstate_init(&state2, _state, ae_true);
_minqpreport_init(&rep2, _state, ae_true);
ae_matrix_init(&ce, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&t2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&t3, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a2, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&lagbc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&laglc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&nonnegative, 0, DT_BOOL, _state, ae_true);
ae_matrix_init(&kkt, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&kktright, 0, DT_REAL, _state, ae_true);
hqrndrandomize(&rs, _state);
bleicepsx = 1.0E-9;
ipmeps = 1.0E-12;
aulepsx = 1.0E-12;
aulrho = 1.0E3;
aulits = 15;
/*
* SMALL-SCALE TESTS: many tests for small N's
*/
for(solvertype=0; solvertype<=3; solvertype++)
{
/*
* Test random linearly constrained convex QP problem with known answer:
* * generate random A and b
* * generate random solution XS
* * calculate unconstrained gradient GS at XS
* * generate random box/linear constraints C, with some of them being
* active at XS, and some being inactive. Calculate residual gradient
* GP after projection of GS onto active set, add one more constraint
* equal to +-(GP-GS).
*
* We test here BLEIC and Dense-AUL solvers, with A being passed
* in dense or sparse format, and linear constraints C being passed
* as dense, sparse or mixed ones.
*/
for(n=1; n<=10; n++)
{
/*
* Generate random A, b and xs
*/
spdmatrixrndcond(n, ae_pow(10.0, 2*ae_randomreal(_state), _state), &rawa, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&xs, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
xs.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
/*
* Generate well conditioned "raw" constraints:
* * generate random box and CCnt-1 linear constraints
* * determine active set, calculate its condition number
* * repeat until condition number is good enough
* (better than 1E2; larger values sometimes result in
* spurious failures)
*/
ae_vector_set_length(&gs, n, _state);
ae_vector_set_length(&tmp, n, _state);
rmatrixmv(n, n, &rawa, 0, 0, 0, &xs, 0, &gs, 0, _state);
for(i=0; i<=n-1; i++)
{
gs.ptr.p_double[i] = gs.ptr.p_double[i]+b.ptr.p_double[i];
}
rawccnt = 1+hqrnduniformi(&rs, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_matrix_set_length(&activeset, n, n+rawccnt, _state);
ae_vector_set_length(&activeeq, n+rawccnt, _state);
ae_matrix_set_length(&rawc, rawccnt, n+1, _state);
ae_vector_set_length(&rawct, rawccnt, _state);
do
{
nactive = 0;
for(i=0; i<=n-1; i++)
{
bndl.ptr.p_double[i] = xs.ptr.p_double[i]-1-hqrnduniformr(&rs, _state);
bndu.ptr.p_double[i] = xs.ptr.p_double[i]+1+hqrnduniformr(&rs, _state);
if( ae_fp_less(hqrnduniformr(&rs, _state),0.66) )
{
/*
* I-th box constraint is inactive
*/
continue;
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),0.50) )
{
/*
* I-th box constraint is equality one
*/
bndl.ptr.p_double[i] = xs.ptr.p_double[i];
bndu.ptr.p_double[i] = xs.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
activeset.ptr.pp_double[j][nactive] = (double)(0);
}
activeset.ptr.pp_double[i][nactive] = (double)(1);
activeeq.ptr.p_bool[nactive] = ae_true;
nactive = nactive+1;
}
else
{
/*
* I-th box constraint is inequality one
*/
for(j=0; j<=n-1; j++)
{
activeset.ptr.pp_double[j][nactive] = (double)(0);
}
if( ae_fp_greater(gs.ptr.p_double[i],(double)(0)) )
{
bndl.ptr.p_double[i] = xs.ptr.p_double[i];
activeset.ptr.pp_double[i][nactive] = (double)(-1);
if( ae_fp_greater(hqrnduniformr(&rs, _state),0.50) )
{
bndu.ptr.p_double[i] = _state->v_posinf;
}
}
else
{
bndu.ptr.p_double[i] = xs.ptr.p_double[i];
activeset.ptr.pp_double[i][nactive] = (double)(1);
if( ae_fp_greater(hqrnduniformr(&rs, _state),0.50) )
{
bndl.ptr.p_double[i] = _state->v_neginf;
}
}
activeeq.ptr.p_bool[nactive] = ae_false;
nactive = nactive+1;
}
}
for(i=0; i<=rawccnt-2; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_less(hqrnduniformr(&rs, _state),0.50) )
{
rawc.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
else
{
rawc.ptr.pp_double[i][j] = (double)(0);
}
}
rawc.ptr.pp_double[i][hqrnduniformi(&rs, n, _state)] = hqrndnormal(&rs, _state);
rawc.ptr.pp_double[i][n] = (double)(0);
for(j=0; j<=n-1; j++)
{
rawc.ptr.pp_double[i][n] = rawc.ptr.pp_double[i][n]+rawc.ptr.pp_double[i][j]*xs.ptr.p_double[j];
}
rawct.ptr.p_int[i] = -1;
if( ae_fp_less(hqrnduniformr(&rs, _state),0.66) )
{
/*
* I-th box constraint is inactive
*/
rawc.ptr.pp_double[i][n] = rawc.ptr.pp_double[i][n]+(1+hqrnduniformr(&rs, _state));
if( ae_fp_greater(hqrnduniformr(&rs, _state),0.50) )
{
ae_v_muld(&rawc.ptr.pp_double[i][0], 1, ae_v_len(0,n), -1);
rawct.ptr.p_int[i] = -rawct.ptr.p_int[i];
}
continue;
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),0.50) )
{
/*
* I-th box constraint is equality one
*/
rawct.ptr.p_int[i] = 0;
for(j=0; j<=n-1; j++)
{
activeset.ptr.pp_double[j][nactive] = rawc.ptr.pp_double[i][j];
}
activeeq.ptr.p_bool[nactive] = ae_true;
nactive = nactive+1;
}
else
{
/*
* I-th box constraint is inequality one
*/
v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &gs.ptr.p_double[0], 1, ae_v_len(0,n-1));
if( ae_fp_greater(v,(double)(0)) )
{
rawct.ptr.p_int[i] = 1;
for(j=0; j<=n-1; j++)
{
activeset.ptr.pp_double[j][nactive] = -rawc.ptr.pp_double[i][j];
}
}
else
{
rawct.ptr.p_int[i] = -1;
for(j=0; j<=n-1; j++)
{
activeset.ptr.pp_double[j][nactive] = rawc.ptr.pp_double[i][j];
}
}
activeeq.ptr.p_bool[nactive] = ae_false;
nactive = nactive+1;
}
}
ae_v_moveneg(&tmp.ptr.p_double[0], 1, &gs.ptr.p_double[0], 1, ae_v_len(0,n-1));
snnlsinit(0, 0, 0, &nnls, _state);
snnlssetproblem(&nnls, &activeset, &tmp, 0, nactive, n, _state);
for(i=0; i<=nactive-1; i++)
{
if( activeeq.ptr.p_bool[i] )
{
snnlsdropnnc(&nnls, i, _state);
}
}
snnlssolve(&nnls, &lagrange, _state);
ae_v_moveneg(&tmp.ptr.p_double[0], 1, &gs.ptr.p_double[0], 1, ae_v_len(0,n-1));
for(i=0; i<=nactive-1; i++)
{
v = lagrange.ptr.p_double[i];
ae_v_subd(&tmp.ptr.p_double[0], 1, &activeset.ptr.pp_double[0][i], activeset.stride, ae_v_len(0,n-1), v);
}
ae_v_move(&rawc.ptr.pp_double[rawccnt-1][0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = ae_v_dotproduct(&tmp.ptr.p_double[0], 1, &xs.ptr.p_double[0], 1, ae_v_len(0,n-1));
rawc.ptr.pp_double[rawccnt-1][n] = v;
rawct.ptr.p_int[rawccnt-1] = -1;
/*
* Calculate reciprocal condition number
*/
if( nactive>0 )
{
bflag = rmatrixsvd(&activeset, n, nactive, 0, 0, 0, &svdw, &svdu, &svdvt, _state);
ae_assert(bflag, "MinQPTest: integrity failure", _state);
constraintsrcond = svdw.ptr.p_double[ae_minint(nactive, n, _state)-1]/svdw.ptr.p_double[0];
}
else
{
constraintsrcond = (double)(1);
}
/*
* Check RCond
*/
}
while(!(ae_fp_greater_eq(constraintsrcond,0.01)&&nactive<=n-1));
/*
* Create optimizer, solve
*/
minqpcreate(n, &state, _state);
if( solvertype==0 )
{
minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state);
}
else
{
if( solvertype==1 )
{
minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state);
}
else
{
if( solvertype==2 )
{
minqpsetalgodenseipm(&state, ipmeps, _state);
}
else
{
if( solvertype==3 )
{
minqpsetalgosparseipm(&state, ipmeps, _state);
}
else
{
ae_assert(ae_false, "unexpected solver type", _state);
}
}
}
}
minqpsetlinearterm(&state, &b, _state);
testminqpunit_randomlyselectconvertandsetquadraticterm(&rawa, n, &state, &rs, _state);
minqpsetbc(&state, &bndl, &bndu, _state);
testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, rawccnt, n, &state, &rs, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
/*
* Test
*
* Because constrained problems are often ill-conditioned,
* we do NOT compare X1 with XS directly. Instead, we:
* a) compare function values at X1 and XS with good precision
* b) check constraint violation with good precision
* c) perform comparison for |X1-XS| with LOW precision
*/
if( rep.terminationtype<=0 )
{
ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:3547");
ae_frame_leave(_state);
return;
}
f0 = (double)(0);
f1 = (double)(0);
for(i=0; i<=n-1; i++)
{
f0 = f0+b.ptr.p_double[i]*xs.ptr.p_double[i];
f1 = f1+b.ptr.p_double[i]*x1.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
f0 = f0+0.5*xs.ptr.p_double[i]*rawa.ptr.pp_double[i][j]*xs.ptr.p_double[j];
f1 = f1+0.5*x1.ptr.p_double[i]*rawa.ptr.pp_double[i][j]*x1.ptr.p_double[j];
}
}
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(f0-f1, _state),1.0E-3), __FILE__, __LINE__, "testminqpunit.ap:3562");
}
/*
* Inequality constrained convex problem:
* * N*N diagonal A
* * one inequality constraint q'*x>=0, where q is random unit vector
* * optimization problem has form 0.5*x'*A*x-(xs*A)*x,
* where xs is some random vector
* * either:
* a) xs is feasible => we must stop at xs
* b) xs is infeasible => we must stop at the boundary q'*x=0 and
* projection of gradient onto q*x=0 must be zero
*
* NOTE: we make several passes because some specific kind of errors is rarely
* caught by this test, so we need several repetitions.
*/
xtol = 1.0E-4;
gtol = 1.0E-4;
for(n=2; n<=6; n++)
{
for(pass=0; pass<=4; pass++)
{
/*
* Generate problem: A, b, CMatrix, x0, XStart
*/
spdmatrixrndcond(n, ae_pow(10.0, 3*ae_randomreal(_state), _state), &a, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&xs, n, _state);
ae_vector_set_length(&xstart, n, _state);
ae_matrix_set_length(&rawc, 1, n+1, _state);
ae_vector_set_length(&rawct, 1, _state);
for(i=0; i<=n-1; i++)
{
xs.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
xstart.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
do
{
v = (double)(0);
for(i=0; i<=n-1; i++)
{
rawc.ptr.pp_double[0][i] = 2*ae_randomreal(_state)-1;
v = v+ae_sqr(rawc.ptr.pp_double[0][i], _state);
}
v = ae_sqrt(v, _state);
}
while(ae_fp_eq(v,(double)(0)));
for(i=0; i<=n-1; i++)
{
rawc.ptr.pp_double[0][i] = rawc.ptr.pp_double[0][i]/v;
}
rawc.ptr.pp_double[0][n] = (double)(0);
rawct.ptr.p_int[0] = 1;
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xs.ptr.p_double[0], 1, ae_v_len(0,n-1));
b.ptr.p_double[i] = -v;
}
/*
* Create optimizer, solve
*/
minqpcreate(n, &state, _state);
if( solvertype==0 )
{
minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state);
}
else
{
if( solvertype==1 )
{
minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state);
}
else
{
if( solvertype==2 )
{
minqpsetalgodenseipm(&state, ipmeps, _state);
}
else
{
if( solvertype==3 )
{
minqpsetalgosparseipm(&state, ipmeps, _state);
}
else
{
ae_assert(ae_false, "unexpected solver type", _state);
}
}
}
}
minqpsetlinearterm(&state, &b, _state);
testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state, &rs, _state);
minqpsetstartingpoint(&state, &xstart, _state);
testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, 1, n, &state, &rs, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
/*
* Test
*/
if( rep.terminationtype<=0 )
{
ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:3645");
ae_frame_leave(_state);
return;
}
v = ae_v_dotproduct(&xs.ptr.p_double[0], 1, &rawc.ptr.pp_double[0][0], 1, ae_v_len(0,n-1));
if( ae_fp_greater_eq(v,(double)(0)) )
{
/*
* XS is feasible
*/
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-xs.ptr.p_double[i], _state),xtol), __FILE__, __LINE__, "testminqpunit.ap:3655");
}
}
else
{
/*
* XS is infeasible:
* * X1 must be approximately feasible
* * gradient projection onto c'*x=0 must be zero
*/
v = ae_v_dotproduct(&x1.ptr.p_double[0], 1, &rawc.ptr.pp_double[0][0], 1, ae_v_len(0,n-1));
ae_set_error_flag(errorflag, ae_fp_less(v,-xtol), __FILE__, __LINE__, "testminqpunit.ap:3665");
ae_vector_set_length(&g, n, _state);
ae_v_move(&g.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1));
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1));
g.ptr.p_double[i] = g.ptr.p_double[i]+v;
}
v = ae_v_dotproduct(&g.ptr.p_double[0], 1, &rawc.ptr.pp_double[0][0], 1, ae_v_len(0,n-1));
ae_v_subd(&g.ptr.p_double[0], 1, &rawc.ptr.pp_double[0][0], 1, ae_v_len(0,n-1), v);
v = ae_v_dotproduct(&g.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,n-1));
ae_set_error_flag(errorflag, ae_fp_greater(ae_sqrt(v, _state),gtol), __FILE__, __LINE__, "testminqpunit.ap:3676");
}
}
}
/*
* Box constraints vs linear ones:
* * N*N SPD A
* * optimization problem has form 0.5*x'*A*x-(x1*A)*x,
* where x1 is some random vector from [-1,+1]
* * K=2*N constraints of the form ai<=x[i] or x[i]<=b[i],
* with ai in [-1.0,-0.1], bi in [+0.1,+1.0]
* * initial point xstart is from [-1,+2]
* * we solve two related QP problems:
* a) one with constraints posed as boundary ones
* b) another one with same constraints posed as general linear ones
* both problems must have same solution.
* Here we test that boundary constrained and linear inequality constrained
* solvers give same results.
*/
xtol = 1.0E-5;
for(n=1; n<=6; n++)
{
/*
* Generate problem: A, b, x0, XStart, C, CT
*/
spdmatrixrndcond(n, ae_pow(10.0, 3*ae_randomreal(_state), _state), &a, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x1, n, _state);
ae_vector_set_length(&xstart, n, _state);
ae_matrix_set_length(&rawc, 2*n, n+1, _state);
ae_vector_set_length(&rawct, 2*n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
for(i=0; i<=n-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
xstart.ptr.p_double[i] = 3*ae_randomreal(_state)-1;
bndl.ptr.p_double[i] = -(0.1+0.9*ae_randomreal(_state));
bndu.ptr.p_double[i] = 0.1+0.9*ae_randomreal(_state);
for(j=0; j<=n-1; j++)
{
rawc.ptr.pp_double[2*i+0][j] = (double)(0);
rawc.ptr.pp_double[2*i+1][j] = (double)(0);
}
rawc.ptr.pp_double[2*i+0][i] = (double)(1);
rawc.ptr.pp_double[2*i+0][n] = bndl.ptr.p_double[i];
rawct.ptr.p_int[2*i+0] = 1;
rawc.ptr.pp_double[2*i+1][i] = (double)(1);
rawc.ptr.pp_double[2*i+1][n] = bndu.ptr.p_double[i];
rawct.ptr.p_int[2*i+1] = -1;
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1));
b.ptr.p_double[i] = -v;
}
/*
* Solve linear inequality constrained problem
*/
minqpcreate(n, &state, _state);
if( solvertype==0 )
{
minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state);
}
else
{
if( solvertype==1 )
{
minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state);
}
else
{
if( solvertype==2 )
{
minqpsetalgodenseipm(&state, ipmeps, _state);
}
else
{
if( solvertype==3 )
{
minqpsetalgosparseipm(&state, ipmeps, _state);
}
else
{
ae_assert(ae_false, "unexpected solver type", _state);
}
}
}
}
minqpsetlinearterm(&state, &b, _state);
testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state, &rs, _state);
minqpsetstartingpoint(&state, &xstart, _state);
testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, 2*n, n, &state, &rs, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
/*
* Solve boundary constrained problem
*/
minqpcreate(n, &state2, _state);
if( solvertype==0 )
{
minqpsetalgobleic(&state2, 0.0, 0.0, bleicepsx, 0, _state);
}
else
{
if( solvertype==1 )
{
minqpsetalgodenseaul(&state2, aulepsx, aulrho, aulits, _state);
}
else
{
if( solvertype==2 )
{
minqpsetalgodenseipm(&state2, ipmeps, _state);
}
else
{
if( solvertype==3 )
{
minqpsetalgosparseipm(&state2, ipmeps, _state);
}
else
{
ae_assert(ae_false, "unexpected solver type", _state);
}
}
}
}
minqpsetlinearterm(&state2, &b, _state);
testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state2, &rs, _state);
minqpsetstartingpoint(&state2, &xstart, _state);
minqpsetbc(&state2, &bndl, &bndu, _state);
minqpoptimize(&state2, _state);
minqpresults(&state2, &x2, &rep2, _state);
/*
* Calculate gradient, check projection
*/
if( rep.terminationtype<=0||rep2.terminationtype<=0 )
{
ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:3782");
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]-xtol), __FILE__, __LINE__, "testminqpunit.ap:3787");
ae_set_error_flag(errorflag, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]+xtol), __FILE__, __LINE__, "testminqpunit.ap:3788");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-x2.ptr.p_double[i], _state),xtol), __FILE__, __LINE__, "testminqpunit.ap:3789");
}
}
/*
* Convex/nonconvex optimization problem with combination of
* box and linear constraints:
*
* * N=2..8
* * f = 0.5*x'*A*x+b'*x
* * b has normally distributed entries with scale 10^BScale
* * several kinds of A are tried: zero, well conditioned SPD,
* well conditioned indefinite, low rank
* * box constraints: x[i] in [-1,+1]
* * initial point x0 = [0 0 ... 0 0]
* * CCnt=min(3,N-1) general linear constraints of form (c,x)=0.
* random mix of equality/inequality constraints is tried, moderate
* condition number is guaranteed, x0 is guaranteed to be feasible.
*
* We check that constrained gradient is close to zero at solution.
* Inequality constraint is considered active if distance to boundary
* is less than TolConstr. We use nonnegative least squares solver
* in order to compute constrained gradient.
*/
tolconstr = (double)(-99999);
for(n=2; n<=8; n++)
{
for(akind=0; akind<=4; akind++)
{
for(bscale=1; bscale>=-1; bscale--)
{
/*
* Dense-AUL solver has lower precision on rank-deficient
* problems, so we skip AKind=3.
*
* IPM solvers can not work with indefinite problems.
*/
if( solvertype==1&&akind==3 )
{
continue;
}
if( (solvertype==2||solvertype==3)&&(akind==2||akind==4) )
{
continue;
}
/*
* Set up tolerances
*/
if( solvertype==0 )
{
tolconstr = 1.0E-8;
}
else
{
if( (solvertype==1||solvertype==2)||solvertype==3 )
{
tolconstr = 1.0E-3;
if( akind==3 )
{
tolconstr = tolconstr*5;
}
}
else
{
ae_assert(ae_false, "unexpected solver type", _state);
}
}
gtol = 1.0E-4;
/*
* Generate A, B and initial point
*/
ae_matrix_set_length(&a, n, n, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&xstart, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = ae_pow((double)(10), (double)(bscale), _state)*hqrndnormal(&rs, _state);
xstart.ptr.p_double[i] = 0.0;
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
if( akind==1 )
{
/*
* Dense well conditioned SPD
*/
spdmatrixrndcond(n, 50.0, &a, _state);
}
if( akind==2 )
{
/*
* Dense well conditioned indefinite
*/
smatrixrndcond(n, 50.0, &a, _state);
}
if( akind==3 )
{
/*
* Low rank semidefinite
*/
ae_vector_set_length(&tmp, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
for(k=1; k<=ae_minint(3, n-1, _state); k++)
{
for(i=0; i<=n-1; i++)
{
tmp.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
v = ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j];
}
}
}
}
if( akind==4 )
{
/*
* Low rank indefinite
*/
ae_vector_set_length(&tmp, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
for(k=1; k<=ae_minint(3, n-1, _state); k++)
{
for(i=0; i<=n-1; i++)
{
tmp.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
v = hqrndnormal(&rs, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j];
}
}
}
}
/*
* Generate constraints
*/
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
for(i=0; i<=n-1; i++)
{
bndl.ptr.p_double[i] = -1.0;
bndu.ptr.p_double[i] = 1.0;
}
rawccnt = ae_minint(3, n-1, _state);
ae_matrix_set_length(&rawc, rawccnt, n+1, _state);
ae_vector_set_length(&rawct, rawccnt, _state);
do
{
for(i=0; i<=rawccnt-1; i++)
{
rawct.ptr.p_int[i] = hqrnduniformi(&rs, 3, _state)-1;
rawc.ptr.pp_double[i][n] = 0.0;
for(j=0; j<=n-1; j++)
{
rawc.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5;
}
}
}
while(ae_fp_less_eq(testminqpunit_getconstraintrcond(&rawc, rawccnt, n, _state),0.01));
/*
* Create and optimize
*/
minqpcreate(n, &state, _state);
minqpsetstartingpoint(&state, &xstart, _state);
if( solvertype==0 )
{
minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state);
}
else
{
if( solvertype==1 )
{
minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state);
}
else
{
if( solvertype==2 )
{
minqpsetalgodenseipm(&state, ipmeps, _state);
}
else
{
if( solvertype==3 )
{
minqpsetalgosparseipm(&state, ipmeps, _state);
}
else
{
ae_assert(ae_false, "unexpected solver type", _state);
}
}
}
}
minqpsetbc(&state, &bndl, &bndu, _state);
testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, rawccnt, n, &state, &rs, _state);
minqpsetlinearterm(&state, &b, _state);
testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state, &rs, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:3958");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
/*
* 1. evaluate unconstrained gradient at solution
*
* 2. calculate constrained gradient (NNLS solver is used
* to evaluate gradient subject to active constraints).
* In order to do this we form CE matrix, matrix of active
* constraints (columns store constraint vectors). Then
* we try to approximate gradient vector by columns of CE,
* subject to non-negativity restriction placed on variables
* corresponding to inequality constraints.
*
* Residual from such regression is a constrained gradient vector.
*/
ae_vector_set_length(&g, n, _state);
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1));
g.ptr.p_double[i] = v+b.ptr.p_double[i];
}
ae_matrix_set_length(&ce, n, n+rawccnt, _state);
ae_vector_set_length(&nonnegative, n+rawccnt, _state);
k = 0;
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:3986");
ae_set_error_flag(errorflag, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminqpunit.ap:3987");
if( ae_fp_less_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i]+tolconstr) )
{
for(j=0; j<=n-1; j++)
{
ce.ptr.pp_double[j][k] = 0.0;
}
ce.ptr.pp_double[i][k] = 1.0;
nonnegative.ptr.p_bool[k] = ae_true;
inc(&k, _state);
continue;
}
if( ae_fp_greater_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i]-tolconstr) )
{
for(j=0; j<=n-1; j++)
{
ce.ptr.pp_double[j][k] = 0.0;
}
ce.ptr.pp_double[i][k] = -1.0;
nonnegative.ptr.p_bool[k] = ae_true;
inc(&k, _state);
continue;
}
}
for(i=0; i<=rawccnt-1; i++)
{
v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = v-rawc.ptr.pp_double[i][n];
ae_set_error_flag(errorflag, rawct.ptr.p_int[i]==0&&ae_fp_greater(ae_fabs(v, _state),tolconstr), __FILE__, __LINE__, "testminqpunit.ap:4011");
ae_set_error_flag(errorflag, rawct.ptr.p_int[i]>0&&ae_fp_less(v,-tolconstr), __FILE__, __LINE__, "testminqpunit.ap:4012");
ae_set_error_flag(errorflag, rawct.ptr.p_int[i]<0&&ae_fp_greater(v,tolconstr), __FILE__, __LINE__, "testminqpunit.ap:4013");
if( rawct.ptr.p_int[i]==0 )
{
for(j=0; j<=n-1; j++)
{
ce.ptr.pp_double[j][k] = rawc.ptr.pp_double[i][j];
}
nonnegative.ptr.p_bool[k] = ae_false;
inc(&k, _state);
continue;
}
if( (rawct.ptr.p_int[i]>0&&ae_fp_less_eq(v,tolconstr))||(rawct.ptr.p_int[i]<0&&ae_fp_greater_eq(v,-tolconstr)) )
{
for(j=0; j<=n-1; j++)
{
ce.ptr.pp_double[j][k] = ae_sign((double)(rawct.ptr.p_int[i]), _state)*rawc.ptr.pp_double[i][j];
}
nonnegative.ptr.p_bool[k] = ae_true;
inc(&k, _state);
continue;
}
}
snnlsinit(0, 0, 0, &nnls, _state);
snnlssetproblem(&nnls, &ce, &g, 0, k, n, _state);
for(i=0; i<=k-1; i++)
{
if( !nonnegative.ptr.p_bool[i] )
{
snnlsdropnnc(&nnls, i, _state);
}
}
snnlssolve(&nnls, &tmp, _state);
for(i=0; i<=k-1; i++)
{
for(j=0; j<=n-1; j++)
{
g.ptr.p_double[j] = g.ptr.p_double[j]-tmp.ptr.p_double[i]*ce.ptr.pp_double[j][i];
}
}
vv = ae_v_dotproduct(&g.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,n-1));
vv = ae_sqrt(vv, _state);
ae_set_error_flag(errorflag, ae_fp_greater(vv,gtol), __FILE__, __LINE__, "testminqpunit.ap:4042");
}
}
}
/*
* Boundary and linear equality/inequality constrained QP problem,
* test for correct handling of non-zero XOrigin:
* * N*N SPD A with moderate condtion number (up to 100)
* * boundary constraints 0<=x[i]<=1
* * K0 )
{
rawc.ptr.pp_double[i][n] = rawc.ptr.pp_double[i][n]-0.1;
}
}
testminqpunit_randomlysplitlc(&rawc, &rawct, k, n, &sparsec, &sparsect, &sparseccnt, &densec, &densect, &denseccnt, &rs, _state);
minqpcreate(n, &state, _state);
state.dbgskipconstraintnormalization = ae_true;
if( solvertype==0 )
{
minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state);
}
else
{
if( solvertype==1 )
{
minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state);
}
else
{
if( solvertype==2 )
{
minqpsetalgodenseipm(&state, ipmeps, _state);
}
else
{
if( solvertype==3 )
{
minqpsetalgosparseipm(&state, ipmeps, _state);
}
else
{
ae_assert(ae_false, "unexpected solver type", _state);
}
}
}
}
minqpsetlinearterm(&state, &b, _state);
testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state, &rs, _state);
minqpsetstartingpoint(&state, &xstart, _state);
minqpsetorigin(&state, &xorigin, _state);
minqpsetbc(&state, &bndl, &bndu, _state);
minqpsetlcmixed(&state, &sparsec, &sparsect, sparseccnt, &densec, &densect, denseccnt, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:4303");
continue;
}
/*
* Scale problem and solve one more time.
* Randomly choose between dense and sparse versions.
*/
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = ae_pow((double)(2), (double)(hqrnduniformi(&rs, 7, _state)-3), _state);
}
akind = hqrnduniformi(&rs, 2, _state);
if( akind==0 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]);
}
}
}
else
{
sparsecreate(n, n, 0, &sa, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
sparseset(&sa, i, j, a.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]), _state);
}
}
}
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i];
xstart.ptr.p_double[i] = xstart.ptr.p_double[i]*s.ptr.p_double[i];
xorigin.ptr.p_double[i] = xorigin.ptr.p_double[i]*s.ptr.p_double[i];
bndl.ptr.p_double[i] = bndl.ptr.p_double[i]*s.ptr.p_double[i];
bndu.ptr.p_double[i] = bndu.ptr.p_double[i]*s.ptr.p_double[i];
}
for(i=0; i<=denseccnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
densec.ptr.pp_double[i][j] = densec.ptr.pp_double[i][j]/s.ptr.p_double[j];
}
}
for(i=0; i<=sparseccnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
sparseset(&sparsec, i, j, sparseget(&sparsec, i, j, _state)/s.ptr.p_double[j], _state);
}
}
minqpcreate(n, &state, _state);
state.dbgskipconstraintnormalization = ae_true;
if( solvertype==0 )
{
minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state);
}
else
{
if( solvertype==1 )
{
minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state);
}
else
{
if( solvertype==2 )
{
minqpsetalgodenseipm(&state, ipmeps, _state);
}
else
{
if( solvertype==3 )
{
minqpsetalgosparseipm(&state, ipmeps, _state);
}
else
{
ae_assert(ae_false, "unexpected solver type", _state);
}
}
}
}
minqpsetlinearterm(&state, &b, _state);
if( akind==0 )
{
minqpsetquadraticterm(&state, &a, ae_fp_greater(ae_randomreal(_state),0.5), _state);
}
if( akind==1 )
{
minqpsetquadratictermsparse(&state, &sa, ae_fp_greater(ae_randomreal(_state),0.5), _state);
}
minqpsetstartingpoint(&state, &xstart, _state);
minqpsetorigin(&state, &xorigin, _state);
minqpsetbc(&state, &bndl, &bndu, _state);
minqpsetlcmixed(&state, &sparsec, &sparsect, sparseccnt, &densec, &densect, denseccnt, _state);
minqpsetscale(&state, &s, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x2, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:4368");
continue;
}
/*
* Compare
*/
mx = (double)(0);
for(i=0; i<=n-1; i++)
{
mx = ae_maxreal(mx, ae_fabs(x1.ptr.p_double[i], _state), _state);
}
mx = ae_maxreal(mx, (double)(1), _state);
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-x2.ptr.p_double[i]/s.ptr.p_double[i], _state),xtol*mx), __FILE__, __LINE__, "testminqpunit.ap:4380");
}
}
}
/*
* General inequality constrained problem:
* * N*N SPD diagonal A with moderate condtion number
* * no boundary constraints
* * K=N inequality constraints C*x >= C*x0, where C is N*N well conditioned
* matrix, x0 is some random vector [-1,+1]
* * optimization problem has form 0.5*x'*A*x-b'*x,
* where b is random vector from [-1,+1]
* * using duality, we can obtain solution of QP problem as follows:
* a) intermediate problem min(0.5*y'*B*y + d'*y) s.t. y>=0
* is solved, where B = C*inv(A)*C', d = -(C*inv(A)*b + C*x0)
* b) after we got dual solution ys, we calculate primal solution
* xs = inv(A)*(C'*ys-b)
*/
for(n=1; n<=6; n++)
{
/*
* Set up tolerances
*/
if( solvertype==0 )
{
xtol = 1.0E-5;
}
else
{
if( (solvertype==1||solvertype==2)||solvertype==3 )
{
xtol = 1.0E-3;
}
else
{
ae_assert(ae_false, "unexpected solver type", _state);
}
}
/*
* Generate problem
*/
ae_vector_set_length(&da, n, _state);
ae_matrix_set_length(&a, n, n, _state);
rmatrixrndcond(n, ae_pow(10.0, 2*ae_randomreal(_state), _state), &t2, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xstart, n, _state);
ae_matrix_set_length(&rawc, n, n+1, _state);
ae_vector_set_length(&rawct, n, _state);
for(i=0; i<=n-1; i++)
{
da.ptr.p_double[i] = ae_exp(6*ae_randomreal(_state)-3, _state);
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
a.ptr.pp_double[i][i] = da.ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
xstart.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=n-1; i++)
{
ae_v_move(&rawc.ptr.pp_double[i][0], 1, &t2.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1));
rawc.ptr.pp_double[i][n] = v;
rawct.ptr.p_int[i] = 1;
}
/*
* Solve primal problem, check feasibility
*/
minqpcreate(n, &state, _state);
if( solvertype==0 )
{
minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state);
}
else
{
if( solvertype==1 )
{
minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state);
}
else
{
if( solvertype==2 )
{
minqpsetalgodenseipm(&state, ipmeps, _state);
}
else
{
if( solvertype==3 )
{
minqpsetalgosparseipm(&state, ipmeps, _state);
}
else
{
ae_assert(ae_false, "unexpected solver type", _state);
}
}
}
}
minqpsetlinearterm(&state, &b, _state);
testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state, &rs, _state);
minqpsetstartingpoint(&state, &xstart, _state);
minqpsetlc(&state, &rawc, &rawct, n, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:4468");
continue;
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&x1.ptr.p_double[0], 1, &rawc.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
ae_set_error_flag(errorflag, ae_fp_less(v,rawc.ptr.pp_double[i][n]-xtol), __FILE__, __LINE__, "testminqpunit.ap:4474");
}
/*
* Generate dual problem:
* * A2 stores new quadratic term
* * B2 stores new linear term
* * BndL/BndU store boundary constraints
*/
ae_matrix_set_length(&t3, n, n, _state);
ae_matrix_set_length(&a2, n, n, _state);
rmatrixtranspose(n, n, &rawc, 0, 0, &t3, 0, 0, _state);
for(i=0; i<=n-1; i++)
{
v = 1/ae_sqrt(da.ptr.p_double[i], _state);
ae_v_muld(&t3.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v);
}
rmatrixsyrk(n, n, 1.0, &t3, 0, 0, 2, 0.0, &a2, 0, 0, ae_true, _state);
ae_vector_set_length(&tmp0, n, _state);
ae_v_move(&tmp0.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1));
for(i=0; i<=n-1; i++)
{
tmp0.ptr.p_double[i] = tmp0.ptr.p_double[i]/da.ptr.p_double[i];
}
ae_vector_set_length(&b2, n, _state);
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &tmp0.ptr.p_double[0], 1, ae_v_len(0,n-1));
b2.ptr.p_double[i] = -(v+rawc.ptr.pp_double[i][n]);
}
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
for(i=0; i<=n-1; i++)
{
bndl.ptr.p_double[i] = 0.0;
bndu.ptr.p_double[i] = _state->v_posinf;
}
minqpcreate(n, &state2, _state);
minqpsetalgoquickqp(&state2, 0.0, 0.0, 1.0E-9, 0, ae_true, _state);
minqpsetlinearterm(&state2, &b2, _state);
minqpsetquadraticterm(&state2, &a2, ae_true, _state);
minqpsetbc(&state2, &bndl, &bndu, _state);
minqpoptimize(&state2, _state);
minqpresults(&state2, &x2, &rep2, _state);
if( rep2.terminationtype<=0 )
{
ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:4529");
continue;
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&rawc.ptr.pp_double[0][i], rawc.stride, &x2.ptr.p_double[0], 1, ae_v_len(0,n-1));
tmp0.ptr.p_double[i] = v-b.ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
tmp0.ptr.p_double[i] = tmp0.ptr.p_double[i]/da.ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(tmp0.ptr.p_double[i]-x1.ptr.p_double[i], _state),xtol*ae_maxreal(ae_fabs(tmp0.ptr.p_double[i], _state), 1.0, _state)), __FILE__, __LINE__, "testminqpunit.ap:4542");
}
}
/*
* Boundary and linear equality/inequality constrained QP problem with
* excessive constraints:
* * N*N SPD A with moderate condtion number (up to 100)
* * boundary constraints 0<=x[i]<=1
* * K=2*N equality/inequality constraints Q*x = Q*x0, where Q is random matrix,
* x0 is some random vector from the feasible hypercube (0.1<=x0[i]<=0.9)
* * optimization problem has form 0.5*x'*A*x-b*x,
* where b is some random vector
* * because constraints are excessive, the main problem is to find
* feasible point; usually, the only existing feasible point is solution,
* so we have to check only feasibility
*/
for(n=1; n<=6; n++)
{
/*
* Set up tolerances
*/
if( solvertype==0 )
{
xtol = 1.0E-5;
}
else
{
if( (solvertype==1||solvertype==2)||solvertype==3 )
{
xtol = 5.0E-3;
}
else
{
ae_assert(ae_false, "unexpected solver type", _state);
}
}
/*
* Generate problem: A, b, BndL, BndU, CMatrix, x0, x1, XStart
*/
k = 2*n;
spdmatrixrndcond(n, ae_pow(10.0, 3*ae_randomreal(_state), _state), &a, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&x1, n, _state);
ae_vector_set_length(&xstart, n, _state);
ae_matrix_set_length(&rawc, k, n+1, _state);
ae_vector_set_length(&rawct, k, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 0.1+0.8*ae_randomreal(_state);
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
bndl.ptr.p_double[i] = 0.0;
bndu.ptr.p_double[i] = 1.0;
xstart.ptr.p_double[i] = (double)(ae_randominteger(2, _state));
}
for(i=0; i<=k-1; i++)
{
for(j=0; j<=n-1; j++)
{
rawc.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1));
rawct.ptr.p_int[i] = ae_randominteger(3, _state)-1;
if( rawct.ptr.p_int[i]==0 )
{
rawc.ptr.pp_double[i][n] = v;
}
if( rawct.ptr.p_int[i]>0 )
{
rawc.ptr.pp_double[i][n] = v-50*xtol;
}
if( rawct.ptr.p_int[i]<0 )
{
rawc.ptr.pp_double[i][n] = v+50*xtol;
}
}
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
/*
* Create optimizer, solve
*/
minqpcreate(n, &state, _state);
if( solvertype==0 )
{
minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state);
}
else
{
if( solvertype==1 )
{
minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state);
}
else
{
if( solvertype==2 )
{
minqpsetalgodenseipm(&state, ipmeps, _state);
}
else
{
if( solvertype==3 )
{
minqpsetalgosparseipm(&state, ipmeps, _state);
}
else
{
ae_assert(ae_false, "unexpected solver type", _state);
}
}
}
}
minqpsetlinearterm(&state, &b, _state);
testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state, &rs, _state);
minqpsetstartingpoint(&state, &xstart, _state);
minqpsetbc(&state, &bndl, &bndu, _state);
testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, k, n, &state, &rs, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
/*
* Check feasibility properties of the solution
*/
if( rep.terminationtype<=0 )
{
ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:4640");
continue;
}
for(i=0; i<=k-1; i++)
{
v = ae_v_dotproduct(&x1.ptr.p_double[0], 1, &rawc.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
if( rawct.ptr.p_int[i]==0 )
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v-rawc.ptr.pp_double[i][n], _state),xtol), __FILE__, __LINE__, "testminqpunit.ap:4647");
}
if( rawct.ptr.p_int[i]>0 )
{
ae_set_error_flag(errorflag, ae_fp_less(v,rawc.ptr.pp_double[i][n]-xtol), __FILE__, __LINE__, "testminqpunit.ap:4649");
}
if( rawct.ptr.p_int[i]<0 )
{
ae_set_error_flag(errorflag, ae_fp_greater(v,rawc.ptr.pp_double[i][n]+xtol), __FILE__, __LINE__, "testminqpunit.ap:4651");
}
}
}
/*
* Boundary constraints posed as general linear ones:
* * no bound constraints
* * 2*N linear constraints 0 <= x[i] <= 1
* * F(x) = |x-x0|^P, where P={2,4} and x0 is randomly selected from [-1,+2]^N
* * with such simple constraints and function it is easy to find
* analytic form of solution: S[i] = bound(x0[i], 0, 1).
* * however, we can't guarantee that solution is strictly feasible
* with respect to nonlinearity constraint, so we check
* for approximate feasibility.
*/
for(n=1; n<=5; n++)
{
/*
* Set up tolerances
*/
if( solvertype==0 )
{
xtol = 1.0E-3;
}
else
{
if( (solvertype==1||solvertype==2)||solvertype==3 )
{
xtol = 1.0E-3;
}
else
{
ae_assert(ae_false, "unexpected solver type", _state);
}
}
/*
* Generate X, BL, BU.
*/
ae_matrix_set_length(&a, n, n, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&xstart, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_matrix_set_length(&rawc, 2*n, n+1, _state);
ae_vector_set_length(&rawct, 2*n, _state);
k = 2*n;
for(i=0; i<=n-1; i++)
{
xstart.ptr.p_double[i] = ae_randomreal(_state);
x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1;
b.ptr.p_double[i] = -x0.ptr.p_double[i];
for(j=0; j<=n; j++)
{
rawc.ptr.pp_double[2*i+0][j] = (double)(0);
rawc.ptr.pp_double[2*i+1][j] = (double)(0);
}
rawc.ptr.pp_double[2*i+0][i] = (double)(1);
rawc.ptr.pp_double[2*i+0][n] = (double)(0);
rawct.ptr.p_int[2*i+0] = 1;
rawc.ptr.pp_double[2*i+1][i] = (double)(1);
rawc.ptr.pp_double[2*i+1][n] = (double)(1);
rawct.ptr.p_int[2*i+1] = -1;
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( i==j )
{
a.ptr.pp_double[i][j] = (double)(1);
}
else
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
}
/*
* Create and optimize
*/
minqpcreate(n, &state, _state);
if( solvertype==0 )
{
minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state);
}
else
{
if( solvertype==1 )
{
minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state);
}
else
{
if( solvertype==2 )
{
minqpsetalgodenseipm(&state, ipmeps, _state);
}
else
{
if( solvertype==3 )
{
minqpsetalgosparseipm(&state, ipmeps, _state);
}
else
{
ae_assert(ae_false, "unexpected solver type", _state);
}
}
}
}
testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, k, n, &state, &rs, _state);
minqpsetlinearterm(&state, &b, _state);
testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state, &rs, _state);
minqpsetstartingpoint(&state, &xstart, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:4738");
continue;
}
/*
* * compare solution with analytic one
* * check feasibility
*/
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-boundval(x0.ptr.p_double[i], 0.0, 1.0, _state), _state),xtol), __FILE__, __LINE__, "testminqpunit.ap:4748");
ae_set_error_flag(errorflag, ae_fp_less(x1.ptr.p_double[i],0.0-xtol), __FILE__, __LINE__, "testminqpunit.ap:4749");
ae_set_error_flag(errorflag, ae_fp_greater(x1.ptr.p_double[i],1.0+xtol), __FILE__, __LINE__, "testminqpunit.ap:4750");
}
}
/*
* Convex optimization problem with excessive constraints:
*
* * N=2..5
* * f = 0.5*x'*A*x+b'*x
* * b has normally distributed entries
* * A is diagonal with log-normally distributed entries
* * box constraints: x[i] in [-1,+1]
* * 2^N "excessive" general linear constraints (v_k,x)<=(v_k,v_k)+v_shift,
* where v_k is one of 2^N vertices of feasible hypercube, v_shift is
* a shift parameter:
* * with zero v_shift such constraints are degenerate (each vertex has
* N box constraints and one "redundant" linear constraint)
* * with positive v_shift linear constraint is always inactive
* * with small (about machine epsilon) but negative v_shift,
* constraint is close to degenerate - but not exactly
*
* Because A is diagonal, we can easily find out solution analytically.
*
* NOTE: TolConstr must be large enough so it won't conflict with
* perturbation introduced by v_shift
*/
for(n=2; n<=5; n++)
{
for(shiftkind=-5; shiftkind<=1; shiftkind++)
{
/*
* Set up tolerances
*/
if( solvertype==0 )
{
tolconstr = 1.0E-6;
gtol = 1.0E-6;
}
else
{
if( (solvertype==1||solvertype==2)||solvertype==3 )
{
tolconstr = 1.0E-4;
gtol = 1.0E-4;
}
else
{
ae_assert(ae_false, "unexpected solver type", _state);
}
}
/*
* Generate A, B and initial point
*/
ae_matrix_set_length(&a, n, n, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&xstart, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
xstart.ptr.p_double[i] = hqrnduniformr(&rs, _state)-0.5;
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
a.ptr.pp_double[i][i] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
}
/*
* Generate constraints
*/
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
for(i=0; i<=n-1; i++)
{
bndl.ptr.p_double[i] = -1.0;
bndu.ptr.p_double[i] = 1.0;
}
rawccnt = ae_round(ae_pow((double)(2), (double)(n), _state), _state);
ae_matrix_set_length(&rawc, rawccnt, n+1, _state);
ae_vector_set_length(&rawct, rawccnt, _state);
for(i=0; i<=rawccnt-1; i++)
{
rawct.ptr.p_int[i] = -1;
k = i;
rawc.ptr.pp_double[i][n] = ae_sign((double)(shiftkind), _state)*ae_pow((double)(10), ae_fabs((double)(shiftkind), _state), _state)*ae_machineepsilon;
for(j=0; j<=n-1; j++)
{
rawc.ptr.pp_double[i][j] = (double)(2*(k%2)-1);
rawc.ptr.pp_double[i][n] = rawc.ptr.pp_double[i][n]+rawc.ptr.pp_double[i][j]*rawc.ptr.pp_double[i][j];
k = k/2;
}
}
/*
* Create and optimize
*/
minqpcreate(n, &state, _state);
minqpsetstartingpoint(&state, &xstart, _state);
if( solvertype==0 )
{
minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state);
}
else
{
if( solvertype==1 )
{
minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state);
}
else
{
if( solvertype==2 )
{
minqpsetalgodenseipm(&state, ipmeps, _state);
}
else
{
if( solvertype==3 )
{
minqpsetalgosparseipm(&state, ipmeps, _state);
}
else
{
ae_assert(ae_false, "unexpected solver type", _state);
}
}
}
}
minqpsetbc(&state, &bndl, &bndu, _state);
testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, rawccnt, n, &state, &rs, _state);
minqpsetlinearterm(&state, &b, _state);
testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state, &rs, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:4861");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
/*
* Evaluate gradient at solution and test
*/
vv = 0.0;
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = v+b.ptr.p_double[i];
if( ae_fp_less_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i]+tolconstr)&&ae_fp_greater(v,(double)(0)) )
{
v = 0.0;
}
if( ae_fp_greater_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i]-tolconstr)&&ae_fp_less(v,(double)(0)) )
{
v = 0.0;
}
vv = vv+ae_sqr(v, _state);
}
vv = ae_sqrt(vv, _state);
ae_set_error_flag(errorflag, ae_fp_greater(vv,gtol), __FILE__, __LINE__, "testminqpunit.ap:4885");
}
}
/*
* Convex optimization problem with known answer (we generate constraints
* and Lagrange coefficients, and then generate quadratic and linear term
* which satisfy KKT conditions for given Lagrange coefficients):
*
* * N=2..8
* * f = 0.5*x'*A*x+b'*x
* * several kinds of A are tried: zero, well conditioned SPD, low rank
* * initial point x0 = [0 0 ... 0 0]
* * first, we generate set of linear constraints (without bounds),
* solution point X and Lagrange multipliers for linear and box constraints
* * then we determine bounds on variables and linear constraints which
* align with values/signs of Lagrange multipliers
* * then, having quadratic term A and known constraints and Lagrange
* multipliers we determine linear term B which makes KKT conditions true
*/
for(n=1; n<=8; n++)
{
for(akind=0; akind<=2; akind++)
{
/*
* Generate quadratic term A, origin and scale
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
issemidefinite = ae_true;
if( akind==1 )
{
/*
* Dense well conditioned SPD
*/
spdmatrixrndcond(n, 50.0, &a, _state);
issemidefinite = ae_false;
}
if( akind==2 )
{
/*
* Low rank semidefinite
*/
ae_vector_set_length(&tmp, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
for(k=1; k<=ae_minint(3, n-1, _state); k++)
{
for(i=0; i<=n-1; i++)
{
tmp.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
v = ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j];
}
}
}
issemidefinite = ae_true;
}
ae_vector_set_length(&s, n, _state);
ae_vector_set_length(&xorigin, n, _state);
for(j=0; j<=n-1; j++)
{
xorigin.ptr.p_double[j] = hqrndnormal(&rs, _state);
s.ptr.p_double[j] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
}
/*
* Generate linear constraints (left parts)
*/
rawccnt = hqrnduniformi(&rs, 2*n+1, _state);
ae_matrix_set_length(&rawc, rawccnt, n, _state);
for(i=0; i<=rawccnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
rawc.ptr.pp_double[i][j] = (double)(0);
}
nnz = hqrnduniformi(&rs, n+1, _state);
for(k=0; k<=nnz-1; k++)
{
j = hqrnduniformi(&rs, n, _state);
v = hqrndnormal(&rs, _state);
v = v+0.1*possign(v, _state);
rawc.ptr.pp_double[i][j] = v;
}
}
/*
* Generate Lagrange multipliers, with at most NActivev_neginf;
bndu.ptr.p_double[j] = _state->v_posinf;
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0))||issemidefinite )
{
bndl.ptr.p_double[j] = xf.ptr.p_double[j]-ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
}
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0))||issemidefinite )
{
bndu.ptr.p_double[j] = xf.ptr.p_double[j]+ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
}
if( ae_fp_neq(lagbc.ptr.p_double[j],(double)(0)) )
{
if( ae_fp_less(hqrnduniformr(&rs, _state),0.15) )
{
bndl.ptr.p_double[j] = xf.ptr.p_double[j];
bndu.ptr.p_double[j] = xf.ptr.p_double[j];
}
else
{
if( ae_fp_less(lagbc.ptr.p_double[j],(double)(0)) )
{
bndl.ptr.p_double[j] = xf.ptr.p_double[j];
}
if( ae_fp_greater(lagbc.ptr.p_double[j],(double)(0)) )
{
bndu.ptr.p_double[j] = xf.ptr.p_double[j];
}
}
}
}
ae_vector_set_length(&rawcl, rawccnt, _state);
ae_vector_set_length(&rawcu, rawccnt, _state);
for(i=0; i<=rawccnt-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+rawc.ptr.pp_double[i][j]*xf.ptr.p_double[j];
}
rawcl.ptr.p_double[i] = _state->v_neginf;
rawcu.ptr.p_double[i] = _state->v_posinf;
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
rawcl.ptr.p_double[i] = v-ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
}
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
rawcu.ptr.p_double[i] = v+ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
}
if( ae_fp_neq(laglc.ptr.p_double[i],(double)(0)) )
{
if( ae_fp_less(hqrnduniformr(&rs, _state),0.15) )
{
/*
* Active equality constraint
*/
rawcl.ptr.p_double[i] = v;
rawcu.ptr.p_double[i] = v;
}
else
{
/*
* Active inequality constraint
*/
if( ae_fp_less(laglc.ptr.p_double[i],(double)(0)) )
{
rawcl.ptr.p_double[i] = v;
}
if( ae_fp_greater(laglc.ptr.p_double[i],(double)(0)) )
{
rawcu.ptr.p_double[i] = v;
}
}
}
if( !ae_isfinite(rawcl.ptr.p_double[i], _state)&&!ae_isfinite(rawcu.ptr.p_double[i], _state) )
{
/*
* At least one bound must be present for linear constraint
*/
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
rawcl.ptr.p_double[i] = v-10;
}
else
{
rawcu.ptr.p_double[i] = v+10;
}
}
}
/*
* Completely skip some solvers depending on their properties:
* * Dense-AUL solver has lower precision on rank-deficient
* problems, so we skip AKind=0 and AKind=2.
* * BLEIC solver is always skipped
*/
if( solvertype==1&&akind!=1 )
{
continue;
}
if( solvertype==0 )
{
continue;
}
/*
* Solve
*/
minqpcreate(n, &state, _state);
if( solvertype==0 )
{
minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state);
}
else
{
if( solvertype==1 )
{
minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state);
}
else
{
if( solvertype==2 )
{
minqpsetalgodenseipm(&state, ipmeps, _state);
}
else
{
if( solvertype==3 )
{
minqpsetalgosparseipm(&state, ipmeps, _state);
}
else
{
ae_assert(ae_false, "unexpected solver type", _state);
}
}
}
}
minqpsetbc(&state, &bndl, &bndu, _state);
testminqpunit_randomlysplitandsetlc2(&rawc, &rawcl, &rawcu, rawccnt, n, &state, &rs, _state);
minqpsetlinearterm(&state, &b, _state);
testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state, &rs, _state);
minqpsetscale(&state, &s, _state);
minqpsetorigin(&state, &xorigin, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:5120");
ae_set_error_flag(errorflag, x1.cnt= C*x0, where C is N*N well conditioned
* matrix, x0 is some random vector [-1,+1]
* * optimization problem has form 0.5*x'*A*x-b'*x,
* where b is random vector from [-1,+1]
* * using duality, we can obtain solution of QP problem as follows:
* a) intermediate problem min(0.5*y'*B*y + d'*y) s.t. y>=0
* is solved, where B = C*inv(A)*C', d = -(C*inv(A)*b + C*x0)
* b) after we got dual solution ys, we calculate primal solution
* xs = inv(A)*(C'*ys-b)
*/
n = 60;
rawccnt = 40;
if( solvertype==0 )
{
xtol = 1.0E-3;
}
else
{
if( (solvertype==1||solvertype==2)||solvertype==3 )
{
xtol = 1.0E-3;
}
else
{
ae_assert(ae_false, "unexpected solver type", _state);
}
}
ae_vector_set_length(&da, n, _state);
ae_matrix_set_length(&a, n, n, _state);
rmatrixrndcond(n, ae_pow(10.0, 2*ae_randomreal(_state), _state), &t2, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xstart, n, _state);
ae_matrix_set_length(&rawc, rawccnt, n+1, _state);
ae_vector_set_length(&rawct, rawccnt, _state);
for(i=0; i<=n-1; i++)
{
da.ptr.p_double[i] = ae_exp(8*ae_randomreal(_state)-4, _state);
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
a.ptr.pp_double[i][i] = da.ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
xstart.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=rawccnt-1; i++)
{
ae_v_move(&rawc.ptr.pp_double[i][0], 1, &t2.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1));
rawc.ptr.pp_double[i][n] = v;
rawct.ptr.p_int[i] = 1;
}
minqpcreate(n, &state, _state);
if( solvertype==0 )
{
minqpsetalgobleic(&state, 0.0, 0.0, bleicepsx, 0, _state);
}
else
{
if( solvertype==1 )
{
minqpsetalgodenseaul(&state, aulepsx, aulrho, aulits, _state);
}
else
{
if( solvertype==2 )
{
minqpsetalgodenseipm(&state, ipmeps, _state);
}
else
{
if( solvertype==3 )
{
minqpsetalgosparseipm(&state, ipmeps, _state);
}
else
{
ae_assert(ae_false, "unexpected solver type", _state);
}
}
}
}
minqpsetlinearterm(&state, &b, _state);
testminqpunit_randomlyselectconvertandsetquadraticterm(&a, n, &state, &rs, _state);
minqpsetstartingpoint(&state, &xstart, _state);
testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, rawccnt, n, &state, &rs, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &x1, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:5344");
continue;
}
for(i=0; i<=rawccnt-1; i++)
{
v = ae_v_dotproduct(&x1.ptr.p_double[0], 1, &rawc.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
ae_set_error_flag(errorflag, ae_fp_less(v,rawc.ptr.pp_double[i][n]-xtol), __FILE__, __LINE__, "testminqpunit.ap:5350");
}
ae_matrix_set_length(&t3, n, rawccnt, _state);
ae_matrix_set_length(&a2, rawccnt, rawccnt, _state);
rmatrixtranspose(rawccnt, n, &rawc, 0, 0, &t3, 0, 0, _state);
for(i=0; i<=n-1; i++)
{
v = 1/ae_sqrt(da.ptr.p_double[i], _state);
ae_v_muld(&t3.ptr.pp_double[i][0], 1, ae_v_len(0,rawccnt-1), v);
}
rmatrixsyrk(rawccnt, n, 1.0, &t3, 0, 0, 2, 0.0, &a2, 0, 0, ae_true, _state);
ae_vector_set_length(&tmp0, n, _state);
ae_v_move(&tmp0.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1));
for(i=0; i<=n-1; i++)
{
tmp0.ptr.p_double[i] = tmp0.ptr.p_double[i]/da.ptr.p_double[i];
}
ae_vector_set_length(&b2, rawccnt, _state);
for(i=0; i<=rawccnt-1; i++)
{
v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &tmp0.ptr.p_double[0], 1, ae_v_len(0,n-1));
b2.ptr.p_double[i] = -(v+rawc.ptr.pp_double[i][n]);
}
ae_vector_set_length(&bndl, rawccnt, _state);
ae_vector_set_length(&bndu, rawccnt, _state);
for(i=0; i<=rawccnt-1; i++)
{
bndl.ptr.p_double[i] = 0.0;
bndu.ptr.p_double[i] = _state->v_posinf;
}
minqpcreate(rawccnt, &state2, _state);
minqpsetalgoquickqp(&state2, 0.0, 0.0, 1.0E-9, 0, ae_true, _state);
minqpsetlinearterm(&state2, &b2, _state);
minqpsetquadraticterm(&state2, &a2, ae_true, _state);
minqpsetbc(&state2, &bndl, &bndu, _state);
minqpoptimize(&state2, _state);
minqpresults(&state2, &x2, &rep2, _state);
if( rep2.terminationtype<=0 )
{
ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:5403");
continue;
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&rawc.ptr.pp_double[0][i], rawc.stride, &x2.ptr.p_double[0], 1, ae_v_len(0,rawccnt-1));
tmp0.ptr.p_double[i] = v-b.ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
tmp0.ptr.p_double[i] = tmp0.ptr.p_double[i]/da.ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(tmp0.ptr.p_double[i]-x1.ptr.p_double[i], _state),xtol*ae_maxreal(ae_fabs(tmp0.ptr.p_double[i], _state), 1.0, _state)), __FILE__, __LINE__, "testminqpunit.ap:5416");
}
}
ae_frame_leave(_state);
}
/*************************************************************************
This function tests special inequality constrained QP problems.
Returns True on errors.
*************************************************************************/
static ae_bool testminqpunit_specialicqptests(ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_matrix c;
ae_vector xstart;
ae_vector xend;
ae_vector xexact;
ae_vector b;
ae_vector bndl;
ae_vector bndu;
ae_vector ct;
minqpstate state;
minqpreport rep;
ae_bool waserrors;
ae_int_t i;
ae_int_t j;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&c, 0, sizeof(c));
memset(&xstart, 0, sizeof(xstart));
memset(&xend, 0, sizeof(xend));
memset(&xexact, 0, sizeof(xexact));
memset(&b, 0, sizeof(b));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(&ct, 0, sizeof(ct));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xstart, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xend, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xexact, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
_minqpstate_init(&state, _state, ae_true);
_minqpreport_init(&rep, _state, ae_true);
waserrors = ae_false;
/*
* Test 1: reported by Vanderlande Industries.
* Tests algorithm ability to handle degenerate constraints.
*/
ae_matrix_set_length(&a, 3, 3, _state);
for(i=0; i<=2; i++)
{
for(j=0; j<=2; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
for(i=0; i<=2; i++)
{
a.ptr.pp_double[i][i] = (double)(1);
}
ae_vector_set_length(&b, 3, _state);
b.ptr.p_double[0] = (double)(-50);
b.ptr.p_double[1] = (double)(-50);
b.ptr.p_double[2] = (double)(-75);
ae_vector_set_length(&bndl, 3, _state);
bndl.ptr.p_double[0] = (double)(0);
bndl.ptr.p_double[1] = (double)(0);
bndl.ptr.p_double[2] = (double)(0);
ae_vector_set_length(&bndu, 3, _state);
bndu.ptr.p_double[0] = (double)(100);
bndu.ptr.p_double[1] = (double)(100);
bndu.ptr.p_double[2] = (double)(150);
ae_vector_set_length(&xstart, 3, _state);
xstart.ptr.p_double[0] = (double)(0);
xstart.ptr.p_double[1] = (double)(100);
xstart.ptr.p_double[2] = (double)(0);
ae_vector_set_length(&xexact, 3, _state);
xexact.ptr.p_double[0] = (double)(0);
xexact.ptr.p_double[1] = (double)(100);
xexact.ptr.p_double[2] = (double)(50);
ae_matrix_set_length(&c, 3, 4, _state);
c.ptr.pp_double[0][0] = (double)(1);
c.ptr.pp_double[0][1] = (double)(-1);
c.ptr.pp_double[0][2] = (double)(0);
c.ptr.pp_double[0][3] = (double)(-100);
c.ptr.pp_double[1][0] = (double)(1);
c.ptr.pp_double[1][1] = (double)(0);
c.ptr.pp_double[1][2] = (double)(-1);
c.ptr.pp_double[1][3] = (double)(0);
c.ptr.pp_double[2][0] = (double)(-1);
c.ptr.pp_double[2][1] = (double)(0);
c.ptr.pp_double[2][2] = (double)(1);
c.ptr.pp_double[2][3] = (double)(50);
ae_vector_set_length(&ct, 3, _state);
ct.ptr.p_int[0] = -1;
ct.ptr.p_int[1] = -1;
ct.ptr.p_int[2] = -1;
minqpcreate(3, &state, _state);
testminqpunit_setrandomalgoconvexlc(&state, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetquadraticterm(&state, &a, ae_true, _state);
minqpsetstartingpoint(&state, &xstart, _state);
minqpsetbc(&state, &bndl, &bndu, _state);
minqpsetlc(&state, &c, &ct, 3, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend, &rep, _state);
if( rep.terminationtype>0 )
{
for(i=0; i<=2; i++)
{
waserrors = waserrors||ae_fp_greater(ae_fabs(xend.ptr.p_double[i]-xexact.ptr.p_double[i], _state),1.0E6*ae_machineepsilon);
}
}
else
{
waserrors = ae_true;
}
/*
* Test 2: reported by Vanderlande Industries.
* Tests algorithm ability to handle degenerate constraints.
*/
ae_matrix_set_length(&a, 3, 3, _state);
for(i=0; i<=2; i++)
{
for(j=0; j<=2; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
for(i=0; i<=2; i++)
{
a.ptr.pp_double[i][i] = (double)(1);
}
ae_vector_set_length(&b, 3, _state);
b.ptr.p_double[0] = (double)(-50);
b.ptr.p_double[1] = (double)(-50);
b.ptr.p_double[2] = (double)(-75);
ae_vector_set_length(&bndl, 3, _state);
bndl.ptr.p_double[0] = (double)(0);
bndl.ptr.p_double[1] = (double)(0);
bndl.ptr.p_double[2] = (double)(0);
ae_vector_set_length(&bndu, 3, _state);
bndu.ptr.p_double[0] = (double)(100);
bndu.ptr.p_double[1] = (double)(100);
bndu.ptr.p_double[2] = (double)(150);
ae_vector_set_length(&xstart, 3, _state);
xstart.ptr.p_double[0] = (double)(0);
xstart.ptr.p_double[1] = (double)(100);
xstart.ptr.p_double[2] = (double)(150);
ae_vector_set_length(&xexact, 3, _state);
xexact.ptr.p_double[0] = (double)(0);
xexact.ptr.p_double[1] = (double)(100);
xexact.ptr.p_double[2] = (double)(100);
ae_matrix_set_length(&c, 3, 4, _state);
c.ptr.pp_double[0][0] = (double)(1);
c.ptr.pp_double[0][1] = (double)(-1);
c.ptr.pp_double[0][2] = (double)(0);
c.ptr.pp_double[0][3] = (double)(-100);
c.ptr.pp_double[1][0] = (double)(0);
c.ptr.pp_double[1][1] = (double)(1);
c.ptr.pp_double[1][2] = (double)(-1);
c.ptr.pp_double[1][3] = (double)(0);
c.ptr.pp_double[2][0] = (double)(0);
c.ptr.pp_double[2][1] = (double)(-1);
c.ptr.pp_double[2][2] = (double)(1);
c.ptr.pp_double[2][3] = (double)(50);
ae_vector_set_length(&ct, 3, _state);
ct.ptr.p_int[0] = -1;
ct.ptr.p_int[1] = -1;
ct.ptr.p_int[2] = -1;
minqpcreate(3, &state, _state);
testminqpunit_setrandomalgoconvexlc(&state, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetquadraticterm(&state, &a, ae_true, _state);
minqpsetstartingpoint(&state, &xstart, _state);
minqpsetbc(&state, &bndl, &bndu, _state);
minqpsetlc(&state, &c, &ct, 3, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xend, &rep, _state);
if( rep.terminationtype>0 )
{
for(i=0; i<=2; i++)
{
waserrors = waserrors||ae_fp_greater(ae_fabs(xend.ptr.p_double[i]-xexact.ptr.p_double[i], _state),1.0E6*ae_machineepsilon);
}
}
else
{
waserrors = ae_true;
}
result = waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function tests linearly constrained DENSE-AUL solver
On failure sets Err to True; on success leaves it unchanged.
*************************************************************************/
static void testminqpunit_denseaultests(ae_bool* errorflag,
ae_state *_state)
{
ae_frame _frame_block;
hqrndstate rs;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
double vv;
ae_int_t scaletype;
ae_matrix rawa;
ae_matrix z;
ae_vector bndl;
ae_vector bndu;
ae_matrix rawc;
ae_vector rawct;
ae_int_t rawccnt;
ae_vector b;
ae_vector x0;
ae_vector xf;
ae_vector r;
ae_vector xsol;
ae_vector s;
minqpstate state;
minqpreport rep;
double epsx;
double xtol;
double rho;
ae_int_t outerits;
densesolverreport svrep;
ae_frame_make(_state, &_frame_block);
memset(&rs, 0, sizeof(rs));
memset(&rawa, 0, sizeof(rawa));
memset(&z, 0, sizeof(z));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(&rawc, 0, sizeof(rawc));
memset(&rawct, 0, sizeof(rawct));
memset(&b, 0, sizeof(b));
memset(&x0, 0, sizeof(x0));
memset(&xf, 0, sizeof(xf));
memset(&r, 0, sizeof(r));
memset(&xsol, 0, sizeof(xsol));
memset(&s, 0, sizeof(s));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&svrep, 0, sizeof(svrep));
_hqrndstate_init(&rs, _state, ae_true);
ae_matrix_init(&rawa, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&rawc, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rawct, 0, DT_INT, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xf, 0, DT_REAL, _state, ae_true);
ae_vector_init(&r, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xsol, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
_minqpstate_init(&state, _state, ae_true);
_minqpreport_init(&rep, _state, ae_true);
_densesolverreport_init(&svrep, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Test that unconstrained problem is solved with high precision,
* independently of Rho and/or outer iterations count.
*
* 50% of problems are rescaled wildly (with scale being passed to
* the solver).
*/
epsx = 1.0E-12;
xtol = 1.0E-7;
for(n=1; n<=10; n++)
{
for(scaletype=0; scaletype<=1; scaletype++)
{
/*
* Generate random A, b, X0 and XSOL
*/
spdmatrixrndcond(n, ae_pow(10.0, 3*hqrnduniformr(&rs, _state), _state), &rawa, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&xsol, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
xsol.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&rawa.ptr.pp_double[i][0], 1, &xsol.ptr.p_double[0], 1, ae_v_len(0,n-1));
b.ptr.p_double[i] = -v;
}
/*
* Generate scale vector, apply it
*/
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
if( scaletype>0 )
{
s.ptr.p_double[i] = ae_pow((double)(10), hqrnduniformr(&rs, _state)*20-10, _state);
}
else
{
s.ptr.p_double[i] = (double)(1);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
rawa.ptr.pp_double[i][j] = rawa.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]);
}
b.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i];
x0.ptr.p_double[i] = x0.ptr.p_double[i]*s.ptr.p_double[i];
xsol.ptr.p_double[i] = xsol.ptr.p_double[i]*s.ptr.p_double[i];
}
/*
* Create optimizer, solve
*/
rho = ae_pow((double)(10), 2*hqrnduniformr(&rs, _state), _state);
outerits = hqrnduniformi(&rs, 5, _state);
minqpcreate(n, &state, _state);
minqpsetalgodenseaul(&state, epsx, rho, outerits, _state);
minqpsetlinearterm(&state, &b, _state);
testminqpunit_randomlyselectconvertandsetquadraticterm(&rawa, n, &state, &rs, _state);
minqpsetscale(&state, &s, _state);
minqpsetstartingpoint(&state, &x0, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xf, &rep, _state);
/*
* Compare against analytically known solution
*/
if( rep.terminationtype<=0 )
{
ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:7136");
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xf.ptr.p_double[i]-xsol.ptr.p_double[i], _state)/s.ptr.p_double[i],xtol), __FILE__, __LINE__, "testminqpunit.ap:7140");
}
}
}
/*
* Test that problem with zero constraint matrix can be solved
* (with high precision). We do not perform any additional "tweaks"
* like scaling of variables, just want to test ability to handle
* zero matrices.
*/
epsx = 1.0E-12;
xtol = 1.0E-7;
for(n=1; n<=10; n++)
{
/*
* Generate random A, b, X0 and XSOL
*/
spdmatrixrndcond(n, ae_pow(10.0, 3*hqrnduniformr(&rs, _state), _state), &rawa, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&xsol, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
xsol.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&rawa.ptr.pp_double[i][0], 1, &xsol.ptr.p_double[0], 1, ae_v_len(0,n-1));
b.ptr.p_double[i] = -v;
}
rawccnt = hqrnduniformi(&rs, 2*n, _state);
ae_matrix_set_length(&rawc, rawccnt, n+1, _state);
ae_vector_set_length(&rawct, rawccnt, _state);
for(i=0; i<=rawccnt-1; i++)
{
for(j=0; j<=n; j++)
{
rawc.ptr.pp_double[i][j] = (double)(0);
}
rawct.ptr.p_int[i] = hqrnduniformi(&rs, 3, _state)-1;
}
/*
* Create optimizer, solve
*/
rho = ae_pow((double)(10), 2*hqrnduniformr(&rs, _state), _state);
outerits = hqrnduniformi(&rs, 5, _state);
minqpcreate(n, &state, _state);
minqpsetalgodenseaul(&state, epsx, rho, outerits, _state);
minqpsetlinearterm(&state, &b, _state);
testminqpunit_randomlyselectconvertandsetquadraticterm(&rawa, n, &state, &rs, _state);
minqpsetlc(&state, &rawc, &rawct, rawccnt, _state);
minqpsetstartingpoint(&state, &x0, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xf, &rep, _state);
/*
* Compare against analytically known solution
*/
if( rep.terminationtype<=0 )
{
ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:7200");
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xf.ptr.p_double[i]-xsol.ptr.p_double[i], _state),xtol), __FILE__, __LINE__, "testminqpunit.ap:7204");
}
}
/*
* Test that box/linearly inequality constrained problem with ALL constraints
* being inactive at BOTH initial and final points is solved with high precision.
*
* 50% of problems are rescaled wildly (with scale being passed to
* the solver).
*/
epsx = 1.0E-12;
xtol = 1.0E-7;
for(n=1; n<=10; n++)
{
for(scaletype=0; scaletype<=1; scaletype++)
{
/*
* Generate random A, b, X0 and XSOL
*/
spdmatrixrndcond(n, ae_pow(10.0, 3*hqrnduniformr(&rs, _state), _state), &rawa, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&xsol, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
xsol.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&rawa.ptr.pp_double[i][0], 1, &xsol.ptr.p_double[0], 1, ae_v_len(0,n-1));
b.ptr.p_double[i] = -v;
}
/*
* Generate such set of inequality constraints that ALL
* constraints are inactive at both X0 and XSOL.
*/
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
for(i=0; i<=n-1; i++)
{
bndl.ptr.p_double[i] = ae_minreal(x0.ptr.p_double[i], xsol.ptr.p_double[i], _state)-1-hqrnduniformr(&rs, _state);
bndu.ptr.p_double[i] = ae_maxreal(x0.ptr.p_double[i], xsol.ptr.p_double[i], _state)+1+hqrnduniformr(&rs, _state);
}
rawccnt = hqrnduniformi(&rs, 2*n, _state);
ae_matrix_set_length(&rawc, rawccnt, n+1, _state);
ae_vector_set_length(&rawct, rawccnt, _state);
for(i=0; i<=rawccnt-1; i++)
{
v = (double)(0);
vv = (double)(0);
for(j=0; j<=n-1; j++)
{
rawc.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
v = v+rawc.ptr.pp_double[i][j]*x0.ptr.p_double[j];
vv = vv+rawc.ptr.pp_double[i][j]*xsol.ptr.p_double[j];
}
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
rawct.ptr.p_int[i] = 1;
rawc.ptr.pp_double[i][n] = ae_minreal(v, vv, _state)-1-hqrnduniformr(&rs, _state);
}
else
{
rawct.ptr.p_int[i] = -1;
rawc.ptr.pp_double[i][n] = ae_maxreal(v, vv, _state)+1+hqrnduniformr(&rs, _state);
}
}
/*
* Generate scale vector, apply it
*/
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
if( scaletype>0 )
{
s.ptr.p_double[i] = ae_pow((double)(10), hqrnduniformr(&rs, _state)*20-10, _state);
}
else
{
s.ptr.p_double[i] = (double)(1);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
rawa.ptr.pp_double[i][j] = rawa.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]);
}
b.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i];
x0.ptr.p_double[i] = x0.ptr.p_double[i]*s.ptr.p_double[i];
xsol.ptr.p_double[i] = xsol.ptr.p_double[i]*s.ptr.p_double[i];
bndl.ptr.p_double[i] = bndl.ptr.p_double[i]*s.ptr.p_double[i];
bndu.ptr.p_double[i] = bndu.ptr.p_double[i]*s.ptr.p_double[i];
}
for(i=0; i<=rawccnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
rawc.ptr.pp_double[i][j] = rawc.ptr.pp_double[i][j]/s.ptr.p_double[j];
}
}
/*
* Create optimizer, solve
*/
rho = 100.0;
outerits = 1;
minqpcreate(n, &state, _state);
minqpsetstartingpoint(&state, &x0, _state);
minqpsetalgodenseaul(&state, epsx, rho, outerits, _state);
minqpsetlinearterm(&state, &b, _state);
testminqpunit_randomlyselectconvertandsetquadraticterm(&rawa, n, &state, &rs, _state);
minqpsetbc(&state, &bndl, &bndu, _state);
testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, rawccnt, n, &state, &rs, _state);
minqpsetscale(&state, &s, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xf, &rep, _state);
/*
* Compare against analytically known solution
*/
if( rep.terminationtype<=0 )
{
ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:7321");
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xf.ptr.p_double[i]-xsol.ptr.p_double[i], _state)/s.ptr.p_double[i],xtol), __FILE__, __LINE__, "testminqpunit.ap:7325");
}
}
}
/*
* Test that linear equality constrained problem is solved with high precision.
*
* 50% of problems are rescaled wildly (variable scaling, with scale being
* passed to the solver).
*/
epsx = 1.0E-12;
xtol = 1.0E-6;
for(n=1; n<=10; n++)
{
for(scaletype=0; scaletype<=1; scaletype++)
{
/*
* Generate random A, b, X0, constraints
*/
spdmatrixrndcond(n, ae_pow(10.0, 3*hqrnduniformr(&rs, _state), _state), &rawa, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&xsol, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
rmatrixrndcond(n, (double)(10), &z, _state);
rawccnt = ae_maxint(n-2, 0, _state);
if( rawccnt>0 )
{
ae_matrix_set_length(&rawc, rawccnt, n+1, _state);
ae_vector_set_length(&rawct, rawccnt, _state);
for(i=0; i<=rawccnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
rawc.ptr.pp_double[i][j] = z.ptr.pp_double[i][j];
}
rawct.ptr.p_int[i] = 0;
rawc.ptr.pp_double[i][n] = hqrndnormal(&rs, _state);
}
}
/*
* Generate scale vector, apply it
*/
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
if( scaletype>0 )
{
s.ptr.p_double[i] = ae_pow((double)(10), hqrnduniformr(&rs, _state)*20-10, _state);
}
else
{
s.ptr.p_double[i] = (double)(1);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
rawa.ptr.pp_double[i][j] = rawa.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]);
}
b.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i];
x0.ptr.p_double[i] = x0.ptr.p_double[i]*s.ptr.p_double[i];
xsol.ptr.p_double[i] = xsol.ptr.p_double[i]*s.ptr.p_double[i];
}
for(i=0; i<=rawccnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
rawc.ptr.pp_double[i][j] = rawc.ptr.pp_double[i][j]/s.ptr.p_double[j];
}
}
/*
* Create optimizer, solve
*/
rho = 100.0;
outerits = 3;
minqpcreate(n, &state, _state);
minqpsetalgodenseaul(&state, epsx, rho, outerits, _state);
minqpsetlinearterm(&state, &b, _state);
testminqpunit_randomlyselectconvertandsetquadraticterm(&rawa, n, &state, &rs, _state);
testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, rawccnt, n, &state, &rs, _state);
minqpsetscale(&state, &s, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xf, &rep, _state);
/*
* Solve problem analytically using Lagrangian approach
*/
ae_matrix_set_length(&z, n+rawccnt, n+rawccnt, _state);
ae_vector_set_length(&r, n+rawccnt, _state);
for(i=0; i<=n+rawccnt-1; i++)
{
for(j=0; j<=n+rawccnt-1; j++)
{
z.ptr.pp_double[i][j] = (double)(0);
}
r.ptr.p_double[i] = (double)(0);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
z.ptr.pp_double[i][j] = rawa.ptr.pp_double[i][j];
}
}
for(i=0; i<=n-1; i++)
{
r.ptr.p_double[i] = -b.ptr.p_double[i];
}
for(i=0; i<=rawccnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
z.ptr.pp_double[n+i][j] = rawc.ptr.pp_double[i][j];
z.ptr.pp_double[j][n+i] = rawc.ptr.pp_double[i][j];
}
r.ptr.p_double[n+i] = rawc.ptr.pp_double[i][n];
}
rmatrixsolve(&z, n+rawccnt, &r, &k, &svrep, &xsol, _state);
ae_assert(k>0, "MinQPTest: integrity check failed", _state);
/*
* Compare against analytically known solution
*/
if( rep.terminationtype<=0 )
{
ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:7435");
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xf.ptr.p_double[i]-xsol.ptr.p_double[i], _state)/s.ptr.p_double[i],xtol), __FILE__, __LINE__, "testminqpunit.ap:7439");
}
}
}
/*
* MEDIUM-SCALE VERSION OF PREVIOUS TEST.
*
* Test that linear equality constrained problem is solved with high precision.
*
* 50% of problems are rescaled wildly (variable scaling, with scale being
* passed to the solver).
*/
epsx = 1.0E-12;
xtol = 1.0E-6;
for(n=99; n<=101; n++)
{
for(scaletype=0; scaletype<=1; scaletype++)
{
/*
* Generate random A, b, X0, constraints
*/
spdmatrixrndcond(n, ae_pow(10.0, 3*hqrnduniformr(&rs, _state), _state), &rawa, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&xsol, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
rmatrixrndcond(n, (double)(10), &z, _state);
rawccnt = ae_maxint(n-2, 0, _state);
if( rawccnt>0 )
{
ae_matrix_set_length(&rawc, rawccnt, n+1, _state);
ae_vector_set_length(&rawct, rawccnt, _state);
for(i=0; i<=rawccnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
rawc.ptr.pp_double[i][j] = z.ptr.pp_double[i][j];
}
rawct.ptr.p_int[i] = 0;
rawc.ptr.pp_double[i][n] = hqrndnormal(&rs, _state);
}
}
/*
* Generate scale vector, apply it
*/
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
if( scaletype>0 )
{
s.ptr.p_double[i] = ae_pow((double)(10), hqrnduniformr(&rs, _state)*20-10, _state);
}
else
{
s.ptr.p_double[i] = (double)(1);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
rawa.ptr.pp_double[i][j] = rawa.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]);
}
b.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i];
x0.ptr.p_double[i] = x0.ptr.p_double[i]*s.ptr.p_double[i];
xsol.ptr.p_double[i] = xsol.ptr.p_double[i]*s.ptr.p_double[i];
}
for(i=0; i<=rawccnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
rawc.ptr.pp_double[i][j] = rawc.ptr.pp_double[i][j]/s.ptr.p_double[j];
}
}
/*
* Create optimizer, solve
*/
rho = 100.0;
outerits = 3;
minqpcreate(n, &state, _state);
minqpsetalgodenseaul(&state, epsx, rho, outerits, _state);
minqpsetlinearterm(&state, &b, _state);
testminqpunit_randomlyselectconvertandsetquadraticterm(&rawa, n, &state, &rs, _state);
testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, rawccnt, n, &state, &rs, _state);
minqpsetscale(&state, &s, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xf, &rep, _state);
/*
* Solve problem analytically using Lagrangian approach
*/
ae_matrix_set_length(&z, n+rawccnt, n+rawccnt, _state);
ae_vector_set_length(&r, n+rawccnt, _state);
for(i=0; i<=n+rawccnt-1; i++)
{
for(j=0; j<=n+rawccnt-1; j++)
{
z.ptr.pp_double[i][j] = (double)(0);
}
r.ptr.p_double[i] = (double)(0);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
z.ptr.pp_double[i][j] = rawa.ptr.pp_double[i][j];
}
}
for(i=0; i<=n-1; i++)
{
r.ptr.p_double[i] = -b.ptr.p_double[i];
}
for(i=0; i<=rawccnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
z.ptr.pp_double[n+i][j] = rawc.ptr.pp_double[i][j];
z.ptr.pp_double[j][n+i] = rawc.ptr.pp_double[i][j];
}
r.ptr.p_double[n+i] = rawc.ptr.pp_double[i][n];
}
rmatrixsolve(&z, n+rawccnt, &r, &k, &svrep, &xsol, _state);
ae_assert(k>0, "MinQPTest: integrity check failed", _state);
/*
* Compare against analytically known solution
*/
if( rep.terminationtype<=0 )
{
ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:7551");
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xf.ptr.p_double[i]-xsol.ptr.p_double[i], _state)/s.ptr.p_double[i],xtol), __FILE__, __LINE__, "testminqpunit.ap:7555");
}
}
}
/*
* Test that constraints are automatically scaled to adapt to problem curvature
* (that multiplication of A and b by some large/small number does not affect
* solver).
*
* We generate random well-scaled problem, and multiply A/b by some large/small number,
* and test that problem is still solved with high precision.
*
* NOTE: just to make things worse, we rescale variables randomly, but primary
* idea of this test is to check for multiplication of A/B
*/
epsx = 1.0E-12;
xtol = 1.0E-6;
for(n=1; n<=10; n++)
{
for(scaletype=-1; scaletype<=1; scaletype++)
{
/*
* Generate random A, b, X0, constraints
*/
spdmatrixrndcond(n, ae_pow(10.0, 3*hqrnduniformr(&rs, _state), _state), &rawa, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&xsol, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
rmatrixrndcond(n, (double)(10), &z, _state);
rawccnt = ae_maxint(n-2, 0, _state);
if( rawccnt>0 )
{
ae_matrix_set_length(&rawc, rawccnt, n+1, _state);
ae_vector_set_length(&rawct, rawccnt, _state);
for(i=0; i<=rawccnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
rawc.ptr.pp_double[i][j] = z.ptr.pp_double[i][j];
}
rawct.ptr.p_int[i] = 0;
rawc.ptr.pp_double[i][n] = hqrndnormal(&rs, _state);
}
}
/*
* Solve problem analytically using Lagrangian approach
*/
ae_matrix_set_length(&z, n+rawccnt, n+rawccnt, _state);
ae_vector_set_length(&r, n+rawccnt, _state);
for(i=0; i<=n+rawccnt-1; i++)
{
for(j=0; j<=n+rawccnt-1; j++)
{
z.ptr.pp_double[i][j] = (double)(0);
}
r.ptr.p_double[i] = (double)(0);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
z.ptr.pp_double[i][j] = rawa.ptr.pp_double[i][j];
}
}
for(i=0; i<=n-1; i++)
{
r.ptr.p_double[i] = -b.ptr.p_double[i];
}
for(i=0; i<=rawccnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
z.ptr.pp_double[n+i][j] = rawc.ptr.pp_double[i][j];
z.ptr.pp_double[j][n+i] = rawc.ptr.pp_double[i][j];
}
r.ptr.p_double[n+i] = rawc.ptr.pp_double[i][n];
}
rmatrixsolve(&z, n+rawccnt, &r, &k, &svrep, &xsol, _state);
ae_assert(k>0, "MinQPTest: integrity check failed", _state);
/*
* Generate scale vector, apply it
*/
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = ae_pow((double)(10), hqrnduniformr(&rs, _state)*20-10, _state);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
rawa.ptr.pp_double[i][j] = rawa.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]);
}
b.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i];
x0.ptr.p_double[i] = x0.ptr.p_double[i]*s.ptr.p_double[i];
xsol.ptr.p_double[i] = xsol.ptr.p_double[i]*s.ptr.p_double[i];
}
for(i=0; i<=rawccnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
rawc.ptr.pp_double[i][j] = rawc.ptr.pp_double[i][j]/s.ptr.p_double[j];
}
}
/*
* Multiply A/B by some coefficient with wild magnitude
*/
v = ae_pow((double)(10), (double)(10*scaletype), _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
rawa.ptr.pp_double[i][j] = rawa.ptr.pp_double[i][j]*v;
}
b.ptr.p_double[i] = b.ptr.p_double[i]*v;
}
/*
* Create optimizer, solve
*/
rho = 100.0;
outerits = 3;
minqpcreate(n, &state, _state);
minqpsetalgodenseaul(&state, epsx, rho, outerits, _state);
minqpsetlinearterm(&state, &b, _state);
testminqpunit_randomlyselectconvertandsetquadraticterm(&rawa, n, &state, &rs, _state);
testminqpunit_randomlysplitandsetlclegacy(&rawc, &rawct, rawccnt, n, &state, &rs, _state);
minqpsetscale(&state, &s, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xf, &rep, _state);
/*
* Compare against analytically known solution
*/
if( rep.terminationtype<=0 )
{
ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminqpunit.ap:7678");
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xf.ptr.p_double[i]-xsol.ptr.p_double[i], _state)/s.ptr.p_double[i],xtol), __FILE__, __LINE__, "testminqpunit.ap:7682");
}
}
}
/*
* Test that problem with slight negative curvature f = -0.001*|x|^2
* subject to general linear (!) constraints -1 <= x[i] <= +1 is
* correctly solved. Initial point is in [-0.001,+0.001] range.
*
* NOTE: this test is mostly intended for working set selection algorithm;
* it must correctly detect non-SPD problems and select full working
* set; starting with zero working set will result in recognition of
* problem as unbounded one and premature termination of algorithm.
*/
epsx = 1.0E-12;
xtol = 1.0E-6;
for(n=1; n<=10; n++)
{
/*
* Generate A, b, X0, constraints
*/
ae_matrix_set_length(&rawa, n, n, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
rawa.ptr.pp_double[i][j] = (double)(0);
}
rawa.ptr.pp_double[i][i] = -0.001;
b.ptr.p_double[i] = (double)(0);
x0.ptr.p_double[i] = 0.001*hqrndnormal(&rs, _state);
}
ae_matrix_set_length(&rawc, 2*n, n+1, _state);
ae_vector_set_length(&rawct, 2*n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n; j++)
{
rawc.ptr.pp_double[2*i+0][j] = (double)(0);
rawc.ptr.pp_double[2*i+1][j] = (double)(0);
}
rawc.ptr.pp_double[2*i+0][i] = (double)(1);
rawc.ptr.pp_double[2*i+1][i] = (double)(1);
rawc.ptr.pp_double[2*i+0][n] = (double)(-1);
rawc.ptr.pp_double[2*i+1][n] = (double)(1);
rawct.ptr.p_int[2*i+0] = 1;
rawct.ptr.p_int[2*i+1] = -1;
}
/*
* Create optimizer, solve
*/
rho = 100.0;
outerits = 5;
minqpcreate(n, &state, _state);
minqpsetalgodenseaul(&state, epsx, rho, outerits, _state);
minqpsetstartingpoint(&state, &x0, _state);
minqpsetquadraticterm(&state, &rawa, ae_true, _state);
minqpsetlinearterm(&state, &b, _state);
minqpsetlc(&state, &rawc, &rawct, 2*n, _state);
minqpoptimize(&state, _state);
minqpresults(&state, &xf, &rep, _state);
/*
* Test
*/
ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:7747");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(ae_fabs(xf.ptr.p_double[i], _state)-1, _state),xtol), __FILE__, __LINE__, "testminqpunit.ap:7751");
}
}
ae_frame_leave(_state);
}
/*************************************************************************
This function tests IPM QP solver
On failure sets Err to True; on success leaves it unchanged.
*************************************************************************/
static void testminqpunit_ipmtests(ae_bool* errorflag, ae_state *_state)
{
ae_frame _frame_block;
hqrndstate rs;
ae_int_t n;
ae_int_t nmain;
ae_int_t nslack;
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
ae_int_t nnz;
ae_int_t nactive;
double f0;
double f1;
ae_matrix maina;
ae_matrix fulla;
ae_vector s;
ae_vector xorigin;
ae_vector xf;
ae_vector x1;
ae_vector g;
ae_vector b;
ae_vector gtrial;
ae_vector bndl;
ae_vector bndu;
ae_int_t akind;
ae_matrix rawc;
ae_vector rawcl;
ae_vector rawcu;
ae_int_t rawccnt;
sparsematrix sparsec;
ae_int_t sparseccnt;
ae_matrix densec;
ae_int_t denseccnt;
ae_bool issemidefinite;
ae_vector tmp;
ae_vector lagbc;
ae_vector laglc;
sparsematrix dummysparse;
vipmstate vsolver;
ae_vector replagbc;
ae_vector replaglc;
ae_int_t repterminationtype;
double epsx;
double xtol;
ae_vector xsol;
ae_vector x0;
ae_vector rawct;
minqpstate state;
minqpreport rep;
ae_frame_make(_state, &_frame_block);
memset(&rs, 0, sizeof(rs));
memset(&maina, 0, sizeof(maina));
memset(&fulla, 0, sizeof(fulla));
memset(&s, 0, sizeof(s));
memset(&xorigin, 0, sizeof(xorigin));
memset(&xf, 0, sizeof(xf));
memset(&x1, 0, sizeof(x1));
memset(&g, 0, sizeof(g));
memset(&b, 0, sizeof(b));
memset(>rial, 0, sizeof(gtrial));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(&rawc, 0, sizeof(rawc));
memset(&rawcl, 0, sizeof(rawcl));
memset(&rawcu, 0, sizeof(rawcu));
memset(&sparsec, 0, sizeof(sparsec));
memset(&densec, 0, sizeof(densec));
memset(&tmp, 0, sizeof(tmp));
memset(&lagbc, 0, sizeof(lagbc));
memset(&laglc, 0, sizeof(laglc));
memset(&dummysparse, 0, sizeof(dummysparse));
memset(&vsolver, 0, sizeof(vsolver));
memset(&replagbc, 0, sizeof(replagbc));
memset(&replaglc, 0, sizeof(replaglc));
memset(&xsol, 0, sizeof(xsol));
memset(&x0, 0, sizeof(x0));
memset(&rawct, 0, sizeof(rawct));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
_hqrndstate_init(&rs, _state, ae_true);
ae_matrix_init(&maina, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&fulla, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xorigin, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xf, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&g, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(>rial, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&rawc, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rawcl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rawcu, 0, DT_REAL, _state, ae_true);
_sparsematrix_init(&sparsec, _state, ae_true);
ae_matrix_init(&densec, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
ae_vector_init(&lagbc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&laglc, 0, DT_REAL, _state, ae_true);
_sparsematrix_init(&dummysparse, _state, ae_true);
_vipmstate_init(&vsolver, _state, ae_true);
ae_vector_init(&replagbc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&replaglc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xsol, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rawct, 0, DT_INT, _state, ae_true);
_minqpstate_init(&state, _state, ae_true);
_minqpreport_init(&rep, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Test handling of slack variables by IPM solver. We use IPM directly,
* without wrapping it with MinQP interface layer.
*
* Convex optimization problem with known answer (we generate constraints
* and Lagrange coefficients, and then generate quadratic and linear term
* which satisfy KKT conditions for given Lagrange coefficients):
*
* * N=2..8
* * f = 0.5*x'*A*x+b'*x
* * several kinds of A are tried: zero, well conditioned SPD, low rank
* * initial point x0 = [0 0 ... 0 0]
* * first, we generate set of linear constraints (without bounds),
* solution point X and Lagrange multipliers for linear and box constraints
* * then we determine bounds on variables and linear constraints which
* align with values/signs of Lagrange multipliers
* * then, having quadratic term A and known constraints and Lagrange
* multipliers we determine linear term B which makes KKT conditions true
*/
epsx = 1.0E-12;
for(nmain=1; nmain<=8; nmain++)
{
for(nslack=0; nslack<=8; nslack++)
{
for(akind=0; akind<=2; akind++)
{
n = nmain+nslack;
/*
* Generate quadratic term A, origin and scale
*/
ae_matrix_set_length(&maina, nmain, nmain, _state);
for(i=0; i<=nmain-1; i++)
{
for(j=0; j<=nmain-1; j++)
{
maina.ptr.pp_double[i][j] = 0.0;
}
}
issemidefinite = ae_true;
if( akind==1 )
{
/*
* Dense well conditioned SPD
*/
spdmatrixrndcond(nmain, 50.0, &maina, _state);
issemidefinite = ae_false;
}
if( akind==2 )
{
/*
* Low rank semidefinite
*/
ae_vector_set_length(&tmp, nmain, _state);
for(i=0; i<=nmain-1; i++)
{
for(j=0; j<=nmain-1; j++)
{
maina.ptr.pp_double[i][j] = 0.0;
}
}
for(k=1; k<=ae_minint(3, nmain-1, _state); k++)
{
for(i=0; i<=nmain-1; i++)
{
tmp.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
v = ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
for(i=0; i<=nmain-1; i++)
{
for(j=0; j<=nmain-1; j++)
{
maina.ptr.pp_double[i][j] = maina.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j];
}
}
}
issemidefinite = ae_true;
}
issemidefinite = issemidefinite||nslack>0;
ae_matrix_set_length(&fulla, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
fulla.ptr.pp_double[i][j] = 0.0;
}
}
for(i=0; i<=nmain-1; i++)
{
for(j=0; j<=nmain-1; j++)
{
fulla.ptr.pp_double[i][j] = maina.ptr.pp_double[i][j];
}
}
ae_vector_set_length(&s, n, _state);
ae_vector_set_length(&xorigin, n, _state);
for(j=0; j<=n-1; j++)
{
xorigin.ptr.p_double[j] = hqrndnormal(&rs, _state);
s.ptr.p_double[j] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
}
/*
* Generate linear constraints (left parts)
*/
rawccnt = hqrnduniformi(&rs, 2*n+1, _state);
if( rawccnt>0 )
{
ae_matrix_set_length(&rawc, rawccnt, n, _state);
for(i=0; i<=rawccnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
rawc.ptr.pp_double[i][j] = (double)(0);
}
nnz = hqrnduniformi(&rs, nmain+1, _state);
for(k=0; k<=nnz-1; k++)
{
j = hqrnduniformi(&rs, nmain, _state);
v = hqrndnormal(&rs, _state);
v = v+0.1*possign(v, _state);
rawc.ptr.pp_double[i][j] = v;
}
}
for(j=nmain; j<=n-1; j++)
{
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
v = hqrndnormal(&rs, _state);
v = v+0.1*possign(v, _state);
rawc.ptr.pp_double[hqrnduniformi(&rs, rawccnt, _state)][j] = v;
}
}
}
/*
* Generate Lagrange multipliers, with 0<=NActive<=N-1 being non-zero
*/
ae_vector_set_length(&lagbc, n, _state);
ae_vector_set_length(&laglc, rawccnt, _state);
for(i=0; i<=n-1; i++)
{
lagbc.ptr.p_double[i] = (double)(0);
}
for(i=0; i<=rawccnt-1; i++)
{
laglc.ptr.p_double[i] = (double)(0);
}
nactive = hqrnduniformi(&rs, n, _state);
k = hqrnduniformi(&rs, ae_minint(nactive, rawccnt, _state)+1, _state);
for(i=0; i<=k-1; i++)
{
v = hqrndnormal(&rs, _state);
v = v+0.01*possign(v, _state);
laglc.ptr.p_double[hqrnduniformi(&rs, rawccnt, _state)] = v;
}
for(i=k; i<=nactive-1; i++)
{
v = hqrndnormal(&rs, _state);
v = v+0.01*possign(v, _state);
lagbc.ptr.p_double[hqrnduniformi(&rs, n, _state)] = v;
}
/*
* Generate solution and gradient at the solution, set B to -G
*/
ae_vector_set_length(&xf, n, _state);
for(i=0; i<=n-1; i++)
{
xf.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&g, n, _state);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+fulla.ptr.pp_double[i][j]*(xf.ptr.p_double[j]-xorigin.ptr.p_double[j]);
}
g.ptr.p_double[i] = v;
}
for(i=0; i<=n-1; i++)
{
g.ptr.p_double[i] = g.ptr.p_double[i]+lagbc.ptr.p_double[i];
}
for(i=0; i<=rawccnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
g.ptr.p_double[j] = g.ptr.p_double[j]+laglc.ptr.p_double[i]*rawc.ptr.pp_double[i][j];
}
}
ae_vector_set_length(&b, n, _state);
for(j=0; j<=n-1; j++)
{
b.ptr.p_double[j] = -g.ptr.p_double[j];
}
/*
* Set up bounds according to Lagrange multipliers
*
* NOTE: for semidefinite problems we set all variable bounds
*/
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
for(j=0; j<=n-1; j++)
{
bndl.ptr.p_double[j] = _state->v_neginf;
bndu.ptr.p_double[j] = _state->v_posinf;
if( (ae_fp_greater(hqrndnormal(&rs, _state),(double)(0))||issemidefinite)||j>=nmain )
{
bndl.ptr.p_double[j] = xf.ptr.p_double[j]-ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
}
if( (ae_fp_greater(hqrndnormal(&rs, _state),(double)(0))||issemidefinite)||j>=nmain )
{
bndu.ptr.p_double[j] = xf.ptr.p_double[j]+ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
}
if( ae_fp_neq(lagbc.ptr.p_double[j],(double)(0)) )
{
if( ae_fp_less(hqrnduniformr(&rs, _state),0.15) )
{
bndl.ptr.p_double[j] = xf.ptr.p_double[j];
bndu.ptr.p_double[j] = xf.ptr.p_double[j];
}
else
{
if( ae_fp_less(lagbc.ptr.p_double[j],(double)(0)) )
{
bndl.ptr.p_double[j] = xf.ptr.p_double[j];
}
if( ae_fp_greater(lagbc.ptr.p_double[j],(double)(0)) )
{
bndu.ptr.p_double[j] = xf.ptr.p_double[j];
}
}
}
}
ae_vector_set_length(&rawcl, rawccnt, _state);
ae_vector_set_length(&rawcu, rawccnt, _state);
for(i=0; i<=rawccnt-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+rawc.ptr.pp_double[i][j]*xf.ptr.p_double[j];
}
rawcl.ptr.p_double[i] = _state->v_neginf;
rawcu.ptr.p_double[i] = _state->v_posinf;
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
rawcl.ptr.p_double[i] = v-ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
}
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
rawcu.ptr.p_double[i] = v+ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
}
if( ae_fp_neq(laglc.ptr.p_double[i],(double)(0)) )
{
if( ae_fp_less(hqrnduniformr(&rs, _state),0.15) )
{
/*
* Active equality constraint
*/
rawcl.ptr.p_double[i] = v;
rawcu.ptr.p_double[i] = v;
}
else
{
/*
* Active inequality constraint
*/
if( ae_fp_less(laglc.ptr.p_double[i],(double)(0)) )
{
rawcl.ptr.p_double[i] = v;
}
if( ae_fp_greater(laglc.ptr.p_double[i],(double)(0)) )
{
rawcu.ptr.p_double[i] = v;
}
}
}
if( !ae_isfinite(rawcl.ptr.p_double[i], _state)&&!ae_isfinite(rawcu.ptr.p_double[i], _state) )
{
/*
* At least one bound must be present for linear constraint
*/
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
rawcl.ptr.p_double[i] = v-10;
}
else
{
rawcu.ptr.p_double[i] = v+10;
}
}
}
/*
* Randomly split constraints into dense and sparse parts
*/
sparseccnt = hqrnduniformi(&rs, rawccnt+1, _state);
denseccnt = rawccnt-sparseccnt;
if( sparseccnt>0 )
{
sparsecreate(sparseccnt, n, 0, &sparsec, _state);
for(i=0; i<=sparseccnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
sparseset(&sparsec, i, j, rawc.ptr.pp_double[i][j], _state);
}
}
sparseconverttocrs(&sparsec, _state);
}
if( denseccnt>0 )
{
ae_matrix_set_length(&densec, denseccnt, n, _state);
for(i=0; i<=denseccnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
densec.ptr.pp_double[i][j] = rawc.ptr.pp_double[i+sparseccnt][j];
}
}
}
/*
* Solve
*/
vipminitdensewithslacks(&vsolver, &s, &xorigin, nmain, n, _state);
vipmsetquadraticlinear(&vsolver, &fulla, &dummysparse, 0, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &b, _state);
vipmsetconstraints(&vsolver, &bndl, &bndu, &sparsec, sparseccnt, &densec, denseccnt, &rawcl, &rawcu, _state);
vipmsetcond(&vsolver, epsx, epsx, epsx, _state);
vipmoptimize(&vsolver, &x1, &replagbc, &replaglc, &repterminationtype, _state);
ae_set_error_flag(errorflag, repterminationtype<=0, __FILE__, __LINE__, "testminqpunit.ap:8077");
ae_set_error_flag(errorflag, x1.cntptr.p_double[i],bndl->ptr.p_double[i])&&ae_fp_less_eq(x->ptr.p_double[i],bndu->ptr.p_double[i]), "ProjectedAntiGradNormal: boundary constraints violation", _state);
if( ((ae_fp_greater(x->ptr.p_double[i],bndl->ptr.p_double[i])&&ae_fp_less(x->ptr.p_double[i],bndu->ptr.p_double[i]))||(ae_fp_eq(x->ptr.p_double[i],bndl->ptr.p_double[i])&&ae_fp_greater(-g->ptr.p_double[i],(double)(0))))||(ae_fp_eq(x->ptr.p_double[i],bndu->ptr.p_double[i])&&ae_fp_less(-g->ptr.p_double[i],(double)(0))) )
{
r = r+g->ptr.p_double[i]*g->ptr.p_double[i];
}
}
result = ae_sqrt(r, _state);
return result;
}
/*************************************************************************
This function tests that norm of bound-constrained gradient at point X is
less than Eps:
* unconstrained gradient is A*x+b
* if I-th component is at the boundary, and antigradient points outside of
the feasible area, I-th component of constrained gradient is zero
This function accepts QP terms A and B, bound constraints, current point,
and performs test. Additionally, it checks that point is feasible w.r.t.
boundary constraints.
In case of failure, error flag is set. Otherwise, it is not modified.
IMPORTANT: this function does NOT use SetErrorFlag() to modify flag.
If you want to use SetErrorFlag() for easier tracking of errors,
you should store flag returned by this function into separate
variable TmpFlag and call SetErrorFlag(ErrorFlag, TmpFlag) yourself.
*************************************************************************/
static void testminqpunit_testbcgradandfeasibility(/* Real */ ae_matrix* a,
/* Real */ ae_vector* b,
/* Real */ ae_vector* bndl,
/* Real */ ae_vector* bndu,
ae_int_t n,
/* Real */ ae_vector* x,
double eps,
ae_bool* errorflag,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
double g;
double gnorm;
gnorm = 0.0;
for(i=0; i<=n-1; i++)
{
g = b->ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
g = g+a->ptr.pp_double[i][j]*x->ptr.p_double[j];
}
if( ae_fp_eq(x->ptr.p_double[i],bndl->ptr.p_double[i])&&ae_fp_greater(g,(double)(0)) )
{
g = (double)(0);
}
if( ae_fp_eq(x->ptr.p_double[i],bndu->ptr.p_double[i])&&ae_fp_less(g,(double)(0)) )
{
g = (double)(0);
}
gnorm = gnorm+ae_sqr(g, _state);
if( ae_fp_less(x->ptr.p_double[i],bndl->ptr.p_double[i]) )
{
*errorflag = ae_true;
}
if( ae_fp_greater(x->ptr.p_double[i],bndu->ptr.p_double[i]) )
{
*errorflag = ae_true;
}
}
gnorm = ae_sqrt(gnorm, _state);
if( ae_fp_greater(gnorm,eps) )
{
*errorflag = ae_true;
}
}
/*************************************************************************
set random type of the QP solver.
All "modern" solvers can be chosen.
OUTPUT PARAMETERS:
BCTol - expected precision of box constraints handling assuming
unit scale of variables.
LCTol - expected precinion of linear constraints handling assuming
unit scale of variables.
RESULT:
Solver type:
*-1 for QuickQP
* 0 for BLEIC-QP
* 1 for DENSE-AUL
* 2 for DENSE-IPM
* 3 for SPARSE-IPM
BCTol and LCTol have following meaning - if some constraint is active, it
means that we should be at most TOL units away from boundary. It is possible
that zero value is returned.
From definition it follows that if we stopped at more than TOL units away
from the boundary, gradient in corresponding direction is nearly zero.
*************************************************************************/
static ae_int_t testminqpunit_setrandomalgoallmodern(minqpstate* s,
double* bctol,
double* lctol,
ae_state *_state)
{
ae_int_t result;
*bctol = 0;
*lctol = 0;
result = ae_randominteger(5, _state)-1;
if( result==-1 )
{
minqpsetalgoquickqp(s, 1.0E-12, 0.0, 0.0, 0, ae_fp_greater(ae_randomreal(_state),0.5), _state);
*bctol = (double)(0);
*lctol = (double)(0);
}
if( result==0 )
{
minqpsetalgobleic(s, 1.0E-12, 0.0, 0.0, 0, _state);
*bctol = (double)(0);
*lctol = 1.0E-8;
}
if( result==1 )
{
minqpsetalgodenseaul(s, 1.0E-12, 1000.0, 10, _state);
*bctol = 1.0E-3;
*lctol = 1.0E-3;
}
if( result==2 )
{
minqpsetalgodenseipm(s, 1.0E-12, _state);
*bctol = 1.0E-3;
*lctol = 1.0E-3;
}
if( result==3 )
{
minqpsetalgosparseipm(s, 1.0E-12, _state);
*bctol = 1.0E-3;
*lctol = 1.0E-3;
}
return result;
}
/*************************************************************************
set random type of theQP solver
*************************************************************************/
static void testminqpunit_setrandomalgononconvex(minqpstate* s,
ae_state *_state)
{
ae_int_t i;
i = 1+ae_randominteger(2, _state);
if( i==1 )
{
minqpsetalgobleic(s, 1.0E-12, 0.0, 0.0, 0, _state);
}
if( i==2 )
{
minqpsetalgoquickqp(s, 1.0E-12, 0.0, 0.0, 0, ae_fp_greater(ae_randomreal(_state),0.5), _state);
}
}
/*************************************************************************
set random type of theQP solver
*************************************************************************/
static void testminqpunit_setrandomalgosemidefinite(minqpstate* s,
double* bctol,
double* lctol,
ae_state *_state)
{
ae_int_t i;
*bctol = 0;
*lctol = 0;
i = 1+ae_randominteger(4, _state);
if( i==1 )
{
minqpsetalgobleic(s, 1.0E-12, 0.0, 0.0, 0, _state);
*bctol = (double)(0);
*lctol = 1.0E-8;
}
if( i==2 )
{
minqpsetalgoquickqp(s, 1.0E-12, 0.0, 0.0, 0, ae_fp_greater(ae_randomreal(_state),0.5), _state);
*bctol = (double)(0);
*lctol = (double)(0);
}
if( i==3 )
{
minqpsetalgodenseipm(s, 1.0E-12, _state);
*bctol = 1.0E-3;
*lctol = 1.0E-3;
}
if( i==4 )
{
minqpsetalgosparseipm(s, 1.0E-12, _state);
*bctol = 1.0E-3;
*lctol = 1.0E-3;
}
}
/*************************************************************************
set random type of the QP solver, must support boundary constraints
*************************************************************************/
static void testminqpunit_setrandomalgobc(minqpstate* s, ae_state *_state)
{
ae_int_t i;
i = ae_randominteger(2, _state);
if( i==0 )
{
minqpsetalgoquickqp(s, 0.0, 0.0, 1.0E-13, 0, ae_true, _state);
}
if( i==1 )
{
minqpsetalgobleic(s, 1.0E-12, 0.0, 0.0, 0, _state);
}
}
/*************************************************************************
set random type of the QP solver,
must support convex problems with boundary/linear constraints
*************************************************************************/
static void testminqpunit_setrandomalgoconvexlc(minqpstate* s,
ae_state *_state)
{
ae_int_t i;
i = ae_randominteger(4, _state);
if( i==0 )
{
minqpsetalgodenseaul(s, 1.0E-12, (double)(10000), 15, _state);
}
if( i==1 )
{
minqpsetalgobleic(s, 0.0, 0.0, 1.0E-12, 0, _state);
}
if( i==2 )
{
minqpsetalgodenseipm(s, 1.0E-12, _state);
}
if( i==3 )
{
minqpsetalgosparseipm(s, 1.0E-12, _state);
}
}
/*************************************************************************
set random type of the QP solver,
must support nonconvex problems with boundary/linear constraints
*************************************************************************/
static void testminqpunit_setrandomalgononconvexlc(minqpstate* s,
ae_state *_state)
{
ae_int_t i;
i = ae_randominteger(1, _state);
if( i==0 )
{
minqpsetalgobleic(s, 1.0E-12, 0.0, 0.0, 0, _state);
}
}
/*************************************************************************
Convert dense matrix to sparse matrix using random format
*************************************************************************/
static void testminqpunit_densetosparse(/* Real */ ae_matrix* a,
ae_int_t n,
sparsematrix* s,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
sparsematrix s0;
ae_frame_make(_state, &_frame_block);
memset(&s0, 0, sizeof(s0));
_sparsematrix_clear(s);
_sparsematrix_init(&s0, _state, ae_true);
sparsecreate(n, n, n*n, &s0, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
sparseset(&s0, i, j, a->ptr.pp_double[i][j], _state);
}
}
sparsecopytobuf(&s0, ae_randominteger(3, _state), s, _state);
ae_frame_leave(_state);
}
/*************************************************************************
Randomly split constraints into dense and sparse parts
*************************************************************************/
static void testminqpunit_randomlysplitlc(/* Real */ ae_matrix* rawc,
/* Integer */ ae_vector* rawct,
ae_int_t rawccnt,
ae_int_t n,
sparsematrix* sparsec,
/* Integer */ ae_vector* sparsect,
ae_int_t* sparseccnt,
/* Real */ ae_matrix* densec,
/* Integer */ ae_vector* densect,
ae_int_t* denseccnt,
hqrndstate* rs,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
_sparsematrix_clear(sparsec);
ae_vector_clear(sparsect);
*sparseccnt = 0;
ae_matrix_clear(densec);
ae_vector_clear(densect);
*denseccnt = 0;
/*
* Split "raw" constraints into dense and sparse parts
*/
*sparseccnt = hqrnduniformi(rs, rawccnt+1, _state);
*denseccnt = rawccnt-(*sparseccnt);
if( *sparseccnt>0 )
{
sparsecreate(*sparseccnt, n+1, 0, sparsec, _state);
ae_vector_set_length(sparsect, *sparseccnt, _state);
for(i=0; i<=*sparseccnt-1; i++)
{
for(j=0; j<=n; j++)
{
sparseset(sparsec, i, j, rawc->ptr.pp_double[i][j], _state);
}
sparsect->ptr.p_int[i] = rawct->ptr.p_int[i];
}
}
if( *denseccnt>0 )
{
ae_matrix_set_length(densec, *denseccnt, n+1, _state);
ae_vector_set_length(densect, *denseccnt, _state);
for(i=0; i<=*denseccnt-1; i++)
{
for(j=0; j<=n; j++)
{
densec->ptr.pp_double[i][j] = rawc->ptr.pp_double[*sparseccnt+i][j];
}
densect->ptr.p_int[i] = rawct->ptr.p_int[*sparseccnt+i];
}
}
}
/*************************************************************************
Randomly split constraints into dense and sparse parts and set them;
legacy API is used.
*************************************************************************/
static void testminqpunit_randomlysplitandsetlclegacy(/* Real */ ae_matrix* rawc,
/* Integer */ ae_vector* rawct,
ae_int_t rawccnt,
ae_int_t n,
minqpstate* state,
hqrndstate* rs,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix densec;
ae_vector densect;
sparsematrix sparsec;
ae_vector sparsect;
ae_int_t denseccnt;
ae_int_t sparseccnt;
ae_frame_make(_state, &_frame_block);
memset(&densec, 0, sizeof(densec));
memset(&densect, 0, sizeof(densect));
memset(&sparsec, 0, sizeof(sparsec));
memset(&sparsect, 0, sizeof(sparsect));
ae_matrix_init(&densec, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&densect, 0, DT_INT, _state, ae_true);
_sparsematrix_init(&sparsec, _state, ae_true);
ae_vector_init(&sparsect, 0, DT_INT, _state, ae_true);
/*
* reset constraints
*/
minqpsetlc(state, &densec, &densect, 0, _state);
/*
* split and set
*/
testminqpunit_randomlysplitlc(rawc, rawct, rawccnt, n, &sparsec, &sparsect, &sparseccnt, &densec, &densect, &denseccnt, rs, _state);
if( ae_fp_greater(hqrnduniformr(rs, _state),0.5)||denseccnt*sparseccnt>0 )
{
minqpsetlcmixed(state, &sparsec, &sparsect, sparseccnt, &densec, &densect, denseccnt, _state);
}
else
{
if( denseccnt>0 )
{
minqpsetlc(state, &densec, &densect, denseccnt, _state);
}
if( sparseccnt>0 )
{
minqpsetlcsparse(state, &sparsec, &sparsect, sparseccnt, _state);
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Randomly split 2-sided constraints into dense and sparse parts and set them;
*************************************************************************/
static void testminqpunit_randomlysplitandsetlc2(/* Real */ ae_matrix* rawc,
/* Real */ ae_vector* rawcl,
/* Real */ ae_vector* rawcu,
ae_int_t rawccnt,
ae_int_t n,
minqpstate* state,
hqrndstate* rs,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix densec;
ae_vector densecl;
ae_vector densecu;
sparsematrix sparsec;
ae_vector sparsecl;
ae_vector sparsecu;
ae_vector wrkcl;
ae_vector wrkcu;
ae_int_t denseccnt;
ae_int_t sparseccnt;
ae_int_t i;
ae_int_t j;
ae_int_t appenddense;
ae_int_t appendsparse;
ae_vector cv;
ae_vector ci;
ae_int_t nnz;
ae_frame_make(_state, &_frame_block);
memset(&densec, 0, sizeof(densec));
memset(&densecl, 0, sizeof(densecl));
memset(&densecu, 0, sizeof(densecu));
memset(&sparsec, 0, sizeof(sparsec));
memset(&sparsecl, 0, sizeof(sparsecl));
memset(&sparsecu, 0, sizeof(sparsecu));
memset(&wrkcl, 0, sizeof(wrkcl));
memset(&wrkcu, 0, sizeof(wrkcu));
memset(&cv, 0, sizeof(cv));
memset(&ci, 0, sizeof(ci));
ae_matrix_init(&densec, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&densecl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&densecu, 0, DT_REAL, _state, ae_true);
_sparsematrix_init(&sparsec, _state, ae_true);
ae_vector_init(&sparsecl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&sparsecu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&wrkcl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&wrkcu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&cv, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ci, 0, DT_INT, _state, ae_true);
/*
* reset constraints
*/
minqpsetlc2dense(state, &densec, &densecl, &densecu, 0, _state);
/*
* Split "raw" constraints into dense and sparse parts
*/
sparseccnt = hqrnduniformi(rs, rawccnt+1, _state);
denseccnt = rawccnt-sparseccnt;
appenddense = hqrnduniformi(rs, denseccnt+1, _state);
denseccnt = denseccnt-appenddense;
appendsparse = hqrnduniformi(rs, sparseccnt+1, _state);
sparseccnt = sparseccnt-appendsparse;
ae_vector_set_length(&wrkcl, sparseccnt+denseccnt, _state);
ae_vector_set_length(&wrkcu, sparseccnt+denseccnt, _state);
if( sparseccnt>0 )
{
sparsecreate(sparseccnt, n, 0, &sparsec, _state);
ae_vector_set_length(&sparsecl, sparseccnt, _state);
ae_vector_set_length(&sparsecu, sparseccnt, _state);
for(i=0; i<=sparseccnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
sparseset(&sparsec, i, j, rawc->ptr.pp_double[i][j], _state);
}
sparsecl.ptr.p_double[i] = rawcl->ptr.p_double[i];
sparsecu.ptr.p_double[i] = rawcu->ptr.p_double[i];
wrkcl.ptr.p_double[i] = sparsecl.ptr.p_double[i];
wrkcu.ptr.p_double[i] = sparsecu.ptr.p_double[i];
}
}
if( denseccnt>0 )
{
ae_matrix_set_length(&densec, denseccnt, n, _state);
ae_vector_set_length(&densecl, denseccnt, _state);
ae_vector_set_length(&densecu, denseccnt, _state);
for(i=0; i<=denseccnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
densec.ptr.pp_double[i][j] = rawc->ptr.pp_double[sparseccnt+appendsparse+i][j];
}
densecl.ptr.p_double[i] = rawcl->ptr.p_double[sparseccnt+appendsparse+i];
densecu.ptr.p_double[i] = rawcu->ptr.p_double[sparseccnt+appendsparse+i];
wrkcl.ptr.p_double[sparseccnt+i] = densecl.ptr.p_double[i];
wrkcu.ptr.p_double[sparseccnt+i] = densecu.ptr.p_double[i];
}
}
/*
* split and set
*/
if( ae_fp_greater(hqrnduniformr(rs, _state),0.5)||denseccnt*sparseccnt>0 )
{
minqpsetlc2mixed(state, &sparsec, sparseccnt, &densec, denseccnt, &wrkcl, &wrkcu, _state);
}
else
{
if( denseccnt>0 )
{
minqpsetlc2dense(state, &densec, &densecl, &densecu, denseccnt, _state);
}
if( sparseccnt>0 )
{
minqpsetlc2(state, &sparsec, &sparsecl, &sparsecu, sparseccnt, _state);
}
}
ae_vector_set_length(&cv, 2*n, _state);
ae_vector_set_length(&ci, 2*n, _state);
for(i=sparseccnt; i<=sparseccnt+appendsparse-1; i++)
{
/*
* Generate sparse representation
*/
nnz = 0;
for(j=0; j<=n-1; j++)
{
if( ae_fp_neq(rawc->ptr.pp_double[i][j],(double)(0)) )
{
cv.ptr.p_double[nnz] = rawc->ptr.pp_double[i][j];
ci.ptr.p_int[nnz] = j;
nnz = nnz+1;
}
}
/*
* Add duplicates which do not change constraint (after simplification)
*/
while((nnz>0&&nnzptr.p_double[i], rawcu->ptr.p_double[i], _state);
}
for(i=rawccnt-appenddense; i<=rawccnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
cv.ptr.p_double[j] = rawc->ptr.pp_double[i][j];
}
minqpaddlc2dense(state, &cv, rawcl->ptr.p_double[i], rawcu->ptr.p_double[i], _state);
}
ae_frame_leave(_state);
}
/*************************************************************************
Randomly selects triangle of full symmetric matrix, converts it to one of
the matrix storage formats (dense or sparse) and sets.
*************************************************************************/
static void testminqpunit_randomlyselectconvertandsetquadraticterm(/* Real */ ae_matrix* a,
ae_int_t n,
minqpstate* state,
hqrndstate* rs,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_matrix densea;
sparsematrix sparsea;
ae_bool isupper;
ae_bool isdense;
ae_frame_make(_state, &_frame_block);
memset(&densea, 0, sizeof(densea));
memset(&sparsea, 0, sizeof(sparsea));
ae_matrix_init(&densea, 0, 0, DT_REAL, _state, ae_true);
_sparsematrix_init(&sparsea, _state, ae_true);
isupper = ae_fp_greater(hqrnduniformr(rs, _state),0.5);
isdense = ae_fp_greater(hqrnduniformr(rs, _state),0.5);
if( isupper&&isdense )
{
ae_matrix_set_length(&densea, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=i; j<=n-1; j++)
{
densea.ptr.pp_double[i][j] = a->ptr.pp_double[i][j];
}
}
minqpsetquadraticterm(state, &densea, isupper, _state);
ae_frame_leave(_state);
return;
}
if( !isupper&&isdense )
{
ae_matrix_set_length(&densea, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=i; j++)
{
densea.ptr.pp_double[i][j] = a->ptr.pp_double[i][j];
}
}
minqpsetquadraticterm(state, &densea, isupper, _state);
ae_frame_leave(_state);
return;
}
if( isupper&&!isdense )
{
sparsecreate(n, n, 0, &sparsea, _state);
for(i=0; i<=n-1; i++)
{
for(j=i; j<=n-1; j++)
{
sparseset(&sparsea, i, j, a->ptr.pp_double[i][j], _state);
}
}
minqpsetquadratictermsparse(state, &sparsea, isupper, _state);
ae_frame_leave(_state);
return;
}
if( !isupper&&!isdense )
{
sparsecreate(n, n, 0, &sparsea, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=i; j++)
{
sparseset(&sparsea, i, j, a->ptr.pp_double[i][j], _state);
}
}
minqpsetquadratictermsparse(state, &sparsea, isupper, _state);
ae_frame_leave(_state);
return;
}
ae_frame_leave(_state);
}
/*************************************************************************
This function returns reciprocal of condition number of general linear
constraints.
*************************************************************************/
static double testminqpunit_getconstraintrcond(/* Real */ ae_matrix* c,
ae_int_t k,
ae_int_t n,
ae_state *_state)
{
ae_frame _frame_block;
ae_bool bflag;
ae_vector svdw;
ae_matrix svdu;
ae_matrix svdvt;
double result;
ae_frame_make(_state, &_frame_block);
memset(&svdw, 0, sizeof(svdw));
memset(&svdu, 0, sizeof(svdu));
memset(&svdvt, 0, sizeof(svdvt));
ae_vector_init(&svdw, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&svdu, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&svdvt, 0, 0, DT_REAL, _state, ae_true);
bflag = rmatrixsvd(c, k, n, 0, 0, 0, &svdw, &svdu, &svdvt, _state);
ae_assert(bflag, "MinQPTest: integrity failure", _state);
if( ae_fp_greater(svdw.ptr.p_double[0],(double)(0)) )
{
result = svdw.ptr.p_double[ae_minint(k, n, _state)-1]/svdw.ptr.p_double[0];
}
else
{
result = (double)(1);
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Computes target function 0.5*x'*H*x+c'*x
-- ALGLIB --
Copyright 01.11.2019 by Bochkanov Sergey
*************************************************************************/
static double testminqpunit_quadratictarget(/* Real */ ae_matrix* a,
/* Real */ ae_vector* b,
ae_int_t n,
/* Real */ ae_vector* x,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
double result;
result = (double)(0);
for(i=0; i<=n-1; i++)
{
result = result+b->ptr.p_double[i]*x->ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
result = result+0.5*x->ptr.p_double[i]*a->ptr.pp_double[i][j]*x->ptr.p_double[j];
}
}
return result;
}
static void testminlpunit_basictests(ae_bool* err, ae_state *_state);
static void testminlpunit_singlecalltests(ae_bool* err, ae_state *_state);
static void testminlpunit_validatesolution(/* Real */ ae_vector* c,
/* Real */ ae_vector* bndl,
/* Real */ ae_vector* bndu,
ae_int_t n,
/* Real */ ae_matrix* a,
/* Real */ ae_vector* al,
/* Real */ ae_vector* au,
ae_int_t m,
/* Real */ ae_vector* xcand,
minlpreport* rep,
double* errprim,
double* errdual,
ae_state *_state);
static void testminlpunit_generatelpproblem(hqrndstate* rs,
ae_int_t n,
/* Real */ ae_vector* c,
/* Real */ ae_vector* bndl,
/* Real */ ae_vector* bndu,
/* Real */ ae_matrix* a,
/* Real */ ae_vector* al,
/* Real */ ae_vector* au,
ae_int_t* m,
ae_state *_state);
static void testminlpunit_generateunboundedlpproblem(hqrndstate* rs,
ae_int_t n,
/* Real */ ae_vector* c,
/* Real */ ae_vector* bndl,
/* Real */ ae_vector* bndu,
/* Real */ ae_matrix* a,
/* Real */ ae_vector* al,
/* Real */ ae_vector* au,
ae_int_t* m,
ae_state *_state);
static void testminlpunit_generateinfeasiblelpproblem(hqrndstate* rs,
ae_int_t n,
/* Real */ ae_vector* c,
/* Real */ ae_vector* bndl,
/* Real */ ae_vector* bndu,
/* Real */ ae_matrix* a,
/* Real */ ae_vector* al,
/* Real */ ae_vector* au,
ae_int_t* m,
ae_state *_state);
static void testminlpunit_generatecabxd(hqrndstate* rs,
ae_int_t n,
ae_int_t m,
/* Real */ ae_vector* c,
/* Real */ ae_matrix* a,
/* Real */ ae_vector* xx,
/* Real */ ae_vector* d,
/* Integer */ ae_vector* basicnonbasic,
ae_state *_state);
static void testminlpunit_generatebounds(hqrndstate* rs,
ae_int_t n,
ae_int_t m,
/* Real */ ae_vector* xx,
/* Real */ ae_vector* d,
/* Integer */ ae_vector* basicnonbasic,
/* Real */ ae_vector* bndl,
/* Real */ ae_vector* bndu,
/* Real */ ae_vector* al,
/* Real */ ae_vector* au,
ae_state *_state);
static void testminlpunit_modifyandsendconstraintsto(ae_int_t n,
/* Real */ ae_matrix* a,
/* Real */ ae_vector* al,
/* Real */ ae_vector* au,
ae_int_t m,
hqrndstate* rs,
minlpstate* state,
ae_state *_state);
ae_bool testminlp(ae_bool silent, ae_state *_state)
{
ae_bool basicerrors;
ae_bool singlecall;
ae_bool wereerrors;
ae_bool result;
basicerrors = ae_false;
singlecall = ae_false;
result = ae_true;
testminlpunit_basictests(&basicerrors, _state);
testminlpunit_singlecalltests(&singlecall, _state);
/*
* report
*/
wereerrors = basicerrors||singlecall;
if( !silent )
{
printf("TESTING MinLP\n");
printf("BASIC TESTS ");
if( basicerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("COMMON TESTS:\n");
printf("* single call usage ");
if( singlecall )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( wereerrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !wereerrors;
return result;
}
/*************************************************************************
Basic tests; sets error flag on failure, does not touch it on success.
*************************************************************************/
static void testminlpunit_basictests(ae_bool* err, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t n;
ae_int_t ccnt;
ae_int_t pass;
minlpstate state;
minlpreport rep;
ae_vector c;
ae_vector x;
ae_vector x0;
ae_vector x2;
ae_vector bndl;
ae_vector bndu;
ae_vector al;
ae_vector au;
ae_matrix a;
double v0;
double v1;
double primtol;
double dualtol;
hqrndstate rs;
ae_frame_make(_state, &_frame_block);
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&c, 0, sizeof(c));
memset(&x, 0, sizeof(x));
memset(&x0, 0, sizeof(x0));
memset(&x2, 0, sizeof(x2));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(&al, 0, sizeof(al));
memset(&au, 0, sizeof(au));
memset(&a, 0, sizeof(a));
memset(&rs, 0, sizeof(rs));
_minlpstate_init(&state, _state, ae_true);
_minlpreport_init(&rep, _state, ae_true);
ae_vector_init(&c, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&al, 0, DT_REAL, _state, ae_true);
ae_vector_init(&au, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
primtol = 1.0E-6;
dualtol = 1.0E-6;
hqrndrandomize(&rs, _state);
/*
* Test default state of the solver
*/
for(pass=1; pass<=5; pass++)
{
n = 1+hqrnduniformi(&rs, 10, _state);
minlpcreate(n, &state, _state);
minlpoptimize(&state, _state);
minlpresults(&state, &x, &rep, _state);
ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminlpunit.ap:92");
ae_set_error_flag(err, x.cntv_posinf;
}
if( ae_fp_less(c.ptr.p_double[i],(double)(0)) )
{
bndl.ptr.p_double[i] = _state->v_neginf;
}
}
minlpcreate(n, &state, _state);
minlpsetcost(&state, &c, _state);
minlpsetbc(&state, &bndl, &bndu, _state);
minlpoptimize(&state, _state);
minlpresults(&state, &x, &rep, _state);
ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminlpunit.ap:151");
ae_set_error_flag(err, x.cntv_neginf;
bndu.ptr.p_double[k] = _state->v_posinf;
minlpcreate(n, &state, _state);
minlpsetcost(&state, &c, _state);
minlpsetbc(&state, &bndl, &bndu, _state);
minlpoptimize(&state, _state);
minlpresults(&state, &x, &rep, _state);
ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminlpunit.ap:180");
ae_set_error_flag(err, x.cntv_posinf;
minlpsetbc(&state, &bndl, &bndu, _state);
minlpoptimize(&state, _state);
minlpresults(&state, &x, &rep, _state);
ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminlpunit.ap:196");
ae_set_error_flag(err, x.cntv_neginf;
bndu.ptr.p_double[k] = hqrndnormal(&rs, _state);
minlpsetbc(&state, &bndl, &bndu, _state);
minlpoptimize(&state, _state);
minlpresults(&state, &x, &rep, _state);
ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminlpunit.ap:212");
ae_set_error_flag(err, x.cntv_neginf;
}
else
{
bndu.ptr.p_double[k] = _state->v_posinf;
}
minlpcreate(n, &state, _state);
minlpsetcost(&state, &c, _state);
minlpsetbc(&state, &bndl, &bndu, _state);
minlpoptimize(&state, _state);
minlpresults(&state, &x, &rep, _state);
ae_set_error_flag(err, rep.terminationtype!=-4, __FILE__, __LINE__, "testminlpunit.ap:267");
ae_set_error_flag(err, x.cntptr.p_double[i], _state) )
{
*errprim = ae_maxreal(*errprim, bndl->ptr.p_double[i]-xcand->ptr.p_double[i], _state);
}
if( ae_isfinite(bndu->ptr.p_double[i], _state) )
{
*errprim = ae_maxreal(*errprim, xcand->ptr.p_double[i]-bndu->ptr.p_double[i], _state);
}
}
for(i=0; i<=m-1; i++)
{
v = ae_v_dotproduct(&a->ptr.pp_double[i][0], 1, &xcand->ptr.p_double[0], 1, ae_v_len(0,n-1));
if( ae_isfinite(al->ptr.p_double[i], _state) )
{
*errprim = ae_maxreal(*errprim, al->ptr.p_double[i]-v, _state);
}
if( ae_isfinite(au->ptr.p_double[i], _state) )
{
*errprim = ae_maxreal(*errprim, v-au->ptr.p_double[i], _state);
}
}
/*
* Compute reduced costs.
* Test dual feasibility.
*/
ae_vector_set_length(&d, nx, _state);
for(i=0; i<=n-1; i++)
{
d.ptr.p_double[i] = c->ptr.p_double[i];
}
for(i=n; i<=nx-1; i++)
{
d.ptr.p_double[i] = (double)(0);
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
d.ptr.p_double[j] = d.ptr.p_double[j]-rep->y.ptr.p_double[i]*a->ptr.pp_double[i][j];
}
d.ptr.p_double[n+i] = d.ptr.p_double[n+i]+rep->y.ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
if( (ae_isfinite(bndl->ptr.p_double[i], _state)&&ae_isfinite(bndu->ptr.p_double[i], _state))&&ae_fp_eq(bndl->ptr.p_double[i],bndu->ptr.p_double[i]) )
{
continue;
}
if( ae_isfinite(bndl->ptr.p_double[i], _state)&&ae_fp_eq(xcand->ptr.p_double[i],bndl->ptr.p_double[i]) )
{
*errdual = ae_maxreal(*errdual, -d.ptr.p_double[i], _state);
continue;
}
if( ae_isfinite(bndu->ptr.p_double[i], _state)&&ae_fp_eq(xcand->ptr.p_double[i],bndu->ptr.p_double[i]) )
{
*errdual = ae_maxreal(*errdual, d.ptr.p_double[i], _state);
continue;
}
*errdual = ae_maxreal(*errdual, ae_fabs(d.ptr.p_double[i], _state), _state);
}
for(i=0; i<=m-1; i++)
{
if( (ae_isfinite(al->ptr.p_double[i], _state)&&ae_isfinite(au->ptr.p_double[i], _state))&&ae_fp_eq(al->ptr.p_double[i],au->ptr.p_double[i]) )
{
continue;
}
if( ae_isfinite(al->ptr.p_double[i], _state)&&rep->stats.ptr.p_int[n+i]<0 )
{
*errdual = ae_maxreal(*errdual, -d.ptr.p_double[n+i], _state);
continue;
}
if( ae_isfinite(au->ptr.p_double[i], _state)&&rep->stats.ptr.p_int[n+i]>0 )
{
*errdual = ae_maxreal(*errdual, d.ptr.p_double[n+i], _state);
continue;
}
*errdual = ae_maxreal(*errdual, ae_fabs(d.ptr.p_double[n+i], _state), _state);
}
ynrm = (double)(0);
for(i=0; i<=m-1; i++)
{
ynrm = ae_maxreal(ynrm, ae_fabs(rep->y.ptr.p_double[i], _state), _state);
}
*errdual = *errdual/ae_maxreal(ynrm, 1.0, _state);
ae_frame_leave(_state);
}
/*************************************************************************
This function generates random LP problem with user-specified number of
variables, with several problem types being randomly chosen internally.
Constraint counts and types are generated randomly; it is possible that
zero amount of constraints is generated.
*************************************************************************/
static void testminlpunit_generatelpproblem(hqrndstate* rs,
ae_int_t n,
/* Real */ ae_vector* c,
/* Real */ ae_vector* bndl,
/* Real */ ae_vector* bndu,
/* Real */ ae_matrix* a,
/* Real */ ae_vector* al,
/* Real */ ae_vector* au,
ae_int_t* m,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t ptype;
ae_int_t pcount;
ae_vector x0;
ae_vector xx;
ae_vector d;
ae_vector basicnonbasic;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t kk;
ae_int_t kt;
double v;
double q;
double big;
ae_int_t nprimal;
ae_int_t ndual;
ae_frame_make(_state, &_frame_block);
memset(&x0, 0, sizeof(x0));
memset(&xx, 0, sizeof(xx));
memset(&d, 0, sizeof(d));
memset(&basicnonbasic, 0, sizeof(basicnonbasic));
ae_vector_clear(c);
ae_vector_clear(bndl);
ae_vector_clear(bndu);
ae_matrix_clear(a);
ae_vector_clear(al);
ae_vector_clear(au);
*m = 0;
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&basicnonbasic, 0, DT_INT, _state, ae_true);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(c, n, _state);
ae_vector_set_length(bndl, n, _state);
ae_vector_set_length(bndu, n, _state);
/*
* Choose problem type
*/
pcount = 4;
ptype = hqrnduniformi(rs, pcount, _state);
/*
* A linearly constrained LP problem with all variables/linear constraints
* being boxed (easy start).
*/
if( ptype==0 )
{
q = 5.0;
*m = 1+hqrnduniformi(rs, 2*n, _state);
ae_matrix_set_length(a, *m, n, _state);
ae_vector_set_length(al, *m, _state);
ae_vector_set_length(au, *m, _state);
for(i=0; i<=n-1; i++)
{
c->ptr.p_double[i] = hqrndnormal(rs, _state);
bndl->ptr.p_double[i] = ae_pow(q, hqrndnormal(rs, _state), _state)-ae_pow(q, hqrndnormal(rs, _state), _state);
bndu->ptr.p_double[i] = bndl->ptr.p_double[i]+ae_pow(q, hqrndnormal(rs, _state), _state);
v = 0.01+0.98*hqrnduniformr(rs, _state);
x0.ptr.p_double[i] = (1-v)*bndl->ptr.p_double[i]+v*bndu->ptr.p_double[i];
}
for(i=0; i<=*m-1; i++)
{
v = 0.0;
for(j=0; j<=n-1; j++)
{
a->ptr.pp_double[i][j] = hqrndnormal(rs, _state)*hqrnduniformi(rs, 2, _state);
v = v+a->ptr.pp_double[i][j]*x0.ptr.p_double[j];
}
al->ptr.p_double[i] = v-ae_pow(q, hqrndnormal(rs, _state), _state);
au->ptr.p_double[i] = v+ae_pow(q, hqrndnormal(rs, _state), _state);
}
ae_frame_leave(_state);
return;
}
/*
* A linearly constrained LP problem with up to M variables (linear
* constraints) being non-boxed (free or having just one constraint).
* A bit harder than all-boxed version.
*
* NOTE: components of C[] corresponding to these non-boxed variables
* are chosen in a way which guarantees dual feasibility of the
* problem.
*/
if( ptype==1 )
{
q = 2.0;
big = 100.00;
*m = 1+hqrnduniformi(rs, 2*n, _state);
ae_matrix_set_length(a, *m, n, _state);
ae_vector_set_length(al, *m, _state);
ae_vector_set_length(au, *m, _state);
for(i=0; i<=n-1; i++)
{
c->ptr.p_double[i] = hqrndnormal(rs, _state);
bndl->ptr.p_double[i] = ae_pow(q, hqrndnormal(rs, _state), _state)-ae_pow(q, hqrndnormal(rs, _state), _state);
bndu->ptr.p_double[i] = bndl->ptr.p_double[i]+ae_pow(q, hqrndnormal(rs, _state), _state);
v = 0.01+0.98*hqrnduniformr(rs, _state);
x0.ptr.p_double[i] = (1-v)*bndl->ptr.p_double[i]+v*bndu->ptr.p_double[i];
}
for(i=0; i<=*m-1; i++)
{
v = 0.0;
for(j=0; j<=n-1; j++)
{
a->ptr.pp_double[i][j] = hqrndnormal(rs, _state);
v = v+a->ptr.pp_double[i][j]*x0.ptr.p_double[j];
}
al->ptr.p_double[i] = v-ae_pow(q, hqrndnormal(rs, _state), _state);
au->ptr.p_double[i] = v+ae_pow(q, hqrndnormal(rs, _state), _state);
}
kk = 1+hqrnduniformi(rs, *m, _state);
for(k=0; k<=kk-1; k++)
{
i = hqrnduniformi(rs, n+(*m), _state);
if( iptr.p_double[i] = _state->v_neginf;
c->ptr.p_double[i] = -big*(1+hqrnduniformr(rs, _state));
}
if( kt==1 )
{
bndu->ptr.p_double[i] = _state->v_posinf;
c->ptr.p_double[i] = big*(1+hqrnduniformr(rs, _state));
}
if( kt==2 )
{
bndl->ptr.p_double[i] = _state->v_neginf;
bndu->ptr.p_double[i] = _state->v_posinf;
}
}
else
{
kt = hqrnduniformi(rs, 3, _state);
if( kt==0 )
{
au->ptr.p_double[i-n] = _state->v_posinf;
}
if( kt==1 )
{
al->ptr.p_double[i-n] = _state->v_neginf;
}
if( kt==2 )
{
al->ptr.p_double[i-n] = _state->v_neginf;
au->ptr.p_double[i-n] = _state->v_posinf;
}
}
}
ae_frame_leave(_state);
return;
}
/*
* A randomly generated non-degenerate LP problem. A mix of fixed,
* range, upper/lower bounds and free variables.
*/
if( ptype==2 )
{
*m = 1+hqrnduniformi(rs, 2*n, _state);
testminlpunit_generatecabxd(rs, n, *m, c, a, &xx, &d, &basicnonbasic, _state);
testminlpunit_generatebounds(rs, n, *m, &xx, &d, &basicnonbasic, bndl, bndu, al, au, _state);
ae_frame_leave(_state);
return;
}
/*
* A randomly generated primal/dual degenerate LP problem. A mix of
* fixed, range, upper/lower bounds and free variables.
*/
if( ptype==3 )
{
*m = 1+hqrnduniformi(rs, 2*n, _state);
testminlpunit_generatecabxd(rs, n, *m, c, a, &xx, &d, &basicnonbasic, _state);
testminlpunit_generatebounds(rs, n, *m, &xx, &d, &basicnonbasic, bndl, bndu, al, au, _state);
ndual = 1+hqrnduniformi(rs, *m, _state);
for(i=0; i<=ndual-1; i++)
{
j = basicnonbasic.ptr.p_int[*m+hqrnduniformi(rs, n, _state)];
if( jptr.p_double[j] = c->ptr.p_double[j]-d.ptr.p_double[j];
d.ptr.p_double[j] = (double)(0);
}
}
nprimal = 1+hqrnduniformi(rs, *m, _state);
for(i=0; i<=nprimal-1; i++)
{
j = basicnonbasic.ptr.p_int[hqrnduniformi(rs, *m, _state)];
if( jptr.p_double[j] = xx.ptr.p_double[j];
}
else
{
bndu->ptr.p_double[j] = xx.ptr.p_double[j];
}
}
else
{
if( ae_fp_greater(hqrndnormal(rs, _state),(double)(0)) )
{
al->ptr.p_double[j-n] = xx.ptr.p_double[j];
}
else
{
au->ptr.p_double[j-n] = xx.ptr.p_double[j];
}
}
}
ae_frame_leave(_state);
return;
}
ae_assert(ae_false, "GenerateLPProblem failed", _state);
ae_frame_leave(_state);
}
/*************************************************************************
This function generates random primal unbounded LP problem.
*************************************************************************/
static void testminlpunit_generateunboundedlpproblem(hqrndstate* rs,
ae_int_t n,
/* Real */ ae_vector* c,
/* Real */ ae_vector* bndl,
/* Real */ ae_vector* bndu,
/* Real */ ae_matrix* a,
/* Real */ ae_vector* al,
/* Real */ ae_vector* au,
ae_int_t* m,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_int_t ptype;
ae_int_t pcount;
double v;
double vv;
double q;
ae_vector x0;
ae_frame_make(_state, &_frame_block);
memset(&x0, 0, sizeof(x0));
ae_vector_clear(c);
ae_vector_clear(bndl);
ae_vector_clear(bndu);
ae_matrix_clear(a);
ae_vector_clear(al);
ae_vector_clear(au);
*m = 0;
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_set_length(c, n, _state);
ae_vector_set_length(bndl, n, _state);
ae_vector_set_length(bndu, n, _state);
/*
* Choose problem type
*/
pcount = 2;
ptype = hqrnduniformi(rs, pcount, _state);
/*
* Boundary-only constraints, can be easily made primal unbounded
*/
if( ptype==0 )
{
q = 5.0;
*m = 0;
ae_matrix_set_length(a, 0, 0, _state);
ae_vector_set_length(al, 0, _state);
ae_vector_set_length(au, 0, _state);
for(i=0; i<=n-1; i++)
{
c->ptr.p_double[i] = hqrndnormal(rs, _state);
v = ae_pow(q, hqrndnormal(rs, _state), _state)-ae_pow(q, hqrndnormal(rs, _state), _state);
if( ae_fp_greater(c->ptr.p_double[i],(double)(0)) )
{
bndl->ptr.p_double[i] = v;
bndu->ptr.p_double[i] = _state->v_posinf;
}
else
{
bndl->ptr.p_double[i] = _state->v_neginf;
bndu->ptr.p_double[i] = v;
}
}
i = hqrnduniformi(rs, n, _state);
do
{
c->ptr.p_double[i] = hqrndnormal(rs, _state);
}
while(ae_fp_eq(c->ptr.p_double[i],(double)(0)));
v = ae_pow(q, hqrndnormal(rs, _state), _state)-ae_pow(q, hqrndnormal(rs, _state), _state);
if( ae_fp_less(c->ptr.p_double[i],(double)(0)) )
{
bndl->ptr.p_double[i] = v;
bndu->ptr.p_double[i] = _state->v_posinf;
}
else
{
bndl->ptr.p_double[i] = _state->v_neginf;
bndu->ptr.p_double[i] = v;
}
ae_frame_leave(_state);
return;
}
/*
* Boundary and single-sided linear constraints; a bit more tricky to make it primal unbounded
*/
if( ptype==1 )
{
q = 5.0;
*m = 1+hqrnduniformi(rs, 2*n, _state);
ae_matrix_set_length(a, *m, n, _state);
ae_vector_set_length(al, *m, _state);
ae_vector_set_length(au, *m, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
c->ptr.p_double[i] = hqrndnormal(rs, _state);
x0.ptr.p_double[i] = hqrndnormal(rs, _state);
if( ae_fp_greater_eq(c->ptr.p_double[i],(double)(0)) )
{
bndl->ptr.p_double[i] = _state->v_neginf;
bndu->ptr.p_double[i] = x0.ptr.p_double[i];
}
else
{
bndl->ptr.p_double[i] = x0.ptr.p_double[i];
bndu->ptr.p_double[i] = _state->v_posinf;
}
}
for(i=0; i<=*m-1; i++)
{
v = (double)(0);
vv = (double)(0);
for(j=0; j<=n-1; j++)
{
a->ptr.pp_double[i][j] = hqrndnormal(rs, _state);
v = v+a->ptr.pp_double[i][j]*x0.ptr.p_double[j];
vv = vv+a->ptr.pp_double[i][j]*c->ptr.p_double[j];
}
if( ae_fp_greater_eq(vv,(double)(0)) )
{
al->ptr.p_double[i] = _state->v_neginf;
au->ptr.p_double[i] = v;
}
else
{
al->ptr.p_double[i] = v;
au->ptr.p_double[i] = _state->v_posinf;
}
}
ae_frame_leave(_state);
return;
}
ae_assert(ae_false, "GenerateUnboundedLPProblem failed", _state);
ae_frame_leave(_state);
}
/*************************************************************************
This function generates random primal infeasible LP problem
*************************************************************************/
static void testminlpunit_generateinfeasiblelpproblem(hqrndstate* rs,
ae_int_t n,
/* Real */ ae_vector* c,
/* Real */ ae_vector* bndl,
/* Real */ ae_vector* bndu,
/* Real */ ae_matrix* a,
/* Real */ ae_vector* al,
/* Real */ ae_vector* au,
ae_int_t* m,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t ptype;
ae_int_t pcount;
double v;
double q;
ae_vector xx;
ae_vector d;
ae_vector x0;
ae_vector tmpi;
ae_frame_make(_state, &_frame_block);
memset(&xx, 0, sizeof(xx));
memset(&d, 0, sizeof(d));
memset(&x0, 0, sizeof(x0));
memset(&tmpi, 0, sizeof(tmpi));
ae_vector_clear(c);
ae_vector_clear(bndl);
ae_vector_clear(bndu);
ae_matrix_clear(a);
ae_vector_clear(al);
ae_vector_clear(au);
*m = 0;
ae_vector_init(&xx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmpi, 0, DT_INT, _state, ae_true);
ae_vector_set_length(c, n, _state);
ae_vector_set_length(bndl, n, _state);
ae_vector_set_length(bndu, n, _state);
/*
* Choose problem type
*/
pcount = 3;
ptype = hqrnduniformi(rs, pcount, _state);
/*
* Boundary-only constraints, can be easily made primal infeasible
*/
if( ptype==0 )
{
q = 5.0;
*m = 0;
ae_matrix_set_length(a, 0, 0, _state);
ae_vector_set_length(al, 0, _state);
ae_vector_set_length(au, 0, _state);
for(i=0; i<=n-1; i++)
{
c->ptr.p_double[i] = hqrndnormal(rs, _state);
v = ae_pow(q, hqrndnormal(rs, _state), _state)-ae_pow(q, hqrndnormal(rs, _state), _state);
bndl->ptr.p_double[i] = v-ae_pow(q, hqrndnormal(rs, _state), _state);
bndu->ptr.p_double[i] = v+ae_pow(q, hqrndnormal(rs, _state), _state);
}
i = hqrnduniformi(rs, n, _state);
v = bndl->ptr.p_double[i];
bndl->ptr.p_double[i] = bndu->ptr.p_double[i];
bndu->ptr.p_double[i] = v;
ae_frame_leave(_state);
return;
}
/*
* Linearly constrained problem with infeasible box constraints
*/
if( ptype==1 )
{
q = (double)(5);
*m = 1+hqrnduniformi(rs, 2*n, _state);
testminlpunit_generatecabxd(rs, n, *m, c, a, &xx, &d, &tmpi, _state);
testminlpunit_generatebounds(rs, n, *m, &xx, &d, &tmpi, bndl, bndu, al, au, _state);
i = hqrnduniformi(rs, n, _state);
v = ae_pow(q, hqrndnormal(rs, _state), _state)-ae_pow(q, hqrndnormal(rs, _state), _state);
bndl->ptr.p_double[i] = v+ae_pow(q, hqrndnormal(rs, _state), _state);
bndu->ptr.p_double[i] = v-ae_pow(q, hqrndnormal(rs, _state), _state);
ae_frame_leave(_state);
return;
}
/*
* Linearly constrained problem with infeasible linear constraints
*/
if( ptype==2 )
{
q = (double)(5);
*m = 1+hqrnduniformi(rs, 2*n, _state);
testminlpunit_generatecabxd(rs, n, *m, c, a, &xx, &d, &tmpi, _state);
testminlpunit_generatebounds(rs, n, *m, &xx, &d, &tmpi, bndl, bndu, al, au, _state);
rmatrixresize(a, a->rows+1, a->cols, _state);
rvectorresize(al, al->cnt+1, _state);
rvectorresize(au, au->cnt+1, _state);
for(i=0; i<=n-1; i++)
{
a->ptr.pp_double[*m][i] = a->ptr.pp_double[*m-1][i];
}
if( ae_isfinite(al->ptr.p_double[*m-1], _state)&&ae_isfinite(au->ptr.p_double[*m-1], _state) )
{
v = ae_pow(q, hqrndnormal(rs, _state), _state);
al->ptr.p_double[*m] = au->ptr.p_double[*m-1]+v;
au->ptr.p_double[*m] = al->ptr.p_double[*m]+ae_pow(q, hqrndnormal(rs, _state), _state);
}
if( ae_isfinite(al->ptr.p_double[*m-1], _state)&&!ae_isfinite(au->ptr.p_double[*m-1], _state) )
{
v = ae_pow(q, hqrndnormal(rs, _state), _state);
au->ptr.p_double[*m] = al->ptr.p_double[*m-1]-v;
al->ptr.p_double[*m] = au->ptr.p_double[*m]-ae_pow(q, hqrndnormal(rs, _state), _state);
}
if( !ae_isfinite(al->ptr.p_double[*m-1], _state)&&ae_isfinite(au->ptr.p_double[*m-1], _state) )
{
v = ae_pow(q, hqrndnormal(rs, _state), _state);
al->ptr.p_double[*m] = au->ptr.p_double[*m-1]+v;
au->ptr.p_double[*m] = al->ptr.p_double[*m]+ae_pow(q, hqrndnormal(rs, _state), _state);
}
if( !ae_isfinite(al->ptr.p_double[*m-1], _state)&&!ae_isfinite(au->ptr.p_double[*m-1], _state) )
{
v = ae_pow(q, hqrndnormal(rs, _state), _state);
al->ptr.p_double[*m] = v;
au->ptr.p_double[*m] = v-ae_pow(q, hqrndnormal(rs, _state), _state);
}
*m = *m+1;
ae_frame_leave(_state);
return;
}
ae_assert(ae_false, "GenerateUnboundedLPProblem failed", _state);
ae_frame_leave(_state);
}
/*************************************************************************
This function generates random C[] and A[] as well as feasible point XX[N+M],
with XX[0..N-1] being structural variables and XX[N..N+M-1] being values
of logical variables.
It also splits structural/logical variables into basic/nonbasic ones and
generates BasicNonbasic[] array, with indexes of basic variables being stored in
first M positions, and indexes of non-basic variables being stored in the
next N positions.
*************************************************************************/
static void testminlpunit_generatecabxd(hqrndstate* rs,
ae_int_t n,
ae_int_t m,
/* Real */ ae_vector* c,
/* Real */ ae_matrix* a,
/* Real */ ae_vector* xx,
/* Real */ ae_vector* d,
/* Integer */ ae_vector* basicnonbasic,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector y;
ae_vector cx;
ae_matrix ax;
ae_matrix bt;
ae_vector pivots;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t kk;
double v;
ae_frame_make(_state, &_frame_block);
memset(&y, 0, sizeof(y));
memset(&cx, 0, sizeof(cx));
memset(&ax, 0, sizeof(ax));
memset(&bt, 0, sizeof(bt));
memset(&pivots, 0, sizeof(pivots));
ae_vector_clear(c);
ae_matrix_clear(a);
ae_vector_clear(xx);
ae_vector_clear(d);
ae_vector_clear(basicnonbasic);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&cx, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ax, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&bt, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&pivots, 0, DT_INT, _state, ae_true);
ae_vector_set_length(xx, n, _state);
ae_vector_set_length(c, n, _state);
ae_matrix_set_length(a, m, n, _state);
ae_vector_set_length(xx, n+m, _state);
ae_vector_set_length(&cx, n+m, _state);
for(i=0; i<=n-1; i++)
{
xx->ptr.p_double[i] = hqrndnormal(rs, _state);
cx.ptr.p_double[i] = hqrndnormal(rs, _state);
c->ptr.p_double[i] = cx.ptr.p_double[i];
}
for(i=n; i<=n+m-1; i++)
{
xx->ptr.p_double[i] = (double)(0);
cx.ptr.p_double[i] = (double)(0);
}
ae_matrix_set_length(&ax, m, n+m, _state);
for(i=0; i<=m-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
ax.ptr.pp_double[i][j] = hqrndnormal(rs, _state);
a->ptr.pp_double[i][j] = ax.ptr.pp_double[i][j];
v = v+xx->ptr.p_double[j]*ax.ptr.pp_double[i][j];
}
xx->ptr.p_double[n+i] = v;
for(j=0; j<=m-1; j++)
{
ax.ptr.pp_double[i][n+j] = (double)(0);
}
ax.ptr.pp_double[i][n+i] = (double)(-1);
}
/*
* Randomly select M basic variables, compute Y and D
*/
ae_matrix_set_length(&bt, m, m, _state);
ae_vector_set_length(&y, m, _state);
ae_vector_set_length(basicnonbasic, n+m, _state);
for(i=0; i<=n+m-1; i++)
{
basicnonbasic->ptr.p_int[i] = i;
}
for(i=0; i<=m-1; i++)
{
k = i+hqrnduniformi(rs, n+m-i, _state);
kk = basicnonbasic->ptr.p_int[i];
basicnonbasic->ptr.p_int[i] = basicnonbasic->ptr.p_int[k];
basicnonbasic->ptr.p_int[k] = kk;
for(j=0; j<=m-1; j++)
{
bt.ptr.pp_double[i][j] = ax.ptr.pp_double[j][basicnonbasic->ptr.p_int[i]];
}
y.ptr.p_double[i] = cx.ptr.p_double[basicnonbasic->ptr.p_int[i]];
}
rmatrixlu(&bt, m, m, &pivots, _state);
for(i=0; i<=m-1; i++)
{
if( pivots.ptr.p_int[i]!=i )
{
v = y.ptr.p_double[i];
y.ptr.p_double[i] = y.ptr.p_double[pivots.ptr.p_int[i]];
y.ptr.p_double[pivots.ptr.p_int[i]] = v;
}
}
rmatrixtrsv(m, &bt, 0, 0, ae_false, ae_true, 0, &y, 0, _state);
rmatrixtrsv(m, &bt, 0, 0, ae_true, ae_false, 0, &y, 0, _state);
ae_vector_set_length(d, n+m, _state);
for(i=0; i<=n+m-1; i++)
{
d->ptr.p_double[i] = cx.ptr.p_double[i];
}
rmatrixgemv(n+m, m, -1.0, &ax, 0, 0, 1, &y, 0, 1.0, d, 0, _state);
ae_frame_leave(_state);
}
/*************************************************************************
This function generates random non-degenerate bounds for given XX and D.
*************************************************************************/
static void testminlpunit_generatebounds(hqrndstate* rs,
ae_int_t n,
ae_int_t m,
/* Real */ ae_vector* xx,
/* Real */ ae_vector* d,
/* Integer */ ae_vector* basicnonbasic,
/* Real */ ae_vector* bndl,
/* Real */ ae_vector* bndu,
/* Real */ ae_vector* al,
/* Real */ ae_vector* au,
ae_state *_state)
{
double v0;
double v1;
double q;
ae_int_t i;
ae_int_t kk;
ae_vector_clear(bndl);
ae_vector_clear(bndu);
ae_vector_clear(al);
ae_vector_clear(au);
ae_vector_set_length(bndl, n, _state);
ae_vector_set_length(bndu, n, _state);
ae_vector_set_length(al, m, _state);
ae_vector_set_length(au, m, _state);
/*
* Choose bounds in such a way that non-basic variables are
* strictly at the bounds and dual feasible, and all basic
* variables are strictly within bounds.
*/
q = (double)(5);
for(kk=0; kk<=n+m-1; kk++)
{
i = basicnonbasic->ptr.p_int[kk];
v0 = xx->ptr.p_double[i]-ae_pow(q, hqrndnormal(rs, _state), _state);
v1 = xx->ptr.p_double[i]+ae_pow(q, hqrndnormal(rs, _state), _state);
if( ae_fp_greater(hqrndnormal(rs, _state),(double)(0)) )
{
v0 = _state->v_neginf;
}
if( ae_fp_greater(hqrndnormal(rs, _state),(double)(0)) )
{
v1 = _state->v_posinf;
}
if( kk>=m )
{
if( ae_fp_greater_eq(d->ptr.p_double[i],(double)(0)) )
{
v0 = xx->ptr.p_double[i];
if( ae_fp_less(hqrnduniformr(rs, _state),0.05) )
{
v1 = v0;
}
}
else
{
v1 = xx->ptr.p_double[i];
if( ae_fp_less(hqrnduniformr(rs, _state),0.05) )
{
v0 = v1;
}
}
}
if( iptr.p_double[i] = v0;
bndu->ptr.p_double[i] = v1;
}
else
{
al->ptr.p_double[i-n] = v0;
au->ptr.p_double[i-n] = v1;
}
}
}
/*************************************************************************
This function sets linear constraints using randomly chosen sequence of
SetLC/AddLC calls.
It may also modify constraints:
* split two-sided constraint into two one-sided constraints
* create duplicates
* insert zero dummies
Thus, you should not use this function when you want to test things like
correctness of Lagrange multipliers and so on.
*************************************************************************/
static void testminlpunit_modifyandsendconstraintsto(ae_int_t n,
/* Real */ ae_matrix* a,
/* Real */ ae_vector* al,
/* Real */ ae_vector* au,
ae_int_t m,
hqrndstate* rs,
minlpstate* state,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t stype;
ae_vector ai;
ae_vector idxi;
ae_int_t nz;
ae_int_t nzmod;
ae_matrix a1;
sparsematrix sa;
ae_vector ct;
ae_int_t ccnt;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t t;
ae_int_t minit;
ae_int_t nadd;
ae_int_t ndup;
double v;
ae_frame_make(_state, &_frame_block);
memset(&ai, 0, sizeof(ai));
memset(&idxi, 0, sizeof(idxi));
memset(&a1, 0, sizeof(a1));
memset(&sa, 0, sizeof(sa));
memset(&ct, 0, sizeof(ct));
ae_vector_init(&ai, 0, DT_REAL, _state, ae_true);
ae_vector_init(&idxi, 0, DT_INT, _state, ae_true);
ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true);
_sparsematrix_init(&sa, _state, ae_true);
ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
/*
* Choose sequence type
*/
stype = hqrnduniformi(rs, 4, _state);
/*
* Straightforward SetLC2() call
*/
if( stype==0 )
{
minlpsetlc2dense(state, a, al, au, m, _state);
ae_frame_leave(_state);
return;
}
/*
* SetLC1() call (conversion to other format)
*/
if( stype==1 )
{
ae_matrix_set_length(&a1, 2*m, n+1, _state);
ae_vector_set_length(&ct, 2*m, _state);
ccnt = 0;
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
a1.ptr.pp_double[ccnt+0][j] = a->ptr.pp_double[i][j];
a1.ptr.pp_double[ccnt+1][j] = a->ptr.pp_double[i][j];
}
if( (ae_isfinite(al->ptr.p_double[i], _state)&&ae_isfinite(au->ptr.p_double[i], _state))&&ae_fp_eq(al->ptr.p_double[i],au->ptr.p_double[i]) )
{
a1.ptr.pp_double[ccnt][n] = al->ptr.p_double[i];
ct.ptr.p_int[ccnt] = 0;
ccnt = ccnt+1;
}
else
{
if( ae_isfinite(al->ptr.p_double[i], _state) )
{
a1.ptr.pp_double[ccnt][n] = al->ptr.p_double[i];
ct.ptr.p_int[ccnt] = 1;
ccnt = ccnt+1;
}
if( ae_isfinite(au->ptr.p_double[i], _state) )
{
a1.ptr.pp_double[ccnt][n] = au->ptr.p_double[i];
ct.ptr.p_int[ccnt] = -1;
ccnt = ccnt+1;
}
}
}
minlpsetlc(state, &a1, &ct, ccnt, _state);
ae_frame_leave(_state);
return;
}
/*
* Straightforward SetLC2Sparse() call
*/
if( stype==2 )
{
if( m==0 )
{
minlpsetlc2(state, &sa, al, au, 0, _state);
ae_frame_leave(_state);
return;
}
sparsecreate(m, n, 0, &sa, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_neq(a->ptr.pp_double[i][j],(double)(0)) )
{
sparseset(&sa, i, j, a->ptr.pp_double[i][j], _state);
}
}
}
if( ae_fp_greater(hqrndnormal(rs, _state),(double)(0)) )
{
sparseconverttocrs(&sa, _state);
}
minlpsetlc2(state, &sa, al, au, m, _state);
ae_frame_leave(_state);
return;
}
/*
* A few rows are added with SetLC2Dense() call, the rest
* is processed with random mix of AddLC2Dense()/AddLC2()
*/
if( stype==3 )
{
if( m==0 )
{
minlpsetlc2(state, &sa, al, au, 0, _state);
ae_frame_leave(_state);
return;
}
minit = hqrnduniformi(rs, m, _state);
minlpsetlc2dense(state, a, al, au, minit, _state);
for(i=minit; i<=m-1; i++)
{
if( hqrnduniformi(rs, 2, _state)==0 )
{
/*
* Add as dense row
*/
ae_vector_set_length(&ai, n, _state);
for(j=0; j<=n-1; j++)
{
ai.ptr.p_double[j] = a->ptr.pp_double[i][j];
}
minlpaddlc2dense(state, &ai, al->ptr.p_double[i], au->ptr.p_double[i], _state);
}
else
{
/*
* Add as sparse row with shuffle and possible duplicates
*/
ae_vector_set_length(&ai, n, _state);
ae_vector_set_length(&idxi, n, _state);
nz = 0;
for(j=0; j<=n-1; j++)
{
if( ae_fp_neq(a->ptr.pp_double[i][j],(double)(0)) )
{
ai.ptr.p_double[nz] = a->ptr.pp_double[i][j];
idxi.ptr.p_int[nz] = j;
nz = nz+1;
}
}
rvectorresize(&ai, nz, _state);
ivectorresize(&idxi, nz, _state);
nadd = 0;
if( nz!=0 )
{
nadd = hqrnduniformi(rs, 2, _state)*hqrnduniformi(rs, 4, _state);
rvectorresize(&ai, nz+nadd, _state);
ivectorresize(&idxi, nz+nadd, _state);
for(j=0; j<=nadd-1; j++)
{
k = hqrnduniformi(rs, nz, _state);
v = hqrndnormal(rs, _state);
idxi.ptr.p_int[nz+j] = idxi.ptr.p_int[k];
ai.ptr.p_double[nz+j] = v;
ai.ptr.p_double[k] = ai.ptr.p_double[k]-v;
}
}
ndup = hqrnduniformi(rs, 2, _state)*hqrnduniformi(rs, 4, _state);
rvectorresize(&ai, nz+nadd+2*ndup, _state);
ivectorresize(&idxi, nz+nadd+2*ndup, _state);
for(j=0; j<=ndup-1; j++)
{
k = hqrnduniformi(rs, n, _state);
v = hqrndnormal(rs, _state);
idxi.ptr.p_int[nz+nadd+2*j+0] = k;
idxi.ptr.p_int[nz+nadd+2*j+1] = k;
ai.ptr.p_double[nz+nadd+2*j+0] = v;
ai.ptr.p_double[nz+nadd+2*j+1] = -v;
}
nzmod = nz+nadd+2*ndup;
for(j=0; j<=nzmod-1; j++)
{
k = j+hqrnduniformi(rs, nzmod-j, _state);
t = idxi.ptr.p_int[j];
idxi.ptr.p_int[j] = idxi.ptr.p_int[k];
idxi.ptr.p_int[k] = t;
v = ai.ptr.p_double[j];
ai.ptr.p_double[j] = ai.ptr.p_double[k];
ai.ptr.p_double[k] = v;
}
minlpaddlc2(state, &idxi, &ai, nzmod, al->ptr.p_double[i], au->ptr.p_double[i], _state);
}
}
ae_frame_leave(_state);
return;
}
ae_assert(ae_false, "MINLPTest: integrity check failed", _state);
ae_frame_leave(_state);
}
static ae_int_t testminnlcunit_maxsolvertype = 2;
static ae_int_t testminnlcunit_maxoptguardlevel = 1;
static void testminnlcunit_testbc(ae_bool* wereerrors, ae_state *_state);
static void testminnlcunit_testlc(ae_bool* wereerrors, ae_state *_state);
static void testminnlcunit_testnlc(ae_bool* wereerrors, ae_state *_state);
static void testminnlcunit_testother(ae_bool* wereerrors,
ae_state *_state);
static void testminnlcunit_testoptguard(ae_bool* wereerrors,
ae_state *_state);
static void testminnlcunit_testbugs(ae_bool* wereerrors, ae_state *_state);
static void testminnlcunit_testoptguardc1test0reportfortask0(ae_bool* err,
optguardnonc1test0report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state);
static void testminnlcunit_testoptguardc1test1reportfortask0(ae_bool* err,
optguardnonc1test1report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state);
static void testminnlcunit_testoptguardc1test0reportfortask1(ae_bool* err,
optguardnonc1test0report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_int_t goodidx,
ae_state *_state);
static void testminnlcunit_testoptguardc1test1reportfortask1(ae_bool* err,
optguardnonc1test1report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_int_t goodidx,
ae_state *_state);
ae_bool testminnlc(ae_bool silent, ae_state *_state)
{
ae_bool waserrors;
ae_bool bcerr;
ae_bool lcerr;
ae_bool nlcerr;
ae_bool othererr;
ae_bool optguarderr;
ae_bool bugs;
ae_bool result;
waserrors = ae_false;
bcerr = ae_false;
lcerr = ae_false;
nlcerr = ae_false;
othererr = ae_false;
optguarderr = ae_false;
bugs = ae_false;
testminnlcunit_testbugs(&bugs, _state);
testminnlcunit_testbc(&bcerr, _state);
testminnlcunit_testlc(&lcerr, _state);
testminnlcunit_testnlc(&nlcerr, _state);
testminnlcunit_testother(&othererr, _state);
testminnlcunit_testoptguard(&optguarderr, _state);
/*
* end
*/
waserrors = ((((bcerr||lcerr)||nlcerr)||othererr)||bugs)||optguarderr;
if( !silent )
{
printf("TESTING MINNLC OPTIMIZATION\n");
printf("GENERIC TESTS:\n");
printf("* box constrained ");
if( bcerr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* linearly constrained ");
if( lcerr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* nonlinearly constrained ");
if( nlcerr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* other properties ");
if( othererr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* optguard integrity monitor ");
if( optguarderr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* fixed bugs ");
if( bugs )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
return result;
}
/*************************************************************************
This function tests bound constrained quadratic programming algorithm.
On failure sets error flag.
*************************************************************************/
static void testminnlcunit_testbc(ae_bool* wereerrors, ae_state *_state)
{
ae_frame _frame_block;
minnlcstate state;
minnlcreport rep;
optguardreport ogrep;
ae_int_t n;
ae_int_t pass;
ae_int_t i;
ae_int_t j;
ae_int_t aulits;
double tolx;
double tolg;
ae_int_t scaletype;
double rho;
ae_int_t solvertype;
ae_matrix fulla;
ae_vector b;
ae_vector bndl;
ae_vector bndu;
ae_vector s;
ae_vector x0;
ae_vector x1;
double gnorm;
double g;
ae_int_t prectype;
hqrndstate rs;
ae_frame_make(_state, &_frame_block);
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&ogrep, 0, sizeof(ogrep));
memset(&fulla, 0, sizeof(fulla));
memset(&b, 0, sizeof(b));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(&s, 0, sizeof(s));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&rs, 0, sizeof(rs));
_minnlcstate_init(&state, _state, ae_true);
_minnlcreport_init(&rep, _state, ae_true);
_optguardreport_init(&ogrep, _state, ae_true);
ae_matrix_init(&fulla, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
for(solvertype=0; solvertype<=testminnlcunit_maxsolvertype; solvertype++)
{
/*
* Convex test:
* * N dimensions
* * random number (0..N) of random boundary constraints
* * positive-definite quadratic programming problem
* * initial point is random (maybe infeasible!)
* * random scale (unit or non-unit)
*/
aulits = 10;
rho = 200.0;
tolx = 0.0005;
tolg = 0.01;
for(n=1; n<=10; n++)
{
for(pass=1; pass<=10; pass++)
{
for(prectype=0; prectype<=2; prectype++)
{
/*
* Generate well-conditioned problem with unit scale
*/
spdmatrixrndcond(n, 1.0E2, &fulla, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
bndl.ptr.p_double[i] = _state->v_neginf;
bndu.ptr.p_double[i] = _state->v_posinf;
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
j = hqrnduniformi(&rs, 5, _state);
if( j==0 )
{
bndl.ptr.p_double[i] = (double)(0);
}
if( j==1 )
{
bndu.ptr.p_double[i] = (double)(0);
}
if( j==2 )
{
bndl.ptr.p_double[i] = hqrndnormal(&rs, _state);
bndu.ptr.p_double[i] = bndl.ptr.p_double[i];
}
if( j==3 )
{
bndl.ptr.p_double[i] = -0.1;
bndu.ptr.p_double[i] = 0.1;
}
}
/*
* Apply scaling to quadratic/linear term, so problem becomes
* well-conditioned in the scaled coordinates.
*/
scaletype = hqrnduniformi(&rs, 2, _state);
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
if( scaletype==0 )
{
s.ptr.p_double[i] = (double)(1);
}
else
{
s.ptr.p_double[i] = ae_exp(5*hqrndnormal(&rs, _state), _state);
}
}
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = x0.ptr.p_double[i]*s.ptr.p_double[i];
bndl.ptr.p_double[i] = bndl.ptr.p_double[i]*s.ptr.p_double[i];
bndu.ptr.p_double[i] = bndu.ptr.p_double[i]*s.ptr.p_double[i];
b.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
fulla.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]);
}
}
/*
* Solve problem
*/
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, rho, aulits, _state);
if( prectype==1 )
{
minnlcsetprecexactlowrank(&state, 0, _state);
}
if( prectype==2 )
{
minnlcsetprecexactrobust(&state, 0, _state);
}
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
if( scaletype!=0 )
{
minnlcsetscale(&state, &s, _state);
}
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minnlcoptguardsmoothness(&state, hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel+1, _state), _state);
}
minnlcsetbc(&state, &bndl, &bndu, _state);
minnlcsetcond(&state, 1.0E-7, 0, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.j.ptr.pp_double[0][i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:240");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:241");
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minnlcoptguardresults(&state, &ogrep, _state);
ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:245");
}
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Check constraint violation reports
*/
ae_set_error_flag(wereerrors, ae_fp_greater(rep.bcerr,tolx), __FILE__, __LINE__, "testminnlcunit.ap:253");
ae_set_error_flag(wereerrors, rep.bcidx>=n, __FILE__, __LINE__, "testminnlcunit.ap:254");
ae_set_error_flag(wereerrors, ae_fp_greater(rep.lcerr,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:255");
ae_set_error_flag(wereerrors, rep.lcidx>=0, __FILE__, __LINE__, "testminnlcunit.ap:256");
/*
* Check feasibility properties
*/
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(wereerrors, ae_isfinite(bndl.ptr.p_double[i], _state)&&ae_fp_less_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i]-tolx*s.ptr.p_double[i]), __FILE__, __LINE__, "testminnlcunit.ap:263");
ae_set_error_flag(wereerrors, ae_isfinite(bndu.ptr.p_double[i], _state)&&ae_fp_greater_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i]+tolx*s.ptr.p_double[i]), __FILE__, __LINE__, "testminnlcunit.ap:264");
}
/*
* Test - calculate scaled constrained gradient at solution,
* check its norm.
*/
gnorm = 0.0;
for(i=0; i<=n-1; i++)
{
g = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
g = g+fulla.ptr.pp_double[i][j]*x1.ptr.p_double[j];
}
g = s.ptr.p_double[i]*g;
if( (ae_isfinite(bndl.ptr.p_double[i], _state)&&ae_fp_less(ae_fabs(x1.ptr.p_double[i]-bndl.ptr.p_double[i], _state),tolx*s.ptr.p_double[i]))&&ae_fp_greater(g,(double)(0)) )
{
g = (double)(0);
}
if( (ae_isfinite(bndu.ptr.p_double[i], _state)&&ae_fp_less(ae_fabs(x1.ptr.p_double[i]-bndu.ptr.p_double[i], _state),tolx*s.ptr.p_double[i]))&&ae_fp_less(g,(double)(0)) )
{
g = (double)(0);
}
gnorm = gnorm+ae_sqr(g, _state);
}
gnorm = ae_sqrt(gnorm, _state);
ae_set_error_flag(wereerrors, ae_fp_greater(gnorm,tolg), __FILE__, __LINE__, "testminnlcunit.ap:286");
}
}
}
/*
* Non-convex test:
* * N dimensions, N>=2
* * box constraints, x[i] in [-1,+1]
* * A is symmetric indefinite with condition number 50.0
* * random B with normal entries
* * initial point is random, feasible
* * scale is always unit
*
* We check that constrained problem can be successfully solved.
* We do not check ability to detect unboundedness of unconstrained
* problem because there is such functionality in MinNLC.
*/
aulits = 50;
rho = 200.0;
tolx = 0.0005;
tolg = 0.01;
for(n=2; n<=10; n++)
{
for(pass=1; pass<=10; pass++)
{
for(prectype=0; prectype<=2; prectype++)
{
/*
* Generate problem
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
fulla.ptr.pp_double[i][j] = 0.0;
}
}
for(i=0; i<=n-1; i++)
{
fulla.ptr.pp_double[i][i] = -1-hqrnduniformr(&rs, _state);
}
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = 0.05*hqrndnormal(&rs, _state);
bndl.ptr.p_double[i] = (double)(-1);
bndu.ptr.p_double[i] = (double)(1);
x0.ptr.p_double[i] = 2*hqrnduniformr(&rs, _state)-1;
}
/*
* Solve problem:
* * without constraints we expect failure
* * with constraints algorithm must succeed
*/
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, rho, aulits, _state);
if( prectype==0 )
{
minnlcsetprecinexact(&state, _state);
}
if( prectype==1 )
{
minnlcsetprecexactlowrank(&state, 0, _state);
}
if( prectype==2 )
{
minnlcsetprecexactrobust(&state, 0, _state);
}
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minnlcoptguardsmoothness(&state, hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel+1, _state), _state);
}
minnlcsetbc(&state, &bndl, &bndu, _state);
minnlcsetcond(&state, 1.0E-7, 0, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.j.ptr.pp_double[0][i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:378");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:379");
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minnlcoptguardresults(&state, &ogrep, _state);
ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:383");
}
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Check feasibility properties
*/
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(wereerrors, ae_isfinite(bndl.ptr.p_double[i], _state)&&ae_fp_less_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i]-tolx), __FILE__, __LINE__, "testminnlcunit.ap:393");
ae_set_error_flag(wereerrors, ae_isfinite(bndu.ptr.p_double[i], _state)&&ae_fp_greater_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i]+tolx), __FILE__, __LINE__, "testminnlcunit.ap:394");
}
/*
* Test - calculate scaled constrained gradient at solution,
* check its norm.
*/
gnorm = 0.0;
for(i=0; i<=n-1; i++)
{
g = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
g = g+fulla.ptr.pp_double[i][j]*x1.ptr.p_double[j];
}
if( (ae_isfinite(bndl.ptr.p_double[i], _state)&&ae_fp_less(ae_fabs(x1.ptr.p_double[i]-bndl.ptr.p_double[i], _state),tolx))&&ae_fp_greater(g,(double)(0)) )
{
g = (double)(0);
}
if( (ae_isfinite(bndu.ptr.p_double[i], _state)&&ae_fp_less(ae_fabs(x1.ptr.p_double[i]-bndu.ptr.p_double[i], _state),tolx))&&ae_fp_less(g,(double)(0)) )
{
g = (double)(0);
}
gnorm = gnorm+ae_sqr(g, _state);
}
gnorm = ae_sqrt(gnorm, _state);
ae_set_error_flag(wereerrors, ae_fp_greater(gnorm,tolg), __FILE__, __LINE__, "testminnlcunit.ap:415");
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
This function tests linearly constrained quadratic programming algorithm.
Sets error flag on failure.
*************************************************************************/
static void testminnlcunit_testlc(ae_bool* wereerrors, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t k;
ae_int_t i;
ae_int_t j;
ae_int_t pass;
ae_matrix q;
ae_matrix fulla;
double v;
double vv;
ae_vector tmp;
ae_vector bl;
ae_vector bu;
ae_vector b;
ae_vector xs0;
ae_vector xstart;
ae_vector x;
ae_vector x0;
ae_vector x1;
ae_vector x2;
ae_vector xm;
ae_vector s;
ae_vector g;
ae_vector bndl;
ae_vector bndu;
ae_matrix a;
ae_matrix c;
ae_matrix ce;
ae_vector ct;
ae_vector nonnegative;
double tolx;
double tolg;
double tolf;
ae_int_t aulits;
double rho;
minnlcstate state;
minnlcreport rep;
optguardreport ogrep;
ae_int_t scaletype;
double f0;
double f1;
double tolconstr;
ae_int_t bscale;
ae_int_t akind;
ae_int_t ccnt;
ae_int_t shiftkind;
ae_int_t prectype;
ae_int_t solvertype;
hqrndstate rs;
snnlssolver nnls;
ae_frame_make(_state, &_frame_block);
memset(&q, 0, sizeof(q));
memset(&fulla, 0, sizeof(fulla));
memset(&tmp, 0, sizeof(tmp));
memset(&bl, 0, sizeof(bl));
memset(&bu, 0, sizeof(bu));
memset(&b, 0, sizeof(b));
memset(&xs0, 0, sizeof(xs0));
memset(&xstart, 0, sizeof(xstart));
memset(&x, 0, sizeof(x));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&x2, 0, sizeof(x2));
memset(&xm, 0, sizeof(xm));
memset(&s, 0, sizeof(s));
memset(&g, 0, sizeof(g));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(&a, 0, sizeof(a));
memset(&c, 0, sizeof(c));
memset(&ce, 0, sizeof(ce));
memset(&ct, 0, sizeof(ct));
memset(&nonnegative, 0, sizeof(nonnegative));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&ogrep, 0, sizeof(ogrep));
memset(&rs, 0, sizeof(rs));
memset(&nnls, 0, sizeof(nnls));
ae_matrix_init(&q, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&fulla, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xs0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xstart, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xm, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&g, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ce, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
ae_vector_init(&nonnegative, 0, DT_BOOL, _state, ae_true);
_minnlcstate_init(&state, _state, ae_true);
_minnlcreport_init(&rep, _state, ae_true);
_optguardreport_init(&ogrep, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
_snnlssolver_init(&nnls, _state, ae_true);
hqrndrandomize(&rs, _state);
for(solvertype=0; solvertype<=testminnlcunit_maxsolvertype; solvertype++)
{
/*
* First test:
* * K=0, __FILE__, __LINE__, "testminnlcunit.ap:593");
ae_set_error_flag(wereerrors, ae_fp_greater(rep.lcerr,tolx), __FILE__, __LINE__, "testminnlcunit.ap:594");
ae_set_error_flag(wereerrors, rep.lcidx>=n, __FILE__, __LINE__, "testminnlcunit.ap:595");
/*
* Compare with analytic solution
*/
f0 = (double)(0);
f1 = (double)(0);
for(i=0; i<=n-1; i++)
{
f0 = f0+b.ptr.p_double[i]*x0.ptr.p_double[i]+0.5*ae_sqr(x0.ptr.p_double[i]/s.ptr.p_double[i], _state);
f1 = f1+b.ptr.p_double[i]*x1.ptr.p_double[i]+0.5*ae_sqr(x1.ptr.p_double[i]/s.ptr.p_double[i], _state);
}
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(f1-f0, _state),tolf), __FILE__, __LINE__, "testminnlcunit.ap:607");
}
}
}
/*
* Inequality constrained problem:
* * N*N diagonal A
* * one inequality constraint q'*x>=0, where q is random unit vector
* * optimization problem has form 0.5*x'*A*x-(x1*A)*x,
* where x1 is some random vector
* * either:
* a) x1 is feasible => we must stop at x1
* b) x1 is infeasible => we must stop at the boundary q'*x=0 and
* projection of gradient onto q*x=0 must be zero
*
* NOTE: we make several passes because some specific kind of errors is rarely
* caught by this test, so we need several repetitions.
*/
rho = 200.0;
tolx = 0.0005;
tolg = 0.01;
aulits = 50;
for(n=2; n<=6; n++)
{
for(pass=0; pass<=4; pass++)
{
/*
* Generate problem: A, b, CMatrix, x0, XStart
*/
spdmatrixrndcond(n, 1.0E2, &fulla, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&xm, n, _state);
ae_vector_set_length(&xstart, n, _state);
ae_matrix_set_length(&c, 1, n+1, _state);
ae_vector_set_length(&ct, 1, _state);
for(i=0; i<=n-1; i++)
{
xm.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
xstart.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
do
{
v = (double)(0);
for(i=0; i<=n-1; i++)
{
c.ptr.pp_double[0][i] = 2*ae_randomreal(_state)-1;
v = v+ae_sqr(c.ptr.pp_double[0][i], _state);
}
v = ae_sqrt(v, _state);
}
while(ae_fp_eq(v,(double)(0)));
for(i=0; i<=n-1; i++)
{
c.ptr.pp_double[0][i] = c.ptr.pp_double[0][i]/v;
}
c.ptr.pp_double[0][n] = (double)(0);
ct.ptr.p_int[0] = 1;
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&fulla.ptr.pp_double[i][0], 1, &xm.ptr.p_double[0], 1, ae_v_len(0,n-1));
b.ptr.p_double[i] = -v;
}
/*
* Apply scaling to linear term and known solution,
* so problem becomes well-conditioned in the scaled coordinates.
*/
scaletype = hqrnduniformi(&rs, 2, _state);
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
if( scaletype==0 )
{
s.ptr.p_double[i] = (double)(1);
}
else
{
s.ptr.p_double[i] = ae_exp(hqrndnormal(&rs, _state), _state);
}
}
for(i=0; i<=n-1; i++)
{
xm.ptr.p_double[i] = xm.ptr.p_double[i]*s.ptr.p_double[i];
xstart.ptr.p_double[i] = xstart.ptr.p_double[i]*s.ptr.p_double[i];
b.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
fulla.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]);
}
}
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[0][j] = c.ptr.pp_double[0][j]/s.ptr.p_double[j];
}
/*
* Create optimizer, solve
*/
minnlccreate(n, &xstart, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, rho, aulits, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetlc(&state, &c, &ct, 1, _state);
minnlcsetscale(&state, &s, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minnlcoptguardsmoothness(&state, hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel+1, _state), _state);
}
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.j.ptr.pp_double[0][i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:729");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:730");
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minnlcoptguardresults(&state, &ogrep, _state);
ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:734");
}
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Check constraint violation reports
*/
ae_set_error_flag(wereerrors, ae_fp_greater(rep.bcerr,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:742");
ae_set_error_flag(wereerrors, rep.bcidx>=0, __FILE__, __LINE__, "testminnlcunit.ap:743");
ae_set_error_flag(wereerrors, ae_fp_greater(rep.lcerr,tolx), __FILE__, __LINE__, "testminnlcunit.ap:744");
ae_set_error_flag(wereerrors, rep.lcidx>=n, __FILE__, __LINE__, "testminnlcunit.ap:745");
/*
* Test solution
*/
ae_vector_set_length(&g, n, _state);
ae_v_move(&g.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1));
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&fulla.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1));
g.ptr.p_double[i] = g.ptr.p_double[i]+v;
}
v = ae_v_dotproduct(&x1.ptr.p_double[0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1));
ae_set_error_flag(wereerrors, ae_fp_less(v,-tolx), __FILE__, __LINE__, "testminnlcunit.ap:758");
if( ae_fp_less(v,tolx) )
{
/*
* Point at the boundary, project gradient into
* equality-constrained subspace.
*/
v = 0.0;
vv = 0.0;
for(i=0; i<=n-1; i++)
{
v = v+g.ptr.p_double[i]*c.ptr.pp_double[0][i];
vv = vv+c.ptr.pp_double[0][i]*c.ptr.pp_double[0][i];
}
v = v/vv;
ae_v_subd(&g.ptr.p_double[0], 1, &c.ptr.pp_double[0][0], 1, ae_v_len(0,n-1), v);
}
v = 0.0;
for(i=0; i<=n-1; i++)
{
v = v+ae_sqr(g.ptr.p_double[i]*s.ptr.p_double[i], _state);
}
ae_set_error_flag(wereerrors, ae_fp_greater(ae_sqrt(v, _state),tolg), __FILE__, __LINE__, "testminnlcunit.ap:778");
}
}
/*
* Equality-constrained test:
* * N*N SPD A
* * K=0, __FILE__, __LINE__, "testminnlcunit.ap:887");
ae_set_error_flag(wereerrors, ae_fp_greater(rep.lcerr,tolx), __FILE__, __LINE__, "testminnlcunit.ap:888");
ae_set_error_flag(wereerrors, rep.lcidx>=n, __FILE__, __LINE__, "testminnlcunit.ap:889");
/*
* Check feasibility properties and gradient projection
*/
for(i=0; i<=k-1; i++)
{
v = ae_v_dotproduct(&x1.ptr.p_double[0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(v-c.ptr.pp_double[i][n], _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:897");
}
ae_vector_set_length(&g, n, _state);
ae_v_move(&g.ptr.p_double[0], 1, &b.ptr.p_double[0], 1, ae_v_len(0,n-1));
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&fulla.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1));
g.ptr.p_double[i] = g.ptr.p_double[i]+v;
}
for(i=0; i<=k-1; i++)
{
v = ae_v_dotproduct(&g.ptr.p_double[0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
ae_v_subd(&g.ptr.p_double[0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v);
}
v = ae_v_dotproduct(&g.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,n-1));
ae_set_error_flag(wereerrors, ae_fp_greater(ae_sqrt(v, _state),tolg), __FILE__, __LINE__, "testminnlcunit.ap:912");
}
}
/*
* Boundary constraints vs linear ones:
* * N*N SPD A
* * optimization problem has form 0.5*x'*A*x-(xm*A)*x,
* where xm is some random vector from [-1,+1]
* * K=2*N constraints of the form ai<=x[i] or x[i]<=b[i],
* with ai in [-1.0,-0.1], bi in [+0.1,+1.0]
* * initial point xstart is from [-1,+2]
* * we solve two related QP problems:
* a) one with constraints posed as boundary ones
* b) another one with same constraints posed as general linear ones
* both problems must have same solution.
* Here we test that boundary constrained and linear inequality constrained
* solvers give same results.
*/
rho = 200.0;
tolx = 0.0005;
tolf = 0.00001;
aulits = 50;
for(n=1; n<=6; n++)
{
/*
* Generate problem: A, b, x0, XStart, C, CT
*/
spdmatrixrndcond(n, 1.0E2, &fulla, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&xm, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_matrix_set_length(&c, 2*n, n+1, _state);
ae_vector_set_length(&ct, 2*n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
for(i=0; i<=n-1; i++)
{
xm.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1;
bndl.ptr.p_double[i] = -(0.1+0.9*ae_randomreal(_state));
bndu.ptr.p_double[i] = 0.1+0.9*ae_randomreal(_state);
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[2*i+0][j] = (double)(0);
c.ptr.pp_double[2*i+1][j] = (double)(0);
}
c.ptr.pp_double[2*i+0][i] = (double)(1);
c.ptr.pp_double[2*i+0][n] = bndl.ptr.p_double[i];
ct.ptr.p_int[2*i+0] = 1;
c.ptr.pp_double[2*i+1][i] = (double)(1);
c.ptr.pp_double[2*i+1][n] = bndu.ptr.p_double[i];
ct.ptr.p_int[2*i+1] = -1;
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&fulla.ptr.pp_double[i][0], 1, &xm.ptr.p_double[0], 1, ae_v_len(0,n-1));
b.ptr.p_double[i] = -v;
}
/*
* Solve linear inequality constrained problem
*/
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, rho, aulits, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetlc(&state, &c, &ct, 2*n, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minnlcoptguardsmoothness(&state, hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel+1, _state), _state);
}
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.j.ptr.pp_double[0][i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:1012");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:1013");
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minnlcoptguardresults(&state, &ogrep, _state);
ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:1017");
}
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Solve boundary constrained problem
*/
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, rho, aulits, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetbc(&state, &bndl, &bndu, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.j.ptr.pp_double[0][i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x2, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x2, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:1059");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:1060");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Compare solutions
*/
f0 = (double)(0);
f1 = (double)(0);
for(i=0; i<=n-1; i++)
{
f0 = f0+b.ptr.p_double[i]*x1.ptr.p_double[i];
f1 = f1+b.ptr.p_double[i]*x2.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
f0 = f0+0.5*x1.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*x1.ptr.p_double[j];
f1 = f1+0.5*x2.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*x2.ptr.p_double[j];
}
}
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(f0-f1, _state),tolf), __FILE__, __LINE__, "testminnlcunit.ap:1079");
}
/*
* Boundary and linear equality constrained QP problem with excessive
* equality constraints:
* * N*N SPD A with moderate condtion number (up to 100)
* * boundary constraints 0<=x[i]<=1
* * K=2*N equality constraints Q*x = Q*x0, where Q is random matrix,
* x0 is some random vector from the feasible hypercube (0.1<=x0[i]<=0.9)
* * optimization problem has form 0.5*x'*A*x-b*x,
* where b is some random vector
* * because constraints are excessive, the main problem is to find
* feasible point; the only existing feasible point is solution,
* so we have to check only feasibility
*/
rho = 1000.0;
tolx = 0.0005;
aulits = 10;
for(n=1; n<=6; n++)
{
/*
* Generate problem: A, b, BndL, BndU, CMatrix, x0, xm, XStart
*/
k = 2*n;
spdmatrixrndcond(n, 1.0E2, &fulla, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xm, n, _state);
ae_vector_set_length(&xstart, n, _state);
ae_matrix_set_length(&c, k, n+1, _state);
ae_vector_set_length(&ct, k, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 0.1+0.8*ae_randomreal(_state);
xm.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
bndl.ptr.p_double[i] = 0.0;
bndu.ptr.p_double[i] = 1.0;
xstart.ptr.p_double[i] = (double)(ae_randominteger(2, _state));
}
for(i=0; i<=k-1; i++)
{
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1));
c.ptr.pp_double[i][n] = v;
ct.ptr.p_int[i] = 0;
}
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
/*
* Create optimizer, solve
*/
minnlccreate(n, &xstart, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, rho, aulits, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetcond(&state, 1.0E-7, 0, _state);
minnlcsetlc(&state, &c, &ct, k, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minnlcoptguardsmoothness(&state, hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel+1, _state), _state);
}
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.j.ptr.pp_double[0][i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:1176");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:1177");
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minnlcoptguardresults(&state, &ogrep, _state);
ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:1181");
}
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=k-1; i++)
{
v = ae_v_dotproduct(&x1.ptr.p_double[0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(v-c.ptr.pp_double[i][n], _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:1188");
}
}
/*
* Boundary and linear equality/inequality constrained QP problem with
* excessive constraints:
* * N*N SPD A with moderate condtion number (up to 100)
* * boundary constraints 0<=x[i]<=1
* * K=2*N equality/inequality constraints:
* * N/2 equality ones q'*x = q'*xm for random vector q
* * the rest are inequality ones, feasible at xm (xm is an inner point for these constraints)
* where xm is some random vector from the feasible hypercube (0.1<=xm[i]<=0.9)
* * optimization problem has form 0.5*x'*A*x-b*x,
* where b is some random vector
* * because constraints are excessive, the main problem is to find
* feasible point; we do not check that algorithm found a solution,
* we just check that it found feasible point.
*
* NOTE: this problem is difficult one (estimates of Lagrange multipliers converge
* slowly), so we use relaxed tolerances - 0.010 for AUL solver
*/
rho = 1000.0;
aulits = 30;
for(n=1; n<=6; n++)
{
/*
* Generate problem: A, b, BndL, BndU, CMatrix, xm, x1, XStart
*/
k = 2*n;
spdmatrixrndcond(n, 1.0E2, &fulla, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&xm, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_matrix_set_length(&c, k, n+1, _state);
ae_vector_set_length(&ct, k, _state);
for(i=0; i<=n-1; i++)
{
xm.ptr.p_double[i] = 0.1+0.8*ae_randomreal(_state);
bndl.ptr.p_double[i] = 0.0;
bndu.ptr.p_double[i] = 1.0;
x0.ptr.p_double[i] = (double)(ae_randominteger(2, _state));
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=n/2-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
v = v+c.ptr.pp_double[i][j]*xm.ptr.p_double[j];
}
c.ptr.pp_double[i][n] = v;
ct.ptr.p_int[i] = 0;
}
for(i=n/2; i<=k-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state)/ae_sqrt((double)(n), _state);
v = v+c.ptr.pp_double[i][j]*xm.ptr.p_double[j];
}
c.ptr.pp_double[i][n] = v;
ct.ptr.p_int[i] = 2*hqrnduniformi(&rs, 2, _state)-1;
if( ct.ptr.p_int[i]>0 )
{
c.ptr.pp_double[i][n] = c.ptr.pp_double[i][n]-0.1;
}
else
{
c.ptr.pp_double[i][n] = c.ptr.pp_double[i][n]+0.1;
}
}
/*
* Create optimizer, solve
*/
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, rho, aulits, _state);
tolx = 0.0050;
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
tolx = 0.0010;
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
tolx = 0.0010;
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetbc(&state, &bndl, &bndu, _state);
minnlcsetlc(&state, &c, &ct, k, _state);
minnlcsetcond(&state, 1.0E-7, 0, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minnlcoptguardsmoothness(&state, hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel+1, _state), _state);
}
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.j.ptr.pp_double[0][i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:1308");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:1309");
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minnlcoptguardresults(&state, &ogrep, _state);
ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:1313");
}
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=k-1; i++)
{
v = ae_v_dotproduct(&x1.ptr.p_double[0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
if( ct.ptr.p_int[i]==0 )
{
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(v-c.ptr.pp_double[i][n], _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:1321");
}
if( ct.ptr.p_int[i]>0 )
{
ae_set_error_flag(wereerrors, ae_fp_less(v,c.ptr.pp_double[i][n]-tolx), __FILE__, __LINE__, "testminnlcunit.ap:1323");
}
if( ct.ptr.p_int[i]<0 )
{
ae_set_error_flag(wereerrors, ae_fp_greater(v,c.ptr.pp_double[i][n]+tolx), __FILE__, __LINE__, "testminnlcunit.ap:1325");
}
}
}
/*
* Boundary and linear equality constrained QP problem,
* test checks that different starting points yield same final point:
* * random N from [1..6], random K from [1..N-1]
* * N*N SPD A with moderate condtion number (important!)
* * boundary constraints 0<=x[i]<=1
* * K=-2; bscale--)
{
/*
* Generate A, B and initial point
*/
ae_matrix_set_length(&a, n, n, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = ae_pow((double)(10), (double)(bscale), _state)*hqrndnormal(&rs, _state);
x.ptr.p_double[i] = 0.0;
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
}
if( akind==1 )
{
/*
* Dense well conditioned SPD
*/
spdmatrixrndcond(n, 50.0, &a, _state);
}
if( solvertype!=0 )
{
/*
* AUL performs poorly on such problems,
* but SLP works goo.
*/
if( akind==2 )
{
/*
* Dense well conditioned indefinite
*/
smatrixrndcond(n, 50.0, &a, _state);
}
if( akind==3 )
{
/*
* Low rank
*/
ae_vector_set_length(&tmp, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 0.0;
}
a.ptr.pp_double[i][i] = 1.0E-9;
}
for(k=1; k<=ae_minint(3, n-1, _state); k++)
{
for(i=0; i<=n-1; i++)
{
tmp.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
v = hqrndnormal(&rs, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = a.ptr.pp_double[i][j]+v*tmp.ptr.p_double[i]*tmp.ptr.p_double[j];
}
}
}
}
}
/*
* Generate constraints
*/
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
for(i=0; i<=n-1; i++)
{
bl.ptr.p_double[i] = -1.0;
bu.ptr.p_double[i] = 1.0;
}
ccnt = ae_minint(3, n-1, _state);
ae_matrix_set_length(&c, ccnt, n+1, _state);
ae_vector_set_length(&ct, ccnt, _state);
for(i=0; i<=ccnt-1; i++)
{
ct.ptr.p_int[i] = hqrnduniformi(&rs, 3, _state)-1;
c.ptr.pp_double[i][n] = 0.0;
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5;
}
c.ptr.pp_double[i][i] = c.ptr.pp_double[i][i]+4;
}
/*
* Create and optimize
*/
minnlccreate(n, &x, &state, _state);
minnlcsetbc(&state, &bl, &bu, _state);
minnlcsetlc(&state, &c, &ct, ccnt, _state);
minnlcsetcond(&state, 1.0E-7, 0, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, 1000.0, 10, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minnlcoptguardsmoothness(&state, hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel+1, _state), _state);
}
while(minnlciteration(&state, _state))
{
ae_assert(state.needfij, "Assertion failed", _state);
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+state.x.ptr.p_double[i]*b.ptr.p_double[i];
state.j.ptr.pp_double[0][i] = b.ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*v;
state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+v;
}
}
minnlcresults(&state, &xs0, &rep, _state);
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:1814");
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minnlcoptguardresults(&state, &ogrep, _state);
ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:1818");
}
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* 1. evaluate unconstrained gradient at solution
*
* 2. calculate constrained gradient (NNLS solver is used
* to evaluate gradient subject to active constraints).
* In order to do this we form CE matrix, matrix of active
* constraints (columns store constraint vectors). Then
* we try to approximate gradient vector by columns of CE,
* subject to non-negativity restriction placed on variables
* corresponding to inequality constraints.
*
* Residual from such regression is a constrained gradient vector.
*/
ae_vector_set_length(&g, n, _state);
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xs0.ptr.p_double[0], 1, ae_v_len(0,n-1));
g.ptr.p_double[i] = v+b.ptr.p_double[i];
}
ae_matrix_set_length(&ce, n, n+ccnt, _state);
ae_vector_set_length(&nonnegative, n+ccnt, _state);
k = 0;
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(wereerrors, ae_fp_less(xs0.ptr.p_double[i],bl.ptr.p_double[i]-tolconstr), __FILE__, __LINE__, "testminnlcunit.ap:1847");
ae_set_error_flag(wereerrors, ae_fp_greater(xs0.ptr.p_double[i],bu.ptr.p_double[i]+tolconstr), __FILE__, __LINE__, "testminnlcunit.ap:1848");
if( ae_fp_less_eq(xs0.ptr.p_double[i],bl.ptr.p_double[i]+tolconstr) )
{
for(j=0; j<=n-1; j++)
{
ce.ptr.pp_double[j][k] = 0.0;
}
ce.ptr.pp_double[i][k] = 1.0;
nonnegative.ptr.p_bool[k] = ae_true;
inc(&k, _state);
continue;
}
if( ae_fp_greater_eq(xs0.ptr.p_double[i],bu.ptr.p_double[i]-tolconstr) )
{
for(j=0; j<=n-1; j++)
{
ce.ptr.pp_double[j][k] = 0.0;
}
ce.ptr.pp_double[i][k] = -1.0;
nonnegative.ptr.p_bool[k] = ae_true;
inc(&k, _state);
continue;
}
}
for(i=0; i<=ccnt-1; i++)
{
v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &xs0.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = v-c.ptr.pp_double[i][n];
ae_set_error_flag(wereerrors, ct.ptr.p_int[i]==0&&ae_fp_greater(ae_fabs(v, _state),tolconstr), __FILE__, __LINE__, "testminnlcunit.ap:1872");
ae_set_error_flag(wereerrors, ct.ptr.p_int[i]>0&&ae_fp_less(v,-tolconstr), __FILE__, __LINE__, "testminnlcunit.ap:1873");
ae_set_error_flag(wereerrors, ct.ptr.p_int[i]<0&&ae_fp_greater(v,tolconstr), __FILE__, __LINE__, "testminnlcunit.ap:1874");
if( ct.ptr.p_int[i]==0 )
{
for(j=0; j<=n-1; j++)
{
ce.ptr.pp_double[j][k] = c.ptr.pp_double[i][j];
}
nonnegative.ptr.p_bool[k] = ae_false;
inc(&k, _state);
continue;
}
if( (ct.ptr.p_int[i]>0&&ae_fp_less_eq(v,tolconstr))||(ct.ptr.p_int[i]<0&&ae_fp_greater_eq(v,-tolconstr)) )
{
for(j=0; j<=n-1; j++)
{
ce.ptr.pp_double[j][k] = ae_sign((double)(ct.ptr.p_int[i]), _state)*c.ptr.pp_double[i][j];
}
nonnegative.ptr.p_bool[k] = ae_true;
inc(&k, _state);
continue;
}
}
snnlsinit(0, 0, 0, &nnls, _state);
snnlssetproblem(&nnls, &ce, &g, 0, k, n, _state);
for(i=0; i<=k-1; i++)
{
if( !nonnegative.ptr.p_bool[i] )
{
snnlsdropnnc(&nnls, i, _state);
}
}
snnlssolve(&nnls, &tmp, _state);
for(i=0; i<=k-1; i++)
{
for(j=0; j<=n-1; j++)
{
g.ptr.p_double[j] = g.ptr.p_double[j]-tmp.ptr.p_double[i]*ce.ptr.pp_double[j][i];
}
}
vv = ae_v_dotproduct(&g.ptr.p_double[0], 1, &g.ptr.p_double[0], 1, ae_v_len(0,n-1));
vv = ae_sqrt(vv, _state);
ae_set_error_flag(wereerrors, ae_fp_greater(vv,1.0E-3), __FILE__, __LINE__, "testminnlcunit.ap:1903");
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
This function tests nonlinearly constrained quadratic programming algorithm.
Sets error flag on failure.
*************************************************************************/
static void testminnlcunit_testnlc(ae_bool* wereerrors, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t n2;
double tolx;
double tolg;
ae_int_t aulits;
double rho;
minnlcstate state;
minnlcreport rep;
optguardreport ogrep;
ae_int_t scaletype;
ae_vector x0;
ae_vector x1;
ae_vector b;
ae_vector bndl;
ae_vector bndu;
ae_vector s;
ae_vector g;
ae_vector rnlc;
ae_vector ckind;
ae_matrix fulla;
ae_matrix c;
ae_vector ct;
ae_int_t cntbc;
ae_int_t cntlc;
ae_int_t cntnlec;
ae_int_t cntnlic;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t pass;
ae_int_t klc;
ae_int_t knlec;
ae_int_t knlic;
double v;
double vv;
double vx;
double vy;
double gnorm2;
double rawgnorm2;
hqrndstate rs;
ae_int_t prectype;
ae_int_t solvertype;
ae_frame_make(_state, &_frame_block);
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&ogrep, 0, sizeof(ogrep));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&b, 0, sizeof(b));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(&s, 0, sizeof(s));
memset(&g, 0, sizeof(g));
memset(&rnlc, 0, sizeof(rnlc));
memset(&ckind, 0, sizeof(ckind));
memset(&fulla, 0, sizeof(fulla));
memset(&c, 0, sizeof(c));
memset(&ct, 0, sizeof(ct));
memset(&rs, 0, sizeof(rs));
_minnlcstate_init(&state, _state, ae_true);
_minnlcreport_init(&rep, _state, ae_true);
_optguardreport_init(&ogrep, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&g, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rnlc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ckind, 0, DT_INT, _state, ae_true);
ae_matrix_init(&fulla, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
for(solvertype=0; solvertype<=testminnlcunit_maxsolvertype; solvertype++)
{
/*
* Basic test:
* * 2-dimensional problem
* * target function F(x0,x1) = (x0-1)^2 + (x1-1)^2
* * one nonlinear constraint Z(x0,x1) = x0^2+x1^2-1,
* which is tried as equality and inequality one
*/
rho = 200.0;
tolx = 0.0005;
aulits = 50;
n = 2;
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, rho, aulits, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetcond(&state, 1.0E-7, 0, _state);
minnlcsetnlc(&state, 0, 1, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = ae_sqr(state.x.ptr.p_double[0]-1, _state)+ae_sqr(state.x.ptr.p_double[1]-1, _state);
state.j.ptr.pp_double[0][0] = 2*(state.x.ptr.p_double[0]-1);
state.j.ptr.pp_double[0][1] = 2*(state.x.ptr.p_double[1]-1);
state.fi.ptr.p_double[1] = ae_sqr(state.x.ptr.p_double[0], _state)+ae_sqr(state.x.ptr.p_double[1], _state)-1;
state.j.ptr.pp_double[1][0] = 2*state.x.ptr.p_double[0];
state.j.ptr.pp_double[1][1] = 2*state.x.ptr.p_double[1];
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:1989");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:1990");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[0]-ae_sqrt((double)(2), _state)/2, _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:1993");
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[1]-ae_sqrt((double)(2), _state)/2, _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:1994");
minnlcsetnlc(&state, 1, 0, _state);
minnlcrestartfrom(&state, &x0, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minnlcoptguardsmoothness(&state, hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel+1, _state), _state);
}
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = ae_sqr(state.x.ptr.p_double[0]-1, _state)+ae_sqr(state.x.ptr.p_double[1]-1, _state);
state.j.ptr.pp_double[0][0] = 2*(state.x.ptr.p_double[0]-1);
state.j.ptr.pp_double[0][1] = 2*(state.x.ptr.p_double[1]-1);
state.fi.ptr.p_double[1] = ae_sqr(state.x.ptr.p_double[0], _state)+ae_sqr(state.x.ptr.p_double[1], _state)-1;
state.j.ptr.pp_double[1][0] = 2*state.x.ptr.p_double[0];
state.j.ptr.pp_double[1][1] = 2*state.x.ptr.p_double[1];
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:2014");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:2015");
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minnlcoptguardresults(&state, &ogrep, _state);
ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:2019");
}
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[0]-ae_sqrt((double)(2), _state)/2, _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:2023");
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[1]-ae_sqrt((double)(2), _state)/2, _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:2024");
/*
* This test checks correctness of scaling being applied to nonlinear
* constraints. We solve bound constrained scaled problem and check
* that solution is correct.
*/
aulits = 50;
rho = 200.0;
tolx = 0.0005;
tolg = 0.01;
for(n=1; n<=10; n++)
{
for(pass=1; pass<=10; pass++)
{
/*
* Generate well-conditioned problem with unit scale
*/
spdmatrixrndcond(n, 1.0E2, &fulla, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
cntnlec = hqrnduniformi(&rs, n, _state);
cntnlic = n-cntnlec;
for(i=0; i<=cntnlec-1; i++)
{
bndl.ptr.p_double[i] = hqrndnormal(&rs, _state);
bndu.ptr.p_double[i] = bndl.ptr.p_double[i];
}
for(i=cntnlec; i<=n-1; i++)
{
bndl.ptr.p_double[i] = hqrndnormal(&rs, _state);
bndu.ptr.p_double[i] = bndl.ptr.p_double[i]+0.5;
}
/*
* Apply scaling to quadratic/linear term, so problem becomes
* well-conditioned in the scaled coordinates.
*/
scaletype = hqrnduniformi(&rs, 2, _state);
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
if( scaletype==0 )
{
s.ptr.p_double[i] = (double)(1);
}
else
{
s.ptr.p_double[i] = ae_exp(5*hqrndnormal(&rs, _state), _state);
}
}
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = x0.ptr.p_double[i]*s.ptr.p_double[i];
bndl.ptr.p_double[i] = bndl.ptr.p_double[i]*s.ptr.p_double[i];
bndu.ptr.p_double[i] = bndu.ptr.p_double[i]*s.ptr.p_double[i];
b.ptr.p_double[i] = b.ptr.p_double[i]/s.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
fulla.ptr.pp_double[i][j] = fulla.ptr.pp_double[i][j]/(s.ptr.p_double[i]*s.ptr.p_double[j]);
}
}
/*
* Solve problem with boundary constraints posed as nonlinear ones
*/
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, rho, aulits, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetscale(&state, &s, _state);
minnlcsetnlc(&state, cntnlec, 2*cntnlic, _state);
minnlcsetcond(&state, 1.0E-7, 0, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minnlcoptguardsmoothness(&state, hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel+1, _state), _state);
}
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
for(i=0; i<=cntnlec+2*cntnlic; i++)
{
state.fi.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
state.j.ptr.pp_double[i][j] = (double)(0);
}
}
/*
* Function itself
*/
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.j.ptr.pp_double[0][i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
/*
* Equality constraints
*/
for(i=0; i<=cntnlec-1; i++)
{
state.fi.ptr.p_double[1+i] = (state.x.ptr.p_double[i]-bndl.ptr.p_double[i])/s.ptr.p_double[i];
state.j.ptr.pp_double[1+i][i] = 1/s.ptr.p_double[i];
}
/*
* Inequality constraints
*/
for(i=0; i<=cntnlic-1; i++)
{
k = cntnlec+i;
state.fi.ptr.p_double[1+cntnlec+2*i+0] = (bndl.ptr.p_double[k]-state.x.ptr.p_double[k])/s.ptr.p_double[k];
state.j.ptr.pp_double[1+cntnlec+2*i+0][k] = -1/s.ptr.p_double[k];
state.fi.ptr.p_double[1+cntnlec+2*i+1] = (state.x.ptr.p_double[k]-bndu.ptr.p_double[k])/s.ptr.p_double[k];
state.j.ptr.pp_double[1+cntnlec+2*i+1][k] = 1/s.ptr.p_double[k];
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:2158");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:2159");
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minnlcoptguardresults(&state, &ogrep, _state);
ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:2163");
}
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Check feasibility properties
*/
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(wereerrors, ae_isfinite(bndl.ptr.p_double[i], _state)&&ae_fp_less_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i]-tolx*s.ptr.p_double[i]), __FILE__, __LINE__, "testminnlcunit.ap:2173");
ae_set_error_flag(wereerrors, ae_isfinite(bndu.ptr.p_double[i], _state)&&ae_fp_greater_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i]+tolx*s.ptr.p_double[i]), __FILE__, __LINE__, "testminnlcunit.ap:2174");
}
/*
* Test - calculate scaled constrained gradient at solution,
* check its norm.
*/
ae_vector_set_length(&g, n, _state);
gnorm2 = 0.0;
for(i=0; i<=n-1; i++)
{
g.ptr.p_double[i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
g.ptr.p_double[i] = g.ptr.p_double[i]+fulla.ptr.pp_double[i][j]*x1.ptr.p_double[j];
}
g.ptr.p_double[i] = s.ptr.p_double[i]*g.ptr.p_double[i];
if( (ae_isfinite(bndl.ptr.p_double[i], _state)&&ae_fp_less(ae_fabs(x1.ptr.p_double[i]-bndl.ptr.p_double[i], _state),tolx*s.ptr.p_double[i]))&&ae_fp_greater(g.ptr.p_double[i],(double)(0)) )
{
g.ptr.p_double[i] = (double)(0);
}
if( (ae_isfinite(bndu.ptr.p_double[i], _state)&&ae_fp_less(ae_fabs(x1.ptr.p_double[i]-bndu.ptr.p_double[i], _state),tolx*s.ptr.p_double[i]))&&ae_fp_less(g.ptr.p_double[i],(double)(0)) )
{
g.ptr.p_double[i] = (double)(0);
}
gnorm2 = gnorm2+ae_sqr(g.ptr.p_double[i], _state);
}
ae_set_error_flag(wereerrors, ae_fp_greater(gnorm2,ae_sqr(tolg, _state)), __FILE__, __LINE__, "testminnlcunit.ap:2196");
}
}
/*
* Complex problem with mix of boundary, linear and nonlinear constraints:
* * quadratic target function f(x) = 0.5*x'*A*x + b'*x
* * unit scaling is used
* * problem size N is even
* * all variables are divided into pairs: x[0] and x[1], x[2] and x[3], ...
* * constraints are set for pairs of variables, i.e. each constraint involves
* only pair of adjacent variables (x0/x1, x2/x3, x4/x5 and so on), and each
* pair of variables has at most one constraint which binds them
* * for variables u and v following kinds of constraints can be randomly set:
* * CKind=0 no constraint
* * CKind=1 boundary equality constraint: u=a, v=b
* * CKind=2 boundary inequality constraint: a0<=u<=b0, a1<=v<=b1
* * CKind=3 linear equality constraint: a*u+b*v = c
* * CKind=4 linear inequality constraint: a*u+b*v <= c
* * CKind=5 nonlinear equality constraint: u^2+v^2 = 1
* * CKind=6 nonlinear inequality constraint: u^2+v^2 <= 1
* * it is relatively easy to calculated projected gradient for such problem
*/
aulits = 50;
rho = 200.0;
tolx = 0.0005;
tolg = 0.005;
n = 20;
n2 = n/2;
for(pass=1; pass<=5; pass++)
{
for(prectype=1; prectype<=2; prectype++)
{
/*
* Generate well-conditioned problem with unit scale
*/
spdmatrixrndcond(n, 1.0E2, &fulla, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_matrix_set_length(&c, n, n+1, _state);
ae_vector_set_length(&ct, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&ckind, n2, _state);
ae_vector_set_length(&rnlc, n2, _state);
cntbc = 0;
cntlc = 0;
cntnlec = 0;
cntnlic = 0;
for(i=0; i<=n-1; i++)
{
bndl.ptr.p_double[i] = _state->v_neginf;
bndu.ptr.p_double[i] = _state->v_posinf;
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
b.ptr.p_double[i] = 10*hqrndnormal(&rs, _state);
}
for(i=0; i<=n2-1; i++)
{
ckind.ptr.p_int[i] = hqrnduniformi(&rs, 7, _state);
rnlc.ptr.p_double[i] = (double)(0);
if( ckind.ptr.p_int[i]==0 )
{
/*
* Unconstrained
*/
continue;
}
if( ckind.ptr.p_int[i]==1 )
{
/*
* Bound equality constrained
*/
bndl.ptr.p_double[2*i+0] = hqrnduniformr(&rs, _state)-0.5;
bndu.ptr.p_double[2*i+0] = bndl.ptr.p_double[2*i+0];
bndl.ptr.p_double[2*i+1] = hqrnduniformr(&rs, _state)-0.5;
bndu.ptr.p_double[2*i+1] = bndl.ptr.p_double[2*i+1];
inc(&cntbc, _state);
continue;
}
if( ckind.ptr.p_int[i]==2 )
{
/*
* Bound inequality constrained
*/
bndl.ptr.p_double[2*i+0] = hqrnduniformr(&rs, _state)-0.5;
bndu.ptr.p_double[2*i+0] = bndl.ptr.p_double[2*i+0]+0.5;
bndl.ptr.p_double[2*i+1] = hqrnduniformr(&rs, _state)-0.5;
bndu.ptr.p_double[2*i+1] = bndl.ptr.p_double[2*i+1]+0.5;
inc(&cntbc, _state);
continue;
}
if( ckind.ptr.p_int[i]==3 )
{
/*
* Linear equality constrained
*/
for(j=0; j<=n; j++)
{
c.ptr.pp_double[cntlc][j] = 0.0;
}
vx = hqrnduniformr(&rs, _state)-0.5;
vy = hqrnduniformr(&rs, _state)-0.5;
c.ptr.pp_double[cntlc][2*i+0] = vx;
c.ptr.pp_double[cntlc][2*i+1] = vy;
c.ptr.pp_double[cntlc][n] = hqrnduniformr(&rs, _state)-0.5;
ct.ptr.p_int[cntlc] = 0;
inc(&cntlc, _state);
continue;
}
if( ckind.ptr.p_int[i]==4 )
{
/*
* Linear inequality constrained
*/
for(j=0; j<=n; j++)
{
c.ptr.pp_double[cntlc][j] = 0.0;
}
vx = hqrnduniformr(&rs, _state)-0.5;
vy = hqrnduniformr(&rs, _state)-0.5;
c.ptr.pp_double[cntlc][2*i+0] = vx;
c.ptr.pp_double[cntlc][2*i+1] = vy;
c.ptr.pp_double[cntlc][n] = hqrnduniformr(&rs, _state)-0.5;
ct.ptr.p_int[cntlc] = -1;
inc(&cntlc, _state);
continue;
}
if( ckind.ptr.p_int[i]==5 )
{
/*
* Nonlinear equality constrained
*/
rnlc.ptr.p_double[i] = 0.5+hqrnduniformr(&rs, _state);
inc(&cntnlec, _state);
continue;
}
if( ckind.ptr.p_int[i]==6 )
{
/*
* Nonlinear inequality constrained
*/
rnlc.ptr.p_double[i] = 0.5+hqrnduniformr(&rs, _state);
inc(&cntnlic, _state);
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
/*
* Solve problem
*/
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, rho, aulits, _state);
minnlcsetcond(&state, 1.0E-7, 0, _state);
if( prectype==0 )
{
minnlcsetprecinexact(&state, _state);
}
if( prectype==1 )
{
minnlcsetprecexactlowrank(&state, 0, _state);
}
if( prectype==2 )
{
minnlcsetprecexactrobust(&state, 0, _state);
}
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
minnlcsetcond(&state, 1.0E-6, 0, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
minnlcsetcond(&state, 1.0E-6, 0, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetbc(&state, &bndl, &bndu, _state);
minnlcsetlc(&state, &c, &ct, cntlc, _state);
minnlcsetnlc(&state, cntnlec, cntnlic, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minnlcoptguardsmoothness(&state, hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel+1, _state), _state);
}
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
/*
* Evaluate target function
*/
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.j.ptr.pp_double[0][i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
/*
* Evaluate constraint functions
*/
knlec = 1;
knlic = 1+cntnlec;
for(i=0; i<=n2-1; i++)
{
if( ckind.ptr.p_int[i]==5 )
{
state.fi.ptr.p_double[knlec] = (double)(0);
for(j=0; j<=n-1; j++)
{
state.j.ptr.pp_double[knlec][j] = 0.0;
}
state.fi.ptr.p_double[knlec] = ae_sqr(state.x.ptr.p_double[2*i+0], _state)+ae_sqr(state.x.ptr.p_double[2*i+1], _state)-rnlc.ptr.p_double[i];
state.j.ptr.pp_double[knlec][2*i+0] = 2*state.x.ptr.p_double[2*i+0];
state.j.ptr.pp_double[knlec][2*i+1] = 2*state.x.ptr.p_double[2*i+1];
inc(&knlec, _state);
continue;
}
if( ckind.ptr.p_int[i]==6 )
{
state.fi.ptr.p_double[knlic] = (double)(0);
for(j=0; j<=n-1; j++)
{
state.j.ptr.pp_double[knlic][j] = 0.0;
}
state.fi.ptr.p_double[knlic] = ae_sqr(state.x.ptr.p_double[2*i+0], _state)+ae_sqr(state.x.ptr.p_double[2*i+1], _state)-rnlc.ptr.p_double[i];
state.j.ptr.pp_double[knlic][2*i+0] = 2*state.x.ptr.p_double[2*i+0];
state.j.ptr.pp_double[knlic][2*i+1] = 2*state.x.ptr.p_double[2*i+1];
inc(&knlic, _state);
continue;
}
}
ae_assert(knlec==1+cntnlec, "Assertion failed", _state);
ae_assert(knlic==1+cntnlec+cntnlic, "Assertion failed", _state);
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:2427");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:2428");
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
minnlcoptguardresults(&state, &ogrep, _state);
ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:2432");
}
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Check feasibility properties
*/
klc = 0;
for(i=0; i<=n2-1; i++)
{
if( ckind.ptr.p_int[i]==0 )
{
/*
* Unconstrained
*/
continue;
}
if( ckind.ptr.p_int[i]==1 )
{
/*
* Bound equality constrained
*/
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[2*i+0]-bndl.ptr.p_double[2*i+0], _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:2455");
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[2*i+1]-bndl.ptr.p_double[2*i+1], _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:2456");
continue;
}
if( ckind.ptr.p_int[i]==2 )
{
/*
* Bound inequality constrained
*/
ae_set_error_flag(wereerrors, ae_fp_less(x1.ptr.p_double[2*i+0],bndl.ptr.p_double[2*i+0]-tolx), __FILE__, __LINE__, "testminnlcunit.ap:2464");
ae_set_error_flag(wereerrors, ae_fp_greater(x1.ptr.p_double[2*i+0],bndu.ptr.p_double[2*i+0]+tolx), __FILE__, __LINE__, "testminnlcunit.ap:2465");
ae_set_error_flag(wereerrors, ae_fp_less(x1.ptr.p_double[2*i+1],bndl.ptr.p_double[2*i+1]-tolx), __FILE__, __LINE__, "testminnlcunit.ap:2466");
ae_set_error_flag(wereerrors, ae_fp_greater(x1.ptr.p_double[2*i+1],bndu.ptr.p_double[2*i+1]+tolx), __FILE__, __LINE__, "testminnlcunit.ap:2467");
continue;
}
if( ckind.ptr.p_int[i]==3 )
{
/*
* Linear equality constrained
*/
v = x1.ptr.p_double[2*i+0]*c.ptr.pp_double[klc][2*i+0]+x1.ptr.p_double[2*i+1]*c.ptr.pp_double[klc][2*i+1]-c.ptr.pp_double[klc][n];
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(v, _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:2476");
inc(&klc, _state);
continue;
}
if( ckind.ptr.p_int[i]==4 )
{
/*
* Linear inequality constrained
*/
v = x1.ptr.p_double[2*i+0]*c.ptr.pp_double[klc][2*i+0]+x1.ptr.p_double[2*i+1]*c.ptr.pp_double[klc][2*i+1]-c.ptr.pp_double[klc][n];
ae_set_error_flag(wereerrors, ae_fp_greater(v,tolx), __FILE__, __LINE__, "testminnlcunit.ap:2486");
inc(&klc, _state);
continue;
}
if( ckind.ptr.p_int[i]==5 )
{
/*
* Nonlinear equality constrained
*/
v = ae_sqr(x1.ptr.p_double[2*i+0], _state)+ae_sqr(x1.ptr.p_double[2*i+1], _state)-rnlc.ptr.p_double[i];
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(v, _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:2496");
continue;
}
if( ckind.ptr.p_int[i]==6 )
{
/*
* Nonlinear inequality constrained
*/
v = ae_sqr(x1.ptr.p_double[2*i+0], _state)+ae_sqr(x1.ptr.p_double[2*i+1], _state)-rnlc.ptr.p_double[i];
ae_set_error_flag(wereerrors, ae_fp_greater(v,tolx), __FILE__, __LINE__, "testminnlcunit.ap:2505");
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
/*
* Test - calculate scaled constrained gradient at solution,
* check its norm.
*/
gnorm2 = 0.0;
rawgnorm2 = (double)(0);
ae_vector_set_length(&g, n, _state);
for(i=0; i<=n-1; i++)
{
v = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
v = v+fulla.ptr.pp_double[i][j]*x1.ptr.p_double[j];
}
g.ptr.p_double[i] = v;
rawgnorm2 = rawgnorm2+v*v;
}
klc = 0;
for(i=0; i<=n2-1; i++)
{
if( ckind.ptr.p_int[i]==0 )
{
/*
* Unconstrained
*/
gnorm2 = gnorm2+ae_sqr(g.ptr.p_double[2*i+0], _state)+ae_sqr(g.ptr.p_double[2*i+1], _state);
ae_set_error_flag(wereerrors, ae_fp_greater(gnorm2,ae_sqr(tolg, _state)*ae_maxreal(rawgnorm2, 1.0, _state)), __FILE__, __LINE__, "testminnlcunit.ap:2535");
continue;
}
if( ckind.ptr.p_int[i]==1 )
{
/*
* Bound equality constrained, unconditionally set gradient to zero
*/
g.ptr.p_double[2*i+0] = 0.0;
g.ptr.p_double[2*i+1] = 0.0;
gnorm2 = gnorm2+ae_sqr(g.ptr.p_double[2*i+0], _state)+ae_sqr(g.ptr.p_double[2*i+1], _state);
ae_set_error_flag(wereerrors, ae_fp_greater(gnorm2,ae_sqr(tolg, _state)*ae_maxreal(rawgnorm2, 1.0, _state)), __FILE__, __LINE__, "testminnlcunit.ap:2546");
continue;
}
if( ckind.ptr.p_int[i]==2 )
{
/*
* Bound inequality constrained, conditionally set gradient to zero
* (when constraint is active)
*/
if( ae_fp_less(x1.ptr.p_double[2*i+0],bndl.ptr.p_double[2*i+0]+tolx)||ae_fp_greater(x1.ptr.p_double[2*i+0],bndu.ptr.p_double[2*i+0]-tolx) )
{
g.ptr.p_double[2*i+0] = 0.0;
}
if( ae_fp_less(x1.ptr.p_double[2*i+1],bndl.ptr.p_double[2*i+1]+tolx)||ae_fp_greater(x1.ptr.p_double[2*i+1],bndu.ptr.p_double[2*i+1]-tolx) )
{
g.ptr.p_double[2*i+1] = 0.0;
}
gnorm2 = gnorm2+ae_sqr(g.ptr.p_double[2*i+0], _state)+ae_sqr(g.ptr.p_double[2*i+1], _state);
ae_set_error_flag(wereerrors, ae_fp_greater(gnorm2,ae_sqr(tolg, _state)*ae_maxreal(rawgnorm2, 1.0, _state)), __FILE__, __LINE__, "testminnlcunit.ap:2560");
continue;
}
if( ckind.ptr.p_int[i]==3 )
{
/*
* Linear equality constrained, unconditionally project gradient into
* equality constrained subspace
*/
v = g.ptr.p_double[2*i+0]*c.ptr.pp_double[klc][2*i+0]+g.ptr.p_double[2*i+1]*c.ptr.pp_double[klc][2*i+1];
vv = ae_sqr(c.ptr.pp_double[klc][2*i+0], _state)+ae_sqr(c.ptr.pp_double[klc][2*i+1], _state);
g.ptr.p_double[2*i+0] = g.ptr.p_double[2*i+0]-c.ptr.pp_double[klc][2*i+0]*(v/vv);
g.ptr.p_double[2*i+1] = g.ptr.p_double[2*i+1]-c.ptr.pp_double[klc][2*i+1]*(v/vv);
inc(&klc, _state);
gnorm2 = gnorm2+ae_sqr(g.ptr.p_double[2*i+0], _state)+ae_sqr(g.ptr.p_double[2*i+1], _state);
ae_set_error_flag(wereerrors, ae_fp_greater(gnorm2,ae_sqr(tolg, _state)*ae_maxreal(rawgnorm2, 1.0, _state)), __FILE__, __LINE__, "testminnlcunit.ap:2575");
continue;
}
if( ckind.ptr.p_int[i]==4 )
{
/*
* Linear inequality constrained, conditionally project gradient
* (when constraint is active)
*/
v = x1.ptr.p_double[2*i+0]*c.ptr.pp_double[klc][2*i+0]+x1.ptr.p_double[2*i+1]*c.ptr.pp_double[klc][2*i+1]-c.ptr.pp_double[klc][n];
if( ae_fp_greater(v,-tolx) )
{
v = g.ptr.p_double[2*i+0]*c.ptr.pp_double[klc][2*i+0]+g.ptr.p_double[2*i+1]*c.ptr.pp_double[klc][2*i+1];
vv = ae_sqr(c.ptr.pp_double[klc][2*i+0], _state)+ae_sqr(c.ptr.pp_double[klc][2*i+1], _state);
g.ptr.p_double[2*i+0] = g.ptr.p_double[2*i+0]-c.ptr.pp_double[klc][2*i+0]*(v/vv);
g.ptr.p_double[2*i+1] = g.ptr.p_double[2*i+1]-c.ptr.pp_double[klc][2*i+1]*(v/vv);
}
inc(&klc, _state);
gnorm2 = gnorm2+ae_sqr(g.ptr.p_double[2*i+0], _state)+ae_sqr(g.ptr.p_double[2*i+1], _state);
ae_set_error_flag(wereerrors, ae_fp_greater(gnorm2,ae_sqr(tolg, _state)*ae_maxreal(rawgnorm2, 1.0, _state)), __FILE__, __LINE__, "testminnlcunit.ap:2594");
continue;
}
if( ckind.ptr.p_int[i]==5 )
{
/*
* Nonlinear equality constrained, unconditionally project gradient
*
* NOTE: here we rely on the fact that corresponding components of X
* sum to one.
*/
v = coalesce(ae_sqrt(ae_sqr(x1.ptr.p_double[2*i+0], _state)+ae_sqr(x1.ptr.p_double[2*i+1], _state), _state), 1.0, _state);
vx = x1.ptr.p_double[2*i+0]/v;
vy = x1.ptr.p_double[2*i+1]/v;
v = g.ptr.p_double[2*i+0]*vx+g.ptr.p_double[2*i+1]*vy;
g.ptr.p_double[2*i+0] = g.ptr.p_double[2*i+0]-vx*v;
g.ptr.p_double[2*i+1] = g.ptr.p_double[2*i+1]-vy*v;
gnorm2 = gnorm2+ae_sqr(g.ptr.p_double[2*i+0], _state)+ae_sqr(g.ptr.p_double[2*i+1], _state);
ae_set_error_flag(wereerrors, ae_fp_greater(gnorm2,ae_sqr(tolg, _state)*ae_maxreal(rawgnorm2, 1.0, _state)), __FILE__, __LINE__, "testminnlcunit.ap:2612");
continue;
}
if( ckind.ptr.p_int[i]==6 )
{
/*
* Nonlinear inequality constrained, conditionally project gradient
* (when constraint is active)
*
* NOTE: here we rely on the fact that corresponding components of X
* sum to one.
*/
v = ae_sqr(x1.ptr.p_double[2*i+0], _state)+ae_sqr(x1.ptr.p_double[2*i+1], _state)-rnlc.ptr.p_double[i];
if( ae_fp_greater(v,-tolx) )
{
v = coalesce(ae_sqrt(ae_sqr(x1.ptr.p_double[2*i+0], _state)+ae_sqr(x1.ptr.p_double[2*i+1], _state), _state), 1.0, _state);
vx = x1.ptr.p_double[2*i+0]/v;
vy = x1.ptr.p_double[2*i+1]/v;
v = g.ptr.p_double[2*i+0]*vx+g.ptr.p_double[2*i+1]*vy;
g.ptr.p_double[2*i+0] = g.ptr.p_double[2*i+0]-vx*v;
g.ptr.p_double[2*i+1] = g.ptr.p_double[2*i+1]-vy*v;
}
gnorm2 = gnorm2+ae_sqr(g.ptr.p_double[2*i+0], _state)+ae_sqr(g.ptr.p_double[2*i+1], _state);
ae_set_error_flag(wereerrors, ae_fp_greater(gnorm2,ae_sqr(tolg, _state)*ae_maxreal(rawgnorm2, 1.0, _state)), __FILE__, __LINE__, "testminnlcunit.ap:2635");
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
This function performs additional tests
On failure sets error flag.
*************************************************************************/
static void testminnlcunit_testother(ae_bool* wereerrors,
ae_state *_state)
{
ae_frame _frame_block;
hqrndstate rs;
double v;
double h;
double fl;
double fr;
double fl2;
double fr2;
double dfl;
double dfr;
double dfl2;
double dfr2;
double d2fl;
double d2fr;
double d2fl2;
double d2fr2;
double f0;
double df;
double d2f;
double ndf;
double nd2f;
double dtol;
double diffstep;
minnlcstate state;
minnlcreport rep;
optguardreport ogrep;
double rho;
ae_int_t aulits;
double tolx;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t n;
ae_vector s;
ae_vector b;
ae_vector x0;
ae_vector x1;
ae_vector x2;
ae_vector x3;
ae_vector xlast;
ae_vector bndl;
ae_vector bndu;
ae_vector xu;
double condv;
ae_matrix a;
ae_matrix c;
ae_matrix fulla;
ae_vector ct;
ae_int_t nlbfgs;
ae_int_t nexactlowrank;
ae_int_t nexactrobust;
ae_int_t nnone;
ae_int_t prectype;
ae_int_t ctype;
ae_int_t trialidx;
ae_int_t blocksize;
ae_int_t blockcnt;
ae_int_t maxits;
ae_int_t spoiliteration;
ae_int_t stopiteration;
ae_int_t spoilvar;
double spoilval;
ae_int_t pass;
ae_int_t solvertype;
ae_int_t badidx0;
ae_int_t badidx1;
ae_int_t nlec;
ae_int_t nlic;
double ss;
ae_int_t stopcallidx;
ae_int_t callidx;
ae_bool terminationrequested;
ae_bool firstrep;
ae_frame_make(_state, &_frame_block);
memset(&rs, 0, sizeof(rs));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&ogrep, 0, sizeof(ogrep));
memset(&s, 0, sizeof(s));
memset(&b, 0, sizeof(b));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&x2, 0, sizeof(x2));
memset(&x3, 0, sizeof(x3));
memset(&xlast, 0, sizeof(xlast));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(&xu, 0, sizeof(xu));
memset(&a, 0, sizeof(a));
memset(&c, 0, sizeof(c));
memset(&fulla, 0, sizeof(fulla));
memset(&ct, 0, sizeof(ct));
_hqrndstate_init(&rs, _state, ae_true);
_minnlcstate_init(&state, _state, ae_true);
_minnlcreport_init(&rep, _state, ae_true);
_optguardreport_init(&ogrep, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x3, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xlast, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xu, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&fulla, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Test equality penalty function (correctly calculated and smooth)
*/
h = 1.0E-4;
v = -0.98;
dtol = 1.0E-3;
while(ae_fp_less_eq(v,0.98))
{
/*
* Test numerical derivative; this test also checks continuity of the
* function
*/
minnlcequalitypenaltyfunction(v-2*h, &fl2, &dfl2, &d2fl2, _state);
minnlcequalitypenaltyfunction(v-h, &fl, &dfl, &d2fl, _state);
minnlcequalitypenaltyfunction(v+h, &fr, &dfr, &d2fr, _state);
minnlcequalitypenaltyfunction(v+2*h, &fr2, &dfr2, &d2fr2, _state);
minnlcequalitypenaltyfunction(v, &f0, &df, &d2f, _state);
ndf = (-fr2+8*fr-8*fl+fl2)/(12*h);
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(ndf-df, _state),dtol*ae_maxreal(ae_fabs(ndf, _state), (double)(1), _state)), __FILE__, __LINE__, "testminnlcunit.ap:2724");
nd2f = (-dfr2+8*dfr-8*dfl+dfl2)/(12*h);
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(nd2f-d2f, _state),dtol*ae_maxreal(ae_fabs(nd2f, _state), (double)(1), _state)), __FILE__, __LINE__, "testminnlcunit.ap:2726");
/*
* Next point
*/
v = v+h;
}
minnlcequalitypenaltyfunction(0.0, &f0, &df, &d2f, _state);
ae_set_error_flag(wereerrors, ae_fp_neq(f0,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:2734");
ae_set_error_flag(wereerrors, ae_fp_neq(df,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:2735");
/*
* Test inequality penalty function (correctly calculated and smooth)
*/
h = 1.0E-4;
v = 0.02;
dtol = 1.0E-3;
while(ae_fp_less_eq(v,2.00))
{
/*
* Test numerical derivative; this test also checks continuity of the
* function
*/
minnlcinequalityshiftfunction(v-2*h, &fl2, &dfl2, &d2fl2, _state);
minnlcinequalityshiftfunction(v-h, &fl, &dfl, &d2fl, _state);
minnlcinequalityshiftfunction(v+h, &fr, &dfr, &d2fr, _state);
minnlcinequalityshiftfunction(v+2*h, &fr2, &dfr2, &d2fr2, _state);
minnlcinequalityshiftfunction(v, &f0, &df, &d2f, _state);
ndf = (-fr2+8*fr-8*fl+fl2)/(12*h);
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(ndf-df, _state),dtol*ae_maxreal(ae_fabs(ndf, _state), (double)(1), _state)), __FILE__, __LINE__, "testminnlcunit.ap:2759");
nd2f = (-dfr2+8*dfr-8*dfl+dfl2)/(12*h);
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(nd2f-d2f, _state),dtol*ae_maxreal(ae_fabs(nd2f, _state), (double)(1), _state)), __FILE__, __LINE__, "testminnlcunit.ap:2761");
/*
* Next point
*/
v = v+h;
}
minnlcinequalityshiftfunction(1.0, &f0, &df, &d2f, _state);
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(f0, _state),1.0E-6), __FILE__, __LINE__, "testminnlcunit.ap:2769");
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(df+1, _state),1.0E-6), __FILE__, __LINE__, "testminnlcunit.ap:2770");
/*
* Test different properties shared by all solvers
*/
for(solvertype=0; solvertype<=testminnlcunit_maxsolvertype; solvertype++)
{
/*
* Test location reports
*/
aulits = 50;
rho = 200.0;
n = 2;
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xlast, n, _state);
x0.ptr.p_double[0] = 0.1+0.1*hqrnduniformr(&rs, _state);
x0.ptr.p_double[1] = 0.2+0.1*hqrnduniformr(&rs, _state);
xlast.ptr.p_double[0] = (double)(0);
xlast.ptr.p_double[1] = (double)(0);
firstrep = ae_true;
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, rho, aulits, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetcond(&state, 1.0E-7, 0, _state);
minnlcsetnlc(&state, 0, 1, _state);
minnlcsetxrep(&state, ae_true, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = ae_sqr(state.x.ptr.p_double[0]-1, _state)+ae_sqr(state.x.ptr.p_double[1]-1, _state);
state.j.ptr.pp_double[0][0] = 2*(state.x.ptr.p_double[0]-1);
state.j.ptr.pp_double[0][1] = 2*(state.x.ptr.p_double[1]-1);
state.fi.ptr.p_double[1] = ae_sqr(state.x.ptr.p_double[0], _state)+ae_sqr(state.x.ptr.p_double[1], _state)-1;
state.j.ptr.pp_double[1][0] = 2*state.x.ptr.p_double[0];
state.j.ptr.pp_double[1][1] = 2*state.x.ptr.p_double[1];
continue;
}
if( state.xupdated )
{
/*
* If first point reported, compare with initial one
*/
if( firstrep )
{
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(state.x.ptr.p_double[0]-x0.ptr.p_double[0], _state),1.0E4*ae_machineepsilon), __FILE__, __LINE__, "testminnlcunit.ap:2823");
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(state.x.ptr.p_double[1]-x0.ptr.p_double[1], _state),1.0E4*ae_machineepsilon), __FILE__, __LINE__, "testminnlcunit.ap:2824");
}
firstrep = ae_false;
/*
* Save last point
*/
xlast.ptr.p_double[0] = state.x.ptr.p_double[0];
xlast.ptr.p_double[1] = state.x.ptr.p_double[1];
/*
* Done
*/
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:2842");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:2843");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[0]-xlast.ptr.p_double[0], _state),1.0E4*ae_machineepsilon), __FILE__, __LINE__, "testminnlcunit.ap:2846");
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[1]-xlast.ptr.p_double[1], _state),1.0E4*ae_machineepsilon), __FILE__, __LINE__, "testminnlcunit.ap:2847");
/*
* Test numerical differentiation
*/
aulits = 50;
rho = 200.0;
tolx = 0.001;
diffstep = 0.0001;
n = 2;
ae_vector_set_length(&x0, n, _state);
x0.ptr.p_double[0] = 0.1;
x0.ptr.p_double[1] = 0.2;
minnlccreatef(n, &x0, diffstep, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, rho, aulits, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetcond(&state, 1.0E-7, 0, _state);
minnlcsetnlc(&state, 0, 1, _state);
while(minnlciteration(&state, _state))
{
if( state.needfi )
{
state.fi.ptr.p_double[0] = ae_sqr(state.x.ptr.p_double[0]-1, _state)+ae_sqr(state.x.ptr.p_double[1]-1, _state);
state.fi.ptr.p_double[1] = ae_sqr(state.x.ptr.p_double[0], _state)+ae_sqr(state.x.ptr.p_double[1], _state)-1;
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:2883");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:2884");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[0]-ae_sqrt((double)(2), _state)/2, _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:2887");
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[1]-ae_sqrt((double)(2), _state)/2, _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:2888");
/*
* Check handling of general linear constraints: solve linearly
* constrained twice, first time with constraints posed as linear
* ones, second time with constraints posed as nonlinear ones.
*
* Linear constraints are normalized because we know that optimizer
* normalizes them internally.
*
* We perform small amount of inner iterations - just 3 steps.
* Only one outer iteration is performed. Such small number of
* iterations allows to reduce influence of round-off errors
* and compare results returned by different control paths within
* optimizer (control path for linear constraints and one for
* nonlinear constraints).
*
* We test following kinds of preconditioners:
* * "none"
* * "exact low rank", restart frequency is 1
* * "exact robust", restart frequency is 1
* Inexact LBFGS-based preconditioner is not tested because its
* behavior greatly depends on order of equations.
*/
n = 15;
k = 5;
maxits = 1;
ae_vector_set_length(&x0, n, _state);
ae_matrix_set_length(&c, k, n+1, _state);
ae_vector_set_length(&ct, k, _state);
for(prectype=0; prectype<=2; prectype++)
{
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
for(i=0; i<=k-1; i++)
{
v = 0.0;
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
v = v+ae_sqr(c.ptr.pp_double[i][j], _state);
}
v = 1/ae_sqrt(v, _state);
ae_v_muld(&c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v);
v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1));
c.ptr.pp_double[i][n] = v;
ct.ptr.p_int[i] = 0;
}
minnlccreate(n, &x0, &state, _state);
minnlcsetcond(&state, 0.0, maxits, _state);
if( solvertype==0 )
{
aulits = 1;
rho = 1.0E3;
minnlcsetalgoaul(&state, rho, aulits, _state);
if( prectype==0 )
{
minnlcsetprecnone(&state, _state);
}
if( prectype==1 )
{
minnlcsetprecexactlowrank(&state, 1, _state);
}
if( prectype==2 )
{
minnlcsetprecexactrobust(&state, 1, _state);
}
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetlc(&state, &c, &ct, k, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_sqr(state.x.ptr.p_double[i], _state);
state.j.ptr.pp_double[0][i] = 2*state.x.ptr.p_double[i];
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:2973");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:2974");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
aulits = 1;
rho = 1.0E3;
minnlcsetalgoaul(&state, rho, aulits, _state);
if( prectype==0 )
{
minnlcsetprecnone(&state, _state);
}
if( prectype==1 )
{
minnlcsetprecexactlowrank(&state, 1, _state);
}
if( prectype==2 )
{
minnlcsetprecexactrobust(&state, 1, _state);
}
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetcond(&state, 0.0, maxits, _state);
minnlcsetnlc(&state, k, 0, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_sqr(state.x.ptr.p_double[i], _state);
state.j.ptr.pp_double[0][i] = 2*state.x.ptr.p_double[i];
}
for(i=0; i<=k-1; i++)
{
v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
state.fi.ptr.p_double[1+i] = v-c.ptr.pp_double[i][n];
ae_v_move(&state.j.ptr.pp_double[1+i][0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x2, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x2, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:3019");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:3020");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-x2.ptr.p_double[i], _state),1.0E-4), __FILE__, __LINE__, "testminnlcunit.ap:3024");
}
}
/*
* Test integrity checks for NAN/INF:
* * algorithm solves optimization problem, which is normal for some time (quadratic)
* * after 5-th step we choose random component of gradient and consistently spoil
* it by NAN or INF.
* * we check that correct termination code is returned (-8)
*/
n = 100;
for(pass=1; pass<=10; pass++)
{
spoiliteration = 5;
stopiteration = 8;
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
/*
* Gradient can be spoiled by +INF, -INF, NAN
*/
spoilvar = hqrnduniformi(&rs, n, _state);
i = hqrnduniformi(&rs, 3, _state);
spoilval = _state->v_nan;
if( i==0 )
{
spoilval = _state->v_neginf;
}
if( i==1 )
{
spoilval = _state->v_posinf;
}
}
else
{
/*
* Function value can be spoiled only by NAN
* (+INF can be recognized as legitimate value during optimization)
*/
spoilvar = -1;
spoilval = _state->v_nan;
}
spdmatrixrndcond(n, 1.0E5, &fulla, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
aulits = 5;
rho = 1.0E3;
minnlcsetalgoaul(&state, rho, aulits, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetcond(&state, 0.0, stopiteration, _state);
minnlcsetxrep(&state, ae_true, _state);
k = -1;
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.j.ptr.pp_double[0][i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
if( k>=spoiliteration )
{
if( spoilvar<0 )
{
state.fi.ptr.p_double[0] = spoilval;
}
else
{
state.j.ptr.pp_double[0][spoilvar] = spoilval;
}
}
continue;
}
if( state.xupdated )
{
inc(&k, _state);
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, rep.terminationtype!=-8, __FILE__, __LINE__, "testminnlcunit.ap:3118");
}
/*
* Test that optimizer respects box constraints in all
* intermediate points:
* * test that analytic Jacobian respects them
* * test that numerical Jacobian respects them
*
* NOTE: we skip SolverType=0 (AUL) because AUL optimizer
* does not provide such guarantee
*/
if( solvertype!=0 )
{
n = 10;
spdmatrixrndcond(n, 1.0E3, &fulla, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
bndl.ptr.p_double[i] = (double)(0);
bndu.ptr.p_double[i] = _state->v_posinf;
}
else
{
bndl.ptr.p_double[i] = _state->v_neginf;
bndu.ptr.p_double[i] = (double)(0);
}
}
/*
* Check analytic Jacobian
*/
minnlccreate(n, &x0, &state, _state);
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
minnlcsetbc(&state, &bndl, &bndu, _state);
minnlcsetcond(&state, 1.0E-8, 0, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(wereerrors, ae_fp_less(state.x.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminnlcunit.ap:3173");
ae_set_error_flag(wereerrors, ae_fp_greater(state.x.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminnlcunit.ap:3174");
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.j.ptr.pp_double[0][i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:3188");
/*
* Check numerical Jacobian
*/
minnlccreatef(n, &x0, 1.0E-4, &state, _state);
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
minnlcsetbc(&state, &bndl, &bndu, _state);
minnlcsetcond(&state, 1.0E-8, 0, _state);
while(minnlciteration(&state, _state))
{
if( state.needfi )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(wereerrors, ae_fp_less(state.x.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminnlcunit.ap:3209");
ae_set_error_flag(wereerrors, ae_fp_greater(state.x.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminnlcunit.ap:3210");
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:3220");
}
/*
* Test constraint violation reports for completely unconstrained
* problems and problems with all constraints being satisfied exactly
*/
tolx = 0.01;
for(pass=1; pass<=10; pass++)
{
n = 1+hqrnduniformi(&rs, 5, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, 1000.0, 10, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetcond(&state, 1.0E-7, 200, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_pow(state.x.ptr.p_double[i], (double)(4), _state);
state.j.ptr.pp_double[0][i] = 4*ae_pow(state.x.ptr.p_double[i], (double)(3), _state);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
/*
* Check solution itself
*/
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:3263");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:3264");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(x1.ptr.p_double[i], _state),tolx), __FILE__, __LINE__, "testminnlcunit.ap:3268");
}
/*
* Check constraint violation reports
*/
ae_set_error_flag(wereerrors, ae_fp_neq(rep.bcerr,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:3273");
ae_set_error_flag(wereerrors, rep.bcidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:3274");
ae_set_error_flag(wereerrors, ae_fp_neq(rep.lcerr,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:3275");
ae_set_error_flag(wereerrors, rep.lcidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:3276");
ae_set_error_flag(wereerrors, ae_fp_neq(rep.nlcerr,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:3277");
ae_set_error_flag(wereerrors, rep.nlcidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:3278");
}
for(pass=1; pass<=10; pass++)
{
n = 1+hqrnduniformi(&rs, 5, _state);
k = 1+hqrnduniformi(&rs, 5, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xu, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_matrix_set_length(&c, k, n+1, _state);
ae_vector_set_length(&ct, k, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
xu.ptr.p_double[i] = hqrndnormal(&rs, _state);
bndl.ptr.p_double[i] = (double)(-1000);
bndu.ptr.p_double[i] = (double)(1000);
}
for(i=0; i<=k-1; i++)
{
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
c.ptr.pp_double[i][n] = (double)(1000);
ct.ptr.p_int[i] = -1;
}
else
{
c.ptr.pp_double[i][n] = (double)(-1000);
ct.ptr.p_int[i] = 1;
}
}
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, 1000.0, 20, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetbc(&state, &bndl, &bndu, _state);
minnlcsetlc(&state, &c, &ct, k, _state);
minnlcsetcond(&state, 1.0E-7, 0, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_pow(state.x.ptr.p_double[i]-xu.ptr.p_double[i], (double)(2), _state);
state.j.ptr.pp_double[0][i] = 2*(state.x.ptr.p_double[i]-xu.ptr.p_double[i]);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
/*
* Check solution itself, calculate reference violation values
*/
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:3343");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:3344");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Check constraint violation reports
*/
ae_set_error_flag(wereerrors, ae_fp_neq(rep.bcerr,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:3351");
ae_set_error_flag(wereerrors, rep.bcidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:3352");
ae_set_error_flag(wereerrors, ae_fp_neq(rep.lcerr,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:3353");
ae_set_error_flag(wereerrors, rep.lcidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:3354");
ae_set_error_flag(wereerrors, ae_fp_neq(rep.nlcerr,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:3355");
ae_set_error_flag(wereerrors, rep.nlcidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:3356");
}
/*
* Test constraint violation reports for box/linearly constrained
* problems. We generate a problem which can not satisfy one (and
* just one) general linear constraint.
*/
tolx = 0.001;
for(pass=1; pass<=10; pass++)
{
/*
* Formulate problem with inconsistent constraints
*/
n = 2+hqrnduniformi(&rs, 5, _state);
k = 1+hqrnduniformi(&rs, 5, _state);
ae_vector_set_length(&s, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xu, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_matrix_set_length(&c, k, n+1, _state);
ae_vector_set_length(&ct, k, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
xu.ptr.p_double[i] = hqrndnormal(&rs, _state);
bndl.ptr.p_double[i] = -0.5*hqrnduniformr(&rs, _state)-0.1;
bndu.ptr.p_double[i] = 0.5*hqrnduniformr(&rs, _state)+0.1;
}
for(i=0; i<=k-1; i++)
{
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
c.ptr.pp_double[i][n] = (double)(1000);
ct.ptr.p_int[i] = -1;
}
else
{
c.ptr.pp_double[i][n] = (double)(-1000);
ct.ptr.p_int[i] = 1;
}
}
ae_assert(n>=2, "NLCTest: integrity check failed", _state);
badidx0 = hqrnduniformi(&rs, k, _state);
badidx1 = hqrnduniformi(&rs, n, _state);
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[badidx0][j] = (double)(0);
}
for(j=0; j<=k-1; j++)
{
c.ptr.pp_double[j][badidx1] = (double)(0);
}
c.ptr.pp_double[badidx0][badidx1] = (double)(1);
c.ptr.pp_double[badidx0][n] = (double)(10*(2*hqrnduniformi(&rs, 2, _state)-1));
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
ct.ptr.p_int[badidx0] = 0;
}
else
{
ct.ptr.p_int[badidx0] = ae_sign(c.ptr.pp_double[badidx0][n], _state);
}
/*
* Create and try to solve
*/
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, 1000.0, 20, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetbc(&state, &bndl, &bndu, _state);
minnlcsetlc(&state, &c, &ct, k, _state);
minnlcsetscale(&state, &s, _state);
minnlcsetcond(&state, 1.0E-7, 0, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_pow(state.x.ptr.p_double[i]-xu.ptr.p_double[i], (double)(2), _state);
state.j.ptr.pp_double[0][i] = 2*(state.x.ptr.p_double[i]-xu.ptr.p_double[i]);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
/*
* Check solution itself, calculate reference violation values
*/
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:3451");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:3452");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Check constraint violation reports
*/
if( ae_fp_greater(rep.bcerr,(double)(0)) )
{
v = ae_maxreal(bndl.ptr.p_double[badidx1]-x1.ptr.p_double[badidx1], x1.ptr.p_double[badidx1]-bndu.ptr.p_double[badidx1], _state);
v = v/s.ptr.p_double[badidx1];
ae_set_error_flag(wereerrors, rep.bcidx!=badidx1, __FILE__, __LINE__, "testminnlcunit.ap:3463");
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(rep.bcerr-v, _state),1.0E3*ae_machineepsilon), __FILE__, __LINE__, "testminnlcunit.ap:3465");
}
else
{
ae_set_error_flag(wereerrors, ae_fp_neq(rep.bcerr,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:3470");
ae_set_error_flag(wereerrors, rep.bcidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:3471");
ae_set_error_flag(wereerrors, ae_fp_less(x1.ptr.p_double[badidx1],bndl.ptr.p_double[badidx1])||ae_fp_greater(x1.ptr.p_double[badidx1],bndu.ptr.p_double[badidx1]), __FILE__, __LINE__, "testminnlcunit.ap:3472");
}
ae_set_error_flag(wereerrors, rep.lcidx!=badidx0, __FILE__, __LINE__, "testminnlcunit.ap:3474");
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(rep.lcerr-ae_fabs(x1.ptr.p_double[badidx1]-c.ptr.pp_double[badidx0][n], _state)/s.ptr.p_double[badidx1], _state),1.0E3*ae_machineepsilon), __FILE__, __LINE__, "testminnlcunit.ap:3475");
ae_set_error_flag(wereerrors, ae_fp_neq(rep.nlcerr,(double)(0)), __FILE__, __LINE__, "testminnlcunit.ap:3476");
ae_set_error_flag(wereerrors, rep.nlcidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:3477");
}
/*
* Test constraint violation reports for box/nonlinearly constrained
* problems. We generate a problem which can not satisfy one (and
* just one) general linear constraint.
*
* NOTE: it is important to have N>=NLEC+NLIC
*/
tolx = 0.001;
for(pass=1; pass<=10; pass++)
{
/*
* Formulate problem with inconsistent constraints
*/
nlec = 1+hqrnduniformi(&rs, 5, _state);
nlic = 1+hqrnduniformi(&rs, 5, _state);
k = nlec+nlic;
n = k+hqrnduniformi(&rs, 5, _state);
ae_vector_set_length(&s, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xu, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_matrix_set_length(&c, k, n+1, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
xu.ptr.p_double[i] = hqrndnormal(&rs, _state);
bndl.ptr.p_double[i] = -0.5*hqrnduniformr(&rs, _state)-0.1;
bndu.ptr.p_double[i] = 0.5*hqrnduniformr(&rs, _state)+0.1;
}
for(i=0; i<=nlec-1; i++)
{
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = (double)(0);
}
c.ptr.pp_double[i][i] = (double)(1);
c.ptr.pp_double[i][n] = bndl.ptr.p_double[i]+hqrnduniformr(&rs, _state)*(bndu.ptr.p_double[i]-bndl.ptr.p_double[i]);
}
for(i=nlec; i<=k-1; i++)
{
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = (double)(0);
}
c.ptr.pp_double[i][i] = (double)(1);
c.ptr.pp_double[i][n] = (double)(1000);
}
badidx0 = hqrnduniformi(&rs, k, _state);
if( badidx0v_posinf;
x0.ptr.p_double[i] = hqrnduniformr(&rs, _state);
}
else
{
bndl.ptr.p_double[i] = (double)(0);
bndu.ptr.p_double[i] = (double)(0);
x0.ptr.p_double[i] = (double)(0);
}
}
for(i=0; i<=blocksize*blockcnt-1; i++)
{
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = 0.0;
}
}
for(k=0; k<=blockcnt-1; k++)
{
rmatrixrndcond(blocksize, condv, &a, _state);
for(i=0; i<=blocksize-1; i++)
{
for(j=0; j<=blocksize-1; j++)
{
c.ptr.pp_double[k*blocksize+i][k*blocksize+j] = a.ptr.pp_double[i][j];
}
}
}
for(i=0; i<=blocksize*blockcnt-1; i++)
{
v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
v = 1/ae_sqrt(v, _state);
ae_v_muld(&c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v);
v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &x0.ptr.p_double[0], 1, ae_v_len(0,n-1));
c.ptr.pp_double[i][n] = v;
ct.ptr.p_int[i] = hqrnduniformi(&rs, 3, _state)-1;
}
/*
* Test unpreconditioned iteration
*/
minnlccreate(n, &x0, &state, _state);
minnlcsetalgoaul(&state, rho, aulits, _state);
minnlcsetcond(&state, 1.0E-7, 0, _state);
if( ctype==0 )
{
minnlcsetlc(&state, &c, &ct, blocksize*blockcnt, _state);
}
else
{
minnlcsetnlc(&state, blocksize*blockcnt, 0, _state);
}
minnlcsetprecnone(&state, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_sqr(state.x.ptr.p_double[i], _state);
state.j.ptr.pp_double[0][i] = 2*state.x.ptr.p_double[i];
}
if( ctype==1 )
{
for(i=0; i<=blocksize*blockcnt-1; i++)
{
v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
state.fi.ptr.p_double[1+i] = v-c.ptr.pp_double[i][n];
ae_v_move(&state.j.ptr.pp_double[1+i][0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:3792");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:3793");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
nnone = nnone+rep.iterationscount;
/*
* Test LBFGS preconditioned iteration
*/
minnlccreate(n, &x0, &state, _state);
minnlcsetalgoaul(&state, rho, aulits, _state);
minnlcsetcond(&state, 1.0E-7, 0, _state);
if( ctype==0 )
{
minnlcsetlc(&state, &c, &ct, blocksize*blockcnt, _state);
}
else
{
minnlcsetnlc(&state, blocksize*blockcnt, 0, _state);
}
minnlcsetprecinexact(&state, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_sqr(state.x.ptr.p_double[i], _state);
state.j.ptr.pp_double[0][i] = 2*state.x.ptr.p_double[i];
}
if( ctype==1 )
{
for(i=0; i<=blocksize*blockcnt-1; i++)
{
v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
state.fi.ptr.p_double[1+i] = v-c.ptr.pp_double[i][n];
ae_v_move(&state.j.ptr.pp_double[1+i][0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:3833");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:3834");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
nlbfgs = nlbfgs+rep.iterationscount;
/*
* Test exact low rank preconditioner
*/
minnlccreate(n, &x0, &state, _state);
minnlcsetalgoaul(&state, rho, aulits, _state);
minnlcsetcond(&state, 1.0E-7, 0, _state);
if( ctype==0 )
{
minnlcsetlc(&state, &c, &ct, blocksize*blockcnt, _state);
}
else
{
minnlcsetnlc(&state, blocksize*blockcnt, 0, _state);
}
minnlcsetprecexactlowrank(&state, 3, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_sqr(state.x.ptr.p_double[i], _state);
state.j.ptr.pp_double[0][i] = 2*state.x.ptr.p_double[i];
}
if( ctype==1 )
{
for(i=0; i<=blocksize*blockcnt-1; i++)
{
v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
state.fi.ptr.p_double[1+i] = v-c.ptr.pp_double[i][n];
ae_v_move(&state.j.ptr.pp_double[1+i][0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:3874");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:3875");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
nexactlowrank = nexactlowrank+rep.iterationscount;
/*
* Test exact robust preconditioner
*/
minnlccreate(n, &x0, &state, _state);
minnlcsetalgoaul(&state, rho, aulits, _state);
minnlcsetcond(&state, 1.0E-7, 0, _state);
if( ctype==0 )
{
minnlcsetlc(&state, &c, &ct, blocksize*blockcnt, _state);
}
else
{
minnlcsetnlc(&state, blocksize*blockcnt, 0, _state);
}
minnlcsetprecexactrobust(&state, 3, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_sqr(state.x.ptr.p_double[i], _state);
state.j.ptr.pp_double[0][i] = 2*state.x.ptr.p_double[i];
}
if( ctype==1 )
{
for(i=0; i<=blocksize*blockcnt-1; i++)
{
v = ae_v_dotproduct(&c.ptr.pp_double[i][0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
state.fi.ptr.p_double[1+i] = v-c.ptr.pp_double[i][n];
ae_v_move(&state.j.ptr.pp_double[1+i][0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:3915");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:3916");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
nexactrobust = nexactrobust+rep.iterationscount;
}
/*
* Compare.
*
* Preconditioners must be significantly different,
* with exact being best one, inexact being second,
* "none" being worst option.
*/
ae_set_error_flag(wereerrors, !ae_fp_less((double)(nexactlowrank),0.9*nlbfgs), __FILE__, __LINE__, "testminnlcunit.ap:3929");
ae_set_error_flag(wereerrors, !ae_fp_less((double)(nexactrobust),0.9*nlbfgs), __FILE__, __LINE__, "testminnlcunit.ap:3930");
ae_set_error_flag(wereerrors, !ae_fp_less((double)(nlbfgs),0.9*nnone), __FILE__, __LINE__, "testminnlcunit.ap:3931");
}
ae_frame_leave(_state);
}
/*************************************************************************
This function tests OptGuard
On failure sets error flag.
*************************************************************************/
static void testminnlcunit_testoptguard(ae_bool* wereerrors,
ae_state *_state)
{
ae_frame _frame_block;
hqrndstate rs;
double v;
minnlcstate state;
minnlcreport rep;
optguardreport ogrep;
optguardnonc1test0report ognonc1test0strrep;
optguardnonc1test0report ognonc1test0lngrep;
optguardnonc1test1report ognonc1test1strrep;
optguardnonc1test1report ognonc1test1lngrep;
ae_int_t i;
ae_int_t j;
ae_int_t n;
ae_matrix a;
ae_matrix a1;
ae_vector s;
ae_vector x0;
ae_vector x1;
ae_vector xlast;
ae_vector b;
ae_vector bndl;
ae_vector bndu;
ae_vector xu;
double diffstep;
ae_int_t pass;
ae_int_t solvertype;
double vbnd;
double fscale;
ae_int_t defecttype;
double vshift;
double vpower;
ae_int_t cntabove;
ae_int_t cntbelow;
ae_bool linesearchstarted;
ae_bool wasgoodlinesearch0;
ae_bool wasgoodlinesearch1;
ae_int_t shortsessions;
ae_int_t maxshortsessions;
double stplen;
double shortstplen;
ae_bool failed;
ae_int_t passcount;
ae_int_t maxfails;
ae_int_t failurecounter;
ae_int_t maxc1test0fails;
ae_int_t maxc1test1fails;
ae_int_t c1test0fails;
ae_int_t c1test1fails;
ae_int_t goodidx;
double avgstr0len;
double avglng0len;
double avgstr1len;
double avglng1len;
ae_int_t funcidx;
ae_int_t varidx;
ae_int_t skind;
ae_matrix jactrue;
ae_matrix jacdefect;
ae_frame_make(_state, &_frame_block);
memset(&rs, 0, sizeof(rs));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&ogrep, 0, sizeof(ogrep));
memset(&ognonc1test0strrep, 0, sizeof(ognonc1test0strrep));
memset(&ognonc1test0lngrep, 0, sizeof(ognonc1test0lngrep));
memset(&ognonc1test1strrep, 0, sizeof(ognonc1test1strrep));
memset(&ognonc1test1lngrep, 0, sizeof(ognonc1test1lngrep));
memset(&a, 0, sizeof(a));
memset(&a1, 0, sizeof(a1));
memset(&s, 0, sizeof(s));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&xlast, 0, sizeof(xlast));
memset(&b, 0, sizeof(b));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(&xu, 0, sizeof(xu));
memset(&jactrue, 0, sizeof(jactrue));
memset(&jacdefect, 0, sizeof(jacdefect));
_hqrndstate_init(&rs, _state, ae_true);
_minnlcstate_init(&state, _state, ae_true);
_minnlcreport_init(&rep, _state, ae_true);
_optguardreport_init(&ogrep, _state, ae_true);
_optguardnonc1test0report_init(&ognonc1test0strrep, _state, ae_true);
_optguardnonc1test0report_init(&ognonc1test0lngrep, _state, ae_true);
_optguardnonc1test1report_init(&ognonc1test1strrep, _state, ae_true);
_optguardnonc1test1report_init(&ognonc1test1lngrep, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xlast, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xu, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&jactrue, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&jacdefect, 0, 0, DT_REAL, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Test functionality which should work in all NLC solvers
*/
for(solvertype=0; solvertype<=testminnlcunit_maxsolvertype; solvertype++)
{
/*
* Check that gradient verification is disabled by default:
* gradient checking for bad problem must return nothing
*/
n = 10;
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 1.0+0.1*i;
}
spdmatrixrndcond(n, 1.0E3, &a, _state);
spdmatrixrndcond(n, 1.0E3, &a1, _state);
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, 1000.0, 5, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetcond(&state, 1.0E-7, 10, _state);
minnlcsetnlc(&state, 0, 1, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*v;
}
state.fi.ptr.p_double[1] = (double)(0);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]*a1.ptr.pp_double[i][j];
}
state.fi.ptr.p_double[1] = state.fi.ptr.p_double[1]+0.5*state.x.ptr.p_double[i]*v;
}
for(i=0; i<=n-1; i++)
{
state.j.ptr.pp_double[0][i] = (double)(0);
state.j.ptr.pp_double[1][i] = (double)(0);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
minnlcoptguardresults(&state, &ogrep, _state);
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:4043");
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4044");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(wereerrors, ogrep.badgradxbase.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:4047");
ae_set_error_flag(wereerrors, ogrep.badgraduser.rows!=0, __FILE__, __LINE__, "testminnlcunit.ap:4048");
ae_set_error_flag(wereerrors, ogrep.badgraduser.cols!=0, __FILE__, __LINE__, "testminnlcunit.ap:4049");
ae_set_error_flag(wereerrors, ogrep.badgradnum.rows!=0, __FILE__, __LINE__, "testminnlcunit.ap:4050");
ae_set_error_flag(wereerrors, ogrep.badgradnum.cols!=0, __FILE__, __LINE__, "testminnlcunit.ap:4051");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(wereerrors, ogrep.badgradsuspected, __FILE__, __LINE__, "testminnlcunit.ap:4054");
ae_set_error_flag(wereerrors, ogrep.badgradfidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:4055");
ae_set_error_flag(wereerrors, ogrep.badgradvidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:4056");
/*
* Test that C0/C1 continuity monitoring is disabled by default;
* we solve nonsmooth problem and test that nothing is returned
* by OptGuard.
*/
n = 10;
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, 1000.0, 1, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetcond(&state, 1.0E-9, 50, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.j.ptr.pp_double[0][i] = (double)(0);
}
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_fabs(v, _state);
v = (double)(ae_sign(v, _state));
for(j=0; j<=n-1; j++)
{
state.j.ptr.pp_double[0][j] = state.j.ptr.pp_double[0][j]+v*a.ptr.pp_double[i][j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
minnlcoptguardresults(&state, &ogrep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4104");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:4105");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminnlcunit.ap:4108");
ae_set_error_flag(wereerrors, ogrep.nonc1suspected, __FILE__, __LINE__, "testminnlcunit.ap:4109");
ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:4110");
ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminnlcunit.ap:4111");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx>=0, __FILE__, __LINE__, "testminnlcunit.ap:4112");
ae_set_error_flag(wereerrors, ogrep.nonc1test0positive, __FILE__, __LINE__, "testminnlcunit.ap:4113");
ae_set_error_flag(wereerrors, ogrep.nonc1test1positive, __FILE__, __LINE__, "testminnlcunit.ap:4114");
/*
* Test gradient checking functionality, try various
* defect types:
* * accidental zeroing of some gradient component
* * accidental addition of 1.0 to some component
* * accidental multiplication by 2.0
* Try distorting both target and constraints.
*/
diffstep = 0.001;
n = 10;
for(skind=0; skind<=1; skind++)
{
for(funcidx=0; funcidx<=1; funcidx++)
{
for(defecttype=-1; defecttype<=2; defecttype++)
{
varidx = hqrnduniformi(&rs, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&s, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = ae_pow((double)(10), skind*(30*hqrnduniformr(&rs, _state)-15), _state);
x0.ptr.p_double[i] = (1.0+0.1*i)*s.ptr.p_double[i];
j = hqrnduniformi(&rs, 3, _state);
bndl.ptr.p_double[i] = -100*s.ptr.p_double[i];
bndu.ptr.p_double[i] = 100*s.ptr.p_double[i];
if( j==1 )
{
bndl.ptr.p_double[i] = x0.ptr.p_double[i];
}
if( j==2 )
{
bndu.ptr.p_double[i] = x0.ptr.p_double[i];
}
}
spdmatrixrndcond(n, 1.0E3, &a, _state);
spdmatrixrndcond(n, 1.0E3, &a1, _state);
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, 1000.0, 5, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcoptguardgradient(&state, diffstep, _state);
minnlcsetcond(&state, 1.0E-7, 10, _state);
minnlcsetscale(&state, &s, _state);
minnlcsetbc(&state, &bndl, &bndu, _state);
minnlcsetnlc(&state, 0, 1, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
if( solvertype!=0 )
{
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(wereerrors, ae_fp_less(state.x.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminnlcunit.ap:4174");
ae_set_error_flag(wereerrors, ae_fp_greater(state.x.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminnlcunit.ap:4175");
}
}
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*(state.x.ptr.p_double[i]/s.ptr.p_double[i])*v;
state.j.ptr.pp_double[0][i] = v;
}
state.fi.ptr.p_double[1] = (double)(0);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]/s.ptr.p_double[j]*a1.ptr.pp_double[i][j];
}
state.fi.ptr.p_double[1] = state.fi.ptr.p_double[1]+0.5*(state.x.ptr.p_double[i]/s.ptr.p_double[i])*v;
state.j.ptr.pp_double[1][i] = v;
}
if( defecttype==0 )
{
state.j.ptr.pp_double[funcidx][varidx] = (double)(0);
}
if( defecttype==1 )
{
state.j.ptr.pp_double[funcidx][varidx] = state.j.ptr.pp_double[funcidx][varidx]+1;
}
if( defecttype==2 )
{
state.j.ptr.pp_double[funcidx][varidx] = state.j.ptr.pp_double[funcidx][varidx]*2;
}
for(i=0; i<=n-1; i++)
{
state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]/s.ptr.p_double[i];
state.j.ptr.pp_double[1][i] = state.j.ptr.pp_double[1][i]/s.ptr.p_double[i];
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
minnlcoptguardresults(&state, &ogrep, _state);
/*
* Check that something is returned
*/
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:4225");
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4226");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Compute reference values for true and spoiled Jacobian at X0
*/
ae_set_error_flag(wereerrors, !isfinitevector(&ogrep.badgradxbase, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4233");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_matrix_set_length(&jactrue, 2, n, _state);
ae_matrix_set_length(&jacdefect, 2, n, _state);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+ogrep.badgradxbase.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
jactrue.ptr.pp_double[0][i] = v;
jacdefect.ptr.pp_double[0][i] = v;
}
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+ogrep.badgradxbase.ptr.p_double[j]/s.ptr.p_double[j]*a1.ptr.pp_double[i][j];
}
jactrue.ptr.pp_double[1][i] = v;
jacdefect.ptr.pp_double[1][i] = v;
}
if( defecttype==0 )
{
jacdefect.ptr.pp_double[funcidx][varidx] = (double)(0);
}
if( defecttype==1 )
{
jacdefect.ptr.pp_double[funcidx][varidx] = jacdefect.ptr.pp_double[funcidx][varidx]+1;
}
if( defecttype==2 )
{
jacdefect.ptr.pp_double[funcidx][varidx] = jacdefect.ptr.pp_double[funcidx][varidx]*2;
}
for(i=0; i<=n-1; i++)
{
jactrue.ptr.pp_double[0][i] = jactrue.ptr.pp_double[0][i]/s.ptr.p_double[i];
jactrue.ptr.pp_double[1][i] = jactrue.ptr.pp_double[1][i]/s.ptr.p_double[i];
jacdefect.ptr.pp_double[0][i] = jacdefect.ptr.pp_double[0][i]/s.ptr.p_double[i];
jacdefect.ptr.pp_double[1][i] = jacdefect.ptr.pp_double[1][i]/s.ptr.p_double[i];
}
/*
* Check OptGuard report
*/
ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgraduser, 2, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4271");
ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgradnum, 2, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4272");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
if( defecttype>=0 )
{
ae_set_error_flag(wereerrors, !ogrep.badgradsuspected, __FILE__, __LINE__, "testminnlcunit.ap:4277");
ae_set_error_flag(wereerrors, ogrep.badgradfidx!=funcidx, __FILE__, __LINE__, "testminnlcunit.ap:4278");
ae_set_error_flag(wereerrors, ogrep.badgradvidx!=varidx, __FILE__, __LINE__, "testminnlcunit.ap:4279");
}
else
{
ae_set_error_flag(wereerrors, ogrep.badgradsuspected, __FILE__, __LINE__, "testminnlcunit.ap:4283");
ae_set_error_flag(wereerrors, ogrep.badgradfidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:4284");
ae_set_error_flag(wereerrors, ogrep.badgradvidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:4285");
}
for(i=0; i<=1; i++)
{
for(j=0; j<=n-1; j++)
{
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jactrue.ptr.pp_double[i][j]-ogrep.badgradnum.ptr.pp_double[i][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testminnlcunit.ap:4290");
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jacdefect.ptr.pp_double[i][j]-ogrep.badgraduser.ptr.pp_double[i][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testminnlcunit.ap:4291");
}
}
}
}
}
/*
* Make sure than no false positives are reported for larger
* problems where numerical noise can be an issue:
* * N=100 dimensions
* * nonnegativity constraints
* * positive-definite quadratic programming problem
* * upper limit on iterations count, MaxIts=25
* We simply test that OptGuard does not return error code.
*/
n = 100;
spdmatrixrndcond(n, 1.0E2, &a, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
bndl.ptr.p_double[i] = (double)(0);
bndu.ptr.p_double[i] = _state->v_posinf;
x0.ptr.p_double[i] = ae_pow(2.0, hqrndnormal(&rs, _state), _state);
}
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, 1000.0, 3, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel, _state), _state);
minnlcsetbc(&state, &bndl, &bndu, _state);
minnlcsetcond(&state, 1.0E-7, 25, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.j.ptr.pp_double[0][i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*a.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+a.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4349");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:4350");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
minnlcoptguardresults(&state, &ogrep, _state);
ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:4354");
}
/*
* Test functionality which works only in some NLC solvers
*/
for(solvertype=0; solvertype<=testminnlcunit_maxsolvertype; solvertype++)
{
/*
* Skip
*/
if( solvertype==2 )
{
continue;
}
/*
* Test detection of discontinuities in the target function
* and its gradient (analytic gradient is used).
*
* Target function is convex quadratic modified by addition of
* nonsmooth/discontinuous (depending on DefectType) perturbation.
*
* This test is complicated because OptGuard does NOT guarantee
* that C0/C1 violations are ALWAYS caught. OptGuard needs line
* search to perform
* * at least 4 function evaluations, with discontinuity in the
* middle of them (at least two function values from the left,
* at least two from the right)
* * at least 7 function evaluations to catch C1 violation
*
* Furthermore, it is possible that optimizer will perform a few
* function evaluations BEFORE and AFTER line search starts,
* which complicates everything.
*
* N, VPower and VBnd are selected randomly at the start of the test.
*/
for(defecttype=0; defecttype<=1; defecttype++)
{
n = 1+hqrnduniformi(&rs, 10, _state);
vpower = 10*ae_pow((double)(10), -0.2*hqrnduniformr(&rs, _state), _state);
vbnd = 1*ae_pow((double)(10), -0.2*hqrnduniformr(&rs, _state), _state);
fscale = 0.1;
maxshortsessions = 4;
shortstplen = 1.0E-6;
shortsessions = 0;
for(pass=1; pass<=100; pass++)
{
/*
* Formulate problem
*/
ae_vector_set_length(&s, n, _state);
ae_vector_set_length(&xlast, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xu, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
do
{
v = (double)(0);
for(i=0; i<=n-1; i++)
{
xu.ptr.p_double[i] = 0.1+hqrnduniformr(&rs, _state);
v = v+ae_sqr(xu.ptr.p_double[i], _state);
}
v = ae_sqrt(v, _state);
}
while(ae_fp_less_eq(v,(double)(0)));
for(i=0; i<=n-1; i++)
{
xu.ptr.p_double[i] = xu.ptr.p_double[i]/v;
}
for(i=0; i<=n-1; i++)
{
xlast.ptr.p_double[i] = (double)(0);
x0.ptr.p_double[i] = 2*xu.ptr.p_double[i]+0.1*hqrnduniformr(&rs, _state);
bndl.ptr.p_double[i] = 0.0;
bndu.ptr.p_double[i] = _state->v_posinf;
s.ptr.p_double[i] = ae_pow((double)(2), 0.1*hqrndnormal(&rs, _state), _state);
}
if( defecttype==0 )
{
vshift = (double)(1);
}
else
{
vshift = (double)(0);
}
/*
* Prepare code which detects "good" (long enough) line searches
*/
cntbelow = 0;
cntabove = 0;
wasgoodlinesearch0 = ae_false;
wasgoodlinesearch1 = ae_false;
linesearchstarted = ae_false;
/*
* Create and try to solve
*/
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, 1000.0, 5, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetbc(&state, &bndl, &bndu, _state);
minnlcsetscale(&state, &s, _state);
minnlcsetcond(&state, 1.0E-7, 1000, _state);
minnlcoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel, _state), _state);
minnlcsetxrep(&state, ae_true, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+fscale*ae_pow(state.x.ptr.p_double[i], (double)(2), _state);
state.j.ptr.pp_double[0][i] = 2*fscale*state.x.ptr.p_double[i];
}
v = (double)(0);
for(i=0; i<=n-1; i++)
{
v = v+state.x.ptr.p_double[i]*xu.ptr.p_double[i];
}
if( ae_fp_less(v,vbnd) )
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+(vshift+vpower*(vbnd-v));
for(i=0; i<=n-1; i++)
{
state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]-vpower*xu.ptr.p_double[i];
}
if( linesearchstarted )
{
inc(&cntbelow, _state);
}
}
else
{
if( linesearchstarted )
{
inc(&cntabove, _state);
}
}
continue;
}
if( state.xupdated )
{
/*
* Finalize previous line search
*/
if( linesearchstarted )
{
stplen = (double)(0);
for(i=0; i<=n-1; i++)
{
stplen = stplen+ae_sqr(state.x.ptr.p_double[i]-xlast.ptr.p_double[i], _state);
}
stplen = ae_sqrt(stplen, _state);
wasgoodlinesearch0 = wasgoodlinesearch0||((cntbelow>=2&&cntabove>=2)&&ae_fp_greater_eq(stplen,shortstplen));
wasgoodlinesearch1 = wasgoodlinesearch1||((cntbelow>=2&&cntabove>=2)&&ae_fp_greater_eq(stplen,shortstplen));
}
/*
* Start new line search
*/
linesearchstarted = ae_true;
cntbelow = 0;
cntabove = 0;
for(i=0; i<=n-1; i++)
{
xlast.ptr.p_double[i] = state.x.ptr.p_double[i];
}
v = (double)(0);
for(i=0; i<=n-1; i++)
{
v = v+state.x.ptr.p_double[i]*xu.ptr.p_double[i];
}
if( ae_fp_less(v,vbnd) )
{
inc(&cntbelow, _state);
}
else
{
inc(&cntabove, _state);
}
/*
* Done
*/
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
minnlcoptguardresults(&state, &ogrep, _state);
/*
* Check basic properties of the solution
*/
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4531");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:4532");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Check OptGuard report, increase
*/
if( defecttype==0 )
{
if( wasgoodlinesearch0 )
{
ae_set_error_flag(wereerrors, optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:4543");
ae_set_error_flag(wereerrors, !ogrep.nonc0suspected, __FILE__, __LINE__, "testminnlcunit.ap:4544");
ae_set_error_flag(wereerrors, ogrep.nonc0fidx!=0, __FILE__, __LINE__, "testminnlcunit.ap:4545");
}
else
{
inc(&shortsessions, _state);
}
}
if( defecttype==1 )
{
if( wasgoodlinesearch1 )
{
ae_set_error_flag(wereerrors, optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminnlcunit.ap:4554");
ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminnlcunit.ap:4555");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testminnlcunit.ap:4556");
}
else
{
inc(&shortsessions, _state);
}
}
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
}
/*
* Check that short optimization sessions are rare.
*/
ae_set_error_flag(wereerrors, shortsessions>maxshortsessions, __FILE__, __LINE__, "testminnlcunit.ap:4568");
}
/*
* One more test for detection of C1 continuity violations in the target.
*
* Target function is a sum of |(x,c_i)| for i=1..N.
* No constraints is present.
* Analytic gradient is provided.
*
* OptGuard should be able to detect violations in more than
* 99.9% of runs; it means that 100 runs should have no more than 4
* failures in all cases (even after multiple repeated tests; according
* to the binomial distribution quantiles).
*
* We select some N and perform exhaustive search for this N.
*
* NOTE: we skip SQP for this test
*/
passcount = 100;
maxfails = 4;
maxc1test0fails = 10;
maxc1test1fails = 10;
n = 1+hqrnduniformi(&rs, 10, _state);
failurecounter = 0;
c1test0fails = 0;
c1test1fails = 0;
avgstr0len = (double)(0);
avglng0len = (double)(0);
avgstr1len = (double)(0);
avglng1len = (double)(0);
for(pass=1; pass<=passcount; pass++)
{
/*
* Formulate problem
*/
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
/*
* Create and try to solve
*/
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, 1000.0, 1, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetcond(&state, 1.0E-7, 50, _state);
minnlcsetscale(&state, &s, _state);
minnlcoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel, _state), _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.j.ptr.pp_double[0][i] = (double)(0);
}
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_fabs(v, _state);
v = (double)(ae_sign(v, _state));
for(j=0; j<=n-1; j++)
{
state.j.ptr.pp_double[0][j] = state.j.ptr.pp_double[0][j]+v*a.ptr.pp_double[i][j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
minnlcoptguardresults(&state, &ogrep, _state);
/*
* Check basic properties of the solution
*/
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4658");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:4659");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Check generic OptGuard report: distinguish between "hard"
* failures which result in immediate termination
* (C0 violation being reported) and "soft" ones
* (C1 violation is NOT reported) which accumulate
* until we exhaust limit.
*/
ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminnlcunit.ap:4670");
ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminnlcunit.ap:4671");
failed = ae_false;
failed = failed||optguardallclear(&ogrep, _state);
failed = failed||!ogrep.nonc1suspected;
failed = failed||ogrep.nonc1fidx!=0;
if( failed )
{
inc(&failurecounter, _state);
}
/*
* Check C1 continuity test #0
*/
minnlcoptguardnonc1test0results(&state, &ognonc1test0strrep, &ognonc1test0lngrep, _state);
minnlcoptguardnonc1test1results(&state, &ognonc1test1strrep, &ognonc1test1lngrep, _state);
if( ogrep.nonc1test0positive )
{
ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminnlcunit.ap:4686");
ae_set_error_flag(wereerrors, !ognonc1test0strrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4687");
ae_set_error_flag(wereerrors, !ognonc1test0lngrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4688");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testminnlcunit.ap:4689");
testminnlcunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0strrep, &a, n, _state);
testminnlcunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0lngrep, &a, n, _state);
avgstr0len = avgstr0len+(double)ognonc1test0strrep.cnt/(double)passcount;
avglng0len = avglng0len+(double)ognonc1test0lngrep.cnt/(double)passcount;
}
else
{
ae_set_error_flag(wereerrors, ognonc1test0strrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4697");
ae_set_error_flag(wereerrors, ognonc1test0lngrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4698");
testminnlcunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0strrep, &a, n, _state);
testminnlcunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0lngrep, &a, n, _state);
inc(&c1test0fails, _state);
}
if( ogrep.nonc1test1positive )
{
ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminnlcunit.ap:4705");
ae_set_error_flag(wereerrors, !ognonc1test1strrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4706");
ae_set_error_flag(wereerrors, !ognonc1test1lngrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4707");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testminnlcunit.ap:4708");
testminnlcunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1strrep, &a, n, _state);
testminnlcunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1lngrep, &a, n, _state);
avgstr1len = avgstr1len+(double)ognonc1test1strrep.cnt/(double)passcount;
avglng1len = avglng1len+(double)ognonc1test1lngrep.cnt/(double)passcount;
}
else
{
ae_set_error_flag(wereerrors, ognonc1test1strrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4716");
ae_set_error_flag(wereerrors, ognonc1test1lngrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4717");
testminnlcunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1strrep, &a, n, _state);
testminnlcunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1lngrep, &a, n, _state);
inc(&c1test1fails, _state);
}
}
ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testminnlcunit.ap:4724");
ae_set_error_flag(wereerrors, c1test0fails>maxc1test0fails, __FILE__, __LINE__, "testminnlcunit.ap:4725");
ae_set_error_flag(wereerrors, c1test1fails>maxc1test1fails, __FILE__, __LINE__, "testminnlcunit.ap:4726");
ae_set_error_flag(wereerrors, ae_fp_less_eq(avglng0len,avgstr0len), __FILE__, __LINE__, "testminnlcunit.ap:4727");
ae_set_error_flag(wereerrors, ae_fp_less_eq(avglng1len,avgstr1len), __FILE__, __LINE__, "testminnlcunit.ap:4728");
/*
* Detection of C1 continuity violations in the target under numerical differentiation:
* * target function is a sum of |(x,c_i)| for i=1..N.
* * no constraints is present.
* * analytic gradient is provided.
*
* OptGuard should always be able to detect violations in more than
* 99% of runs (note: reduced strength when compared with analytic gradient);
* it means that 100 runs should have no more than 10 failures in all cases
* (even after multiple repeated tests; according to the binomial distribution
* quantiles).
*
* We select some N and perform exhaustive search for this N.
*
* NOTE: we skip SQP solver for this test
*/
diffstep = 0.0001;
passcount = 100;
maxfails = 10;
n = 1+hqrnduniformi(&rs, 10, _state);
failurecounter = 0;
for(pass=1; pass<=passcount; pass++)
{
/*
* Formulate problem
*/
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = 0.01*ae_pow((double)(2), 0.33*hqrndnormal(&rs, _state), _state);
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
/*
* Create and try to solve
*/
minnlccreatef(n, &x0, diffstep, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, 1000.0, 1, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetcond(&state, 1.0E-7, 50, _state);
minnlcoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel, _state), _state);
while(minnlciteration(&state, _state))
{
if( state.needfi )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+ae_fabs(v, _state);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
minnlcoptguardresults(&state, &ogrep, _state);
/*
* Check basic properties of the solution
*/
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4803");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:4804");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Check OptGuard report: distinguish between "hard"
* failures which result in immediate termination
* (C0 violation being reported) and "soft" ones
* (C1 violation is NOT reported) which accumulate
* until we exhaust limit.
*/
ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminnlcunit.ap:4815");
ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminnlcunit.ap:4816");
failed = ae_false;
failed = failed||optguardallclear(&ogrep, _state);
failed = failed||!ogrep.nonc1suspected;
failed = failed||ogrep.nonc1fidx!=0;
if( failed )
{
inc(&failurecounter, _state);
}
}
ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testminnlcunit.ap:4824");
/*
* Detection of C1 continuity violations in the nonlinear constraints.
*
* This test is a bit tricky because optimizers are less sensitive to
* continuity violations in constraints, so we may have hard time collecting
* enough statistics. In order to do so we solve carefully designed hard
* problem with MULTIPLE bad constraints and only one good constraint.
*
* Optimizer may report any of bad constraints, but not good one.
*
* We select some N and perform exhaustive search for this N.
*/
passcount = 100;
maxfails = 20;
n = 5;
failurecounter = 0;
c1test0fails = 0;
c1test1fails = 0;
for(pass=1; pass<=passcount; pass++)
{
/*
* Formulate problem, select constraint index to perturb with
* nonsmoothness; make sure that this constraint is active at
* the solution
*/
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&s, n, _state);
ae_vector_set_length(&b, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrnduniformr(&rs, _state)-0.5;
s.ptr.p_double[i] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = ae_pow((double)(2), 0.01*hqrndnormal(&rs, _state), _state);
}
}
goodidx = hqrnduniformi(&rs, n, _state);
/*
* Create and try to solve
*/
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, 1000.0, 3, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetcond(&state, 1.0E-7, 50, _state);
minnlcsetnlc(&state, 0, n, _state);
minnlcsetscale(&state, &s, _state);
minnlcoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminnlcunit_maxoptguardlevel, _state), _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.j.ptr.pp_double[0][i] = b.ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[1+i] = (double)(-1);
for(j=0; j<=n-1; j++)
{
state.fi.ptr.p_double[1+i] = state.fi.ptr.p_double[1+i]+a.ptr.pp_double[i][j]*ae_sqr(state.x.ptr.p_double[j], _state);
state.j.ptr.pp_double[1+i][j] = 2*a.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
if( i!=goodidx )
{
state.fi.ptr.p_double[1+i] = ae_maxreal(state.fi.ptr.p_double[1+i], 0.0, _state);
for(j=0; j<=n-1; j++)
{
state.j.ptr.pp_double[1+i][j] = ae_sign(state.fi.ptr.p_double[1+i], _state)*state.j.ptr.pp_double[1+i][j];
}
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
minnlcoptguardresults(&state, &ogrep, _state);
/*
* Check basic properties of the solution
*/
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:4920");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:4921");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Check generic OptGuard report: distinguish between "hard"
* failures which result in immediate termination
* (C0 violation being reported) and "soft" ones
* (C1 violation is NOT reported) which accumulate
* until we exhaust limit.
*/
ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminnlcunit.ap:4932");
ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminnlcunit.ap:4933");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx==goodidx+1, __FILE__, __LINE__, "testminnlcunit.ap:4934");
failed = ae_false;
failed = failed||optguardallclear(&ogrep, _state);
failed = failed||!ogrep.nonc1suspected;
if( failed )
{
inc(&failurecounter, _state);
}
/*
* Check C1 continuity tests #0 and #1
*/
minnlcoptguardnonc1test0results(&state, &ognonc1test0strrep, &ognonc1test0lngrep, _state);
minnlcoptguardnonc1test1results(&state, &ognonc1test1strrep, &ognonc1test1lngrep, _state);
if( ogrep.nonc1test0positive )
{
ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminnlcunit.ap:4948");
ae_set_error_flag(wereerrors, !ognonc1test0strrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4949");
ae_set_error_flag(wereerrors, !ognonc1test0lngrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4950");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx<1, __FILE__, __LINE__, "testminnlcunit.ap:4951");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx>n, __FILE__, __LINE__, "testminnlcunit.ap:4952");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx==goodidx+1, __FILE__, __LINE__, "testminnlcunit.ap:4953");
testminnlcunit_testoptguardc1test0reportfortask1(wereerrors, &ognonc1test0strrep, &a, n, goodidx, _state);
testminnlcunit_testoptguardc1test0reportfortask1(wereerrors, &ognonc1test0lngrep, &a, n, goodidx, _state);
}
else
{
ae_set_error_flag(wereerrors, ognonc1test0strrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4959");
ae_set_error_flag(wereerrors, ognonc1test0lngrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4960");
testminnlcunit_testoptguardc1test0reportfortask1(wereerrors, &ognonc1test0strrep, &a, n, goodidx, _state);
testminnlcunit_testoptguardc1test0reportfortask1(wereerrors, &ognonc1test0lngrep, &a, n, goodidx, _state);
inc(&c1test0fails, _state);
}
if( ogrep.nonc1test1positive )
{
ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminnlcunit.ap:4967");
ae_set_error_flag(wereerrors, !ognonc1test1strrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4968");
ae_set_error_flag(wereerrors, !ognonc1test1lngrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4969");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx<1, __FILE__, __LINE__, "testminnlcunit.ap:4970");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx>n, __FILE__, __LINE__, "testminnlcunit.ap:4971");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx==goodidx+1, __FILE__, __LINE__, "testminnlcunit.ap:4972");
testminnlcunit_testoptguardc1test1reportfortask1(wereerrors, &ognonc1test1strrep, &a, n, goodidx, _state);
testminnlcunit_testoptguardc1test1reportfortask1(wereerrors, &ognonc1test1lngrep, &a, n, goodidx, _state);
}
else
{
ae_set_error_flag(wereerrors, ognonc1test1strrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4978");
ae_set_error_flag(wereerrors, ognonc1test1lngrep.positive, __FILE__, __LINE__, "testminnlcunit.ap:4979");
testminnlcunit_testoptguardc1test1reportfortask1(wereerrors, &ognonc1test1strrep, &a, n, goodidx, _state);
testminnlcunit_testoptguardc1test1reportfortask1(wereerrors, &ognonc1test1lngrep, &a, n, goodidx, _state);
inc(&c1test1fails, _state);
}
}
ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testminnlcunit.ap:4985");
}
ae_frame_leave(_state);
}
/*************************************************************************
This function performs tests for fixed bugs
On failure sets error flag.
*************************************************************************/
static void testminnlcunit_testbugs(ae_bool* wereerrors, ae_state *_state)
{
ae_frame _frame_block;
hqrndstate rs;
ae_int_t n;
ae_int_t aulits;
ae_int_t maxits;
double rho;
ae_int_t ckind;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t solvertype;
minnlcstate state;
minnlcreport rep;
ae_vector x0;
ae_vector x1;
ae_vector x2;
ae_vector bndl;
ae_vector bndu;
ae_vector d;
ae_vector b;
ae_vector ct;
ae_matrix c;
ae_frame_make(_state, &_frame_block);
memset(&rs, 0, sizeof(rs));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&x2, 0, sizeof(x2));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(&d, 0, sizeof(d));
memset(&b, 0, sizeof(b));
memset(&ct, 0, sizeof(ct));
memset(&c, 0, sizeof(c));
_hqrndstate_init(&rs, _state, ae_true);
_minnlcstate_init(&state, _state, ae_true);
_minnlcreport_init(&rep, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Bug description (fixed): sometimes on non-convex problems, when
* Lagrange coefficient for inequality constraint becomes small,
* algorithm performs VERY deep step into infeasible area (step is 1E50),
* which de-stabilizes it and prevents from converging back to feasible area.
*
* Very rare situation, but must be fixed with additional "convexifying" term.
* This test reproduces situation with convexified term turned off, then
* checks that introduction of term solves issue.
*
* We perform three kinds of tests:
* * with box inequality constraint
* * with linear inequality constraint
* * with nonlinear inequality constraint
*
* In all three cases we:
* * first time solve non-convex problem with artificially moved stabilizing
* point and decreased initial value of Lagrange multiplier.
* * second time we solve problem with good stabilizing point, but zero Lagrange multiplier
* * last time solve same problem, but with default settings
*/
aulits = 1;
maxits = 1;
rho = 100.0;
n = 1;
ae_vector_set_length(&x0, n, _state);
x0.ptr.p_double[0] = 0.0;
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
bndl.ptr.p_double[0] = 0.0;
bndu.ptr.p_double[0] = _state->v_posinf;
ae_matrix_set_length(&c, 1, 2, _state);
ae_vector_set_length(&ct, 1, _state);
c.ptr.pp_double[0][0] = 1.0;
c.ptr.pp_double[0][1] = 0.0;
ct.ptr.p_int[0] = 1;
for(ckind=0; ckind<=2; ckind++)
{
minnlccreate(n, &x0, &state, _state);
state.stabilizingpoint = -1.0E300;
state.initialinequalitymultiplier = 1.0E-12;
minnlcsetalgoaul(&state, rho, aulits, _state);
minnlcsetcond(&state, 0.0, maxits, _state);
if( ckind==0 )
{
minnlcsetbc(&state, &bndl, &bndu, _state);
}
if( ckind==1 )
{
minnlcsetlc(&state, &c, &ct, 1, _state);
}
if( ckind==2 )
{
minnlcsetnlc(&state, 0, 1, _state);
}
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = state.x.ptr.p_double[0]-ae_sqr(state.x.ptr.p_double[0], _state);
state.j.ptr.pp_double[0][0] = 1-2*state.x.ptr.p_double[0];
if( ckind==2 )
{
state.fi.ptr.p_double[1] = -state.x.ptr.p_double[0];
state.j.ptr.pp_double[1][0] = (double)(-1);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:5083");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(wereerrors, ae_fp_greater(x1.ptr.p_double[0],-1.0E6), __FILE__, __LINE__, "testminnlcunit.ap:5086");
minnlccreate(n, &x0, &state, _state);
state.stabilizingpoint = -1.0E2;
state.initialinequalitymultiplier = 1.0E-12;
minnlcsetalgoaul(&state, rho, aulits, _state);
minnlcsetcond(&state, 0.0, maxits, _state);
if( ckind==0 )
{
minnlcsetbc(&state, &bndl, &bndu, _state);
}
if( ckind==1 )
{
minnlcsetlc(&state, &c, &ct, 1, _state);
}
if( ckind==2 )
{
minnlcsetnlc(&state, 0, 1, _state);
}
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = state.x.ptr.p_double[0]-ae_sqr(state.x.ptr.p_double[0], _state);
state.j.ptr.pp_double[0][0] = 1-2*state.x.ptr.p_double[0];
if( ckind==2 )
{
state.fi.ptr.p_double[1] = -state.x.ptr.p_double[0];
state.j.ptr.pp_double[1][0] = (double)(-1);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:5115");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(wereerrors, ae_fp_less(x1.ptr.p_double[0],3*state.stabilizingpoint), __FILE__, __LINE__, "testminnlcunit.ap:5118");
minnlccreate(n, &x0, &state, _state);
minnlcsetalgoaul(&state, rho, aulits, _state);
minnlcsetcond(&state, 0.0, maxits, _state);
if( ckind==0 )
{
minnlcsetbc(&state, &bndl, &bndu, _state);
}
if( ckind==1 )
{
minnlcsetlc(&state, &c, &ct, 1, _state);
}
if( ckind==2 )
{
minnlcsetnlc(&state, 0, 1, _state);
}
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = state.x.ptr.p_double[0]-ae_sqr(state.x.ptr.p_double[0], _state);
state.j.ptr.pp_double[0][0] = 1-2*state.x.ptr.p_double[0];
if( ckind==2 )
{
state.fi.ptr.p_double[1] = -state.x.ptr.p_double[0];
state.j.ptr.pp_double[1][0] = (double)(-1);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:5145");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(wereerrors, ae_fp_less(x1.ptr.p_double[0],3*state.stabilizingpoint), __FILE__, __LINE__, "testminnlcunit.ap:5148");
}
/*
* This test checks report by E. Pozamantir. Relevant for SLP
* and related methods, but we test it for all algorithms.
*
* Description:
*
* The sequential linear programming solver performs warm-start
* at each iteration, i.e. it reuses previously found LP basis.
* However, when some initially non-zero Jacobian entries become
* exactly zero (possible with constraints which are nonsmooth
* at some distance from the boundary), our warm-start strategy
* may fail because warm-start basis becomes exactly degenerate.
*
* In order to test that this bug was fixed we solve carefully
* designed noisy test problem with Jacobian entries being randomly
* turned on and off. Simply being able to return from the solver
* without triggering critical exception is enough.
*/
for(solvertype=0; solvertype<=testminnlcunit_maxsolvertype; solvertype++)
{
for(n=6; n<=15; n++)
{
/*
* Setup problem
*/
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&d, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
d.ptr.p_double[i] = ae_sqr(hqrndnormal(&rs, _state), _state);
}
k = 1+hqrnduniformi(&rs, n/3, _state);
ae_matrix_set_length(&c, 2*k, n+1, _state);
for(i=0; i<=2*k-1; i++)
{
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
for(i=0; i<=k-1; i++)
{
c.ptr.pp_double[i][n] = (double)(0);
}
for(i=k; i<=2*k-1; i++)
{
c.ptr.pp_double[i][n] = 0.1+hqrnduniformr(&rs, _state);
}
/*
* Create solver and solve problem
*/
minnlccreate(n, &x0, &state, _state);
if( solvertype==0 )
{
minnlcsetalgoaul(&state, 200.0, 20, _state);
}
else
{
if( solvertype==1 )
{
minnlcsetalgoslp(&state, _state);
}
else
{
if( solvertype==2 )
{
minnlcsetalgosqp(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
minnlcsetcond(&state, 1.0E-7, 20, _state);
minnlcsetnlc(&state, k, k, _state);
while(minnlciteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(j=0; j<=n-1; j++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*d.ptr.p_double[j]*ae_sqr(state.x.ptr.p_double[j], _state);
state.j.ptr.pp_double[0][j] = d.ptr.p_double[j]*state.x.ptr.p_double[j];
}
for(i=0; i<=2*k-1; i++)
{
state.fi.ptr.p_double[1+i] = -c.ptr.pp_double[i][n];
for(j=0; j<=n-1; j++)
{
state.fi.ptr.p_double[1+i] = state.fi.ptr.p_double[1+i]+c.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.j.ptr.pp_double[1+i][j] = hqrnduniformi(&rs, 2, _state)*c.ptr.pp_double[i][j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnlcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:5235");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnlcunit.ap:5236");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
This function tests report of "non-C1" test #0 for task #0
given by matrix A.
On failure sets error flag.
*************************************************************************/
static void testminnlcunit_testoptguardc1test0reportfortask0(ae_bool* err,
optguardnonc1test0report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
double vv;
double va;
double vb;
ae_bool hasc1discontinuities;
if( rep->positive )
{
/*
* Check positive report, first checks
*/
ae_set_error_flag(err, rep->fidx!=0, __FILE__, __LINE__, "testminnlcunit.ap:5265");
ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testminnlcunit.ap:5266");
ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testminnlcunit.ap:5267");
ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testminnlcunit.ap:5268");
ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testminnlcunit.ap:5269");
ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testminnlcunit.ap:5270");
ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testminnlcunit.ap:5271");
ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testminnlcunit.ap:5272");
ae_set_error_flag(err, rep->f.cnt!=rep->cnt, __FILE__, __LINE__, "testminnlcunit.ap:5273");
ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:5274");
ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:5275");
ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testminnlcunit.ap:5276");
ae_set_error_flag(err, !isfinitevector(&rep->f, rep->cnt, _state), __FILE__, __LINE__, "testminnlcunit.ap:5277");
if( *err )
{
return;
}
/*
* Check consistency of Stp.
*/
for(k=0; k<=rep->cnt-2; k++)
{
ae_set_error_flag(err, ae_fp_greater_eq(rep->stp.ptr.p_double[k],rep->stp.ptr.p_double[k+1]), __FILE__, __LINE__, "testminnlcunit.ap:5285");
}
/*
* Check that interval [#StpIdxA,#StpIdxB] contains at least one discontinuity
*/
hasc1discontinuities = ae_false;
for(i=0; i<=n-1; i++)
{
va = (double)(0);
vb = (double)(0);
for(j=0; j<=n-1; j++)
{
va = va+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxa]);
vb = vb+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxb]);
}
hasc1discontinuities = hasc1discontinuities||ae_sign(va, _state)!=ae_sign(vb, _state);
}
ae_set_error_flag(err, !hasc1discontinuities, __FILE__, __LINE__, "testminnlcunit.ap:5302");
}
else
{
/*
* Check negative report: fields must be empty
*/
ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5309");
ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5310");
ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5311");
ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5312");
ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testminnlcunit.ap:5313");
ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5314");
ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5315");
ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5316");
ae_set_error_flag(err, rep->f.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5317");
}
}
/*************************************************************************
This function tests report of "non-C1" test #1 for task #0
given by matrix A.
On failure sets error flag.
*************************************************************************/
static void testminnlcunit_testoptguardc1test1reportfortask0(ae_bool* err,
optguardnonc1test1report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
double vv;
double va;
double vb;
ae_bool tooclose;
ae_bool hasc1discontinuities;
if( rep->positive )
{
/*
* Check positive report, first checks
*/
ae_set_error_flag(err, rep->fidx!=0, __FILE__, __LINE__, "testminnlcunit.ap:5345");
ae_set_error_flag(err, rep->vidx<0, __FILE__, __LINE__, "testminnlcunit.ap:5346");
ae_set_error_flag(err, rep->vidx>n, __FILE__, __LINE__, "testminnlcunit.ap:5347");
ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testminnlcunit.ap:5348");
ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testminnlcunit.ap:5349");
ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testminnlcunit.ap:5350");
ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testminnlcunit.ap:5351");
ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testminnlcunit.ap:5352");
ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testminnlcunit.ap:5353");
ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testminnlcunit.ap:5354");
ae_set_error_flag(err, rep->g.cnt!=rep->cnt, __FILE__, __LINE__, "testminnlcunit.ap:5355");
ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:5356");
ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:5357");
ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testminnlcunit.ap:5358");
ae_set_error_flag(err, !isfinitevector(&rep->g, rep->cnt, _state), __FILE__, __LINE__, "testminnlcunit.ap:5359");
if( *err )
{
return;
}
/*
* Check consistency of Stp
*/
for(k=0; k<=rep->cnt-2; k++)
{
ae_set_error_flag(err, ae_fp_greater_eq(rep->stp.ptr.p_double[k],rep->stp.ptr.p_double[k+1]), __FILE__, __LINE__, "testminnlcunit.ap:5367");
}
/*
* Check that interval [#StpIdxA,#StpIdxB] contains at least one discontinuity
*/
tooclose = ae_false;
hasc1discontinuities = ae_false;
for(i=0; i<=n-1; i++)
{
va = (double)(0);
vb = (double)(0);
for(j=0; j<=n-1; j++)
{
va = va+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxa]);
vb = vb+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxb]);
}
tooclose = (tooclose||ae_fp_less(ae_fabs(va, _state),1.0E-8))||ae_fp_less(ae_fabs(vb, _state),1.0E-8);
hasc1discontinuities = hasc1discontinuities||ae_sign(va, _state)!=ae_sign(vb, _state);
}
if( !tooclose )
{
ae_set_error_flag(err, !hasc1discontinuities, __FILE__, __LINE__, "testminnlcunit.ap:5387");
}
}
else
{
/*
* Check negative report: fields must be empty
*/
ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5394");
ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5395");
ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5396");
ae_set_error_flag(err, rep->vidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5397");
ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5398");
ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testminnlcunit.ap:5399");
ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5400");
ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5401");
ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5402");
ae_set_error_flag(err, rep->g.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5403");
}
}
/*************************************************************************
This function tests report of "non-C1" test #0 for task #1
given by matrix A.
On failure sets error flag.
*************************************************************************/
static void testminnlcunit_testoptguardc1test0reportfortask1(ae_bool* err,
optguardnonc1test0report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_int_t goodidx,
ae_state *_state)
{
if( rep->positive )
{
/*
* Check positive report, first checks
*/
ae_set_error_flag(err, rep->fidx==goodidx+1, __FILE__, __LINE__, "testminnlcunit.ap:5427");
ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testminnlcunit.ap:5428");
ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testminnlcunit.ap:5429");
ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testminnlcunit.ap:5430");
ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testminnlcunit.ap:5431");
ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testminnlcunit.ap:5432");
ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testminnlcunit.ap:5433");
ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testminnlcunit.ap:5434");
ae_set_error_flag(err, rep->f.cnt!=rep->cnt, __FILE__, __LINE__, "testminnlcunit.ap:5435");
ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:5436");
ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:5437");
ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testminnlcunit.ap:5438");
ae_set_error_flag(err, !isfinitevector(&rep->f, rep->cnt, _state), __FILE__, __LINE__, "testminnlcunit.ap:5439");
if( *err )
{
return;
}
}
else
{
/*
* Check negative report: fields must be empty
*/
ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5448");
ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5449");
ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5450");
ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5451");
ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testminnlcunit.ap:5452");
ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5453");
ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5454");
ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5455");
ae_set_error_flag(err, rep->f.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5456");
}
}
/*************************************************************************
This function tests report of "non-C1" test #1 for task #1 given by matrix A.
On failure sets error flag.
*************************************************************************/
static void testminnlcunit_testoptguardc1test1reportfortask1(ae_bool* err,
optguardnonc1test1report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_int_t goodidx,
ae_state *_state)
{
if( rep->positive )
{
/*
* Check positive report, first checks
*/
ae_set_error_flag(err, rep->fidx==goodidx+1, __FILE__, __LINE__, "testminnlcunit.ap:5479");
ae_set_error_flag(err, rep->vidx<0, __FILE__, __LINE__, "testminnlcunit.ap:5480");
ae_set_error_flag(err, rep->vidx>n, __FILE__, __LINE__, "testminnlcunit.ap:5481");
ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testminnlcunit.ap:5482");
ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testminnlcunit.ap:5483");
ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testminnlcunit.ap:5484");
ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testminnlcunit.ap:5485");
ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testminnlcunit.ap:5486");
ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testminnlcunit.ap:5487");
ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testminnlcunit.ap:5488");
ae_set_error_flag(err, rep->g.cnt!=rep->cnt, __FILE__, __LINE__, "testminnlcunit.ap:5489");
ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:5490");
ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testminnlcunit.ap:5491");
ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testminnlcunit.ap:5492");
ae_set_error_flag(err, !isfinitevector(&rep->g, rep->cnt, _state), __FILE__, __LINE__, "testminnlcunit.ap:5493");
if( *err )
{
return;
}
}
else
{
/*
* Check negative report: fields must be empty
*/
ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5502");
ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5503");
ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5504");
ae_set_error_flag(err, rep->vidx!=-1, __FILE__, __LINE__, "testminnlcunit.ap:5505");
ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5506");
ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testminnlcunit.ap:5507");
ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5508");
ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5509");
ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5510");
ae_set_error_flag(err, rep->g.cnt!=0, __FILE__, __LINE__, "testminnlcunit.ap:5511");
}
}
static ae_int_t testminbcunit_maxoptguardlevel = 1;
static void testminbcunit_calciip2(minbcstate* state,
ae_int_t n,
ae_int_t fk,
ae_state *_state);
static void testminbcunit_testfeasibility(ae_bool* feaserr,
ae_bool* converr,
ae_bool* interr,
ae_state *_state);
static void testminbcunit_testother(ae_bool* err, ae_state *_state);
static void testminbcunit_testpreconditioning(ae_bool* err,
ae_state *_state);
static void testminbcunit_testoptguard(ae_bool* wereerrors,
ae_state *_state);
static void testminbcunit_setrandompreconditioner(minbcstate* state,
ae_int_t n,
ae_int_t preckind,
ae_state *_state);
static void testminbcunit_testoptguardc1test0reportfortask0(ae_bool* err,
optguardnonc1test0report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state);
static void testminbcunit_testoptguardc1test1reportfortask0(ae_bool* err,
optguardnonc1test1report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state);
ae_bool testminbc(ae_bool silent, ae_state *_state)
{
ae_bool waserrors;
ae_bool feasibilityerrors;
ae_bool othererrors;
ae_bool precerrors;
ae_bool interrors;
ae_bool converrors;
ae_bool optguarderrors;
ae_bool result;
waserrors = ae_false;
feasibilityerrors = ae_false;
othererrors = ae_false;
precerrors = ae_false;
interrors = ae_false;
converrors = ae_false;
optguarderrors = ae_false;
testminbcunit_testfeasibility(&feasibilityerrors, &converrors, &interrors, _state);
testminbcunit_testother(&othererrors, _state);
testminbcunit_testpreconditioning(&precerrors, _state);
testminbcunit_testoptguard(&optguarderrors, _state);
/*
* end
*/
waserrors = ((((feasibilityerrors||othererrors)||converrors)||interrors)||precerrors)||optguarderrors;
if( !silent )
{
printf("TESTING BC OPTIMIZATION\n");
printf("FEASIBILITY PROPERTIES: ");
if( feasibilityerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("PRECONDITIONING: ");
if( precerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("OTHER PROPERTIES: ");
if( othererrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("CONVERGENCE PROPERTIES: ");
if( converrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("INTERNAL ERRORS: ");
if( interrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("OPTGUARD: ");
if( optguarderrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
return result;
}
/*************************************************************************
Calculate test function IIP2
f(x) = sum( ((i*i+1)^FK*x[i])^2, i=0..N-1)
It has high condition number which makes fast convergence unlikely without
good preconditioner.
*************************************************************************/
static void testminbcunit_calciip2(minbcstate* state,
ae_int_t n,
ae_int_t fk,
ae_state *_state)
{
ae_int_t i;
if( state->needfg )
{
state->f = (double)(0);
}
for(i=0; i<=n-1; i++)
{
if( state->needfg )
{
state->f = state->f+ae_pow((double)(i*i+1), (double)(2*fk), _state)*ae_sqr(state->x.ptr.p_double[i], _state);
state->g.ptr.p_double[i] = ae_pow((double)(i*i+1), (double)(2*fk), _state)*2*state->x.ptr.p_double[i];
}
}
}
/*************************************************************************
This function test feasibility properties.
It launches a sequence of problems and examines their solutions.
Most of the attention is directed towards feasibility properties,
although we make some quick checks to ensure that actual solution is found.
On failure sets FeasErr (or ConvErr, depending on failure type) to True,
or leaves it unchanged otherwise.
IntErr is set to True on internal errors (errors in the control flow).
*************************************************************************/
static void testminbcunit_testfeasibility(ae_bool* feaserr,
ae_bool* converr,
ae_bool* interr,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t pkind;
ae_int_t preckind;
ae_int_t passcount;
ae_int_t pass;
ae_int_t n;
ae_int_t nmax;
ae_int_t i;
ae_int_t p;
double v;
ae_vector bl;
ae_vector bu;
ae_vector x;
ae_vector g;
ae_vector x0;
ae_vector xc;
ae_vector xs;
ae_vector svdw;
ae_matrix csvdu;
ae_matrix svdvt;
minbcstate state;
double weakepsg;
minbcreport rep;
ae_int_t dkind;
double diffstep;
ae_frame_make(_state, &_frame_block);
memset(&bl, 0, sizeof(bl));
memset(&bu, 0, sizeof(bu));
memset(&x, 0, sizeof(x));
memset(&g, 0, sizeof(g));
memset(&x0, 0, sizeof(x0));
memset(&xc, 0, sizeof(xc));
memset(&xs, 0, sizeof(xs));
memset(&svdw, 0, sizeof(svdw));
memset(&csvdu, 0, sizeof(csvdu));
memset(&svdvt, 0, sizeof(svdvt));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
ae_vector_init(&bl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&g, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xs, 0, DT_REAL, _state, ae_true);
ae_vector_init(&svdw, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&csvdu, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&svdvt, 0, 0, DT_REAL, _state, ae_true);
_minbcstate_init(&state, _state, ae_true);
_minbcreport_init(&rep, _state, ae_true);
nmax = 5;
weakepsg = 1.0E-4;
passcount = 10;
for(pass=1; pass<=passcount; pass++)
{
/*
* Another simple problem:
* * bound constraints 0 <= x[i] <= 1
* * no linear constraints
* * preconditioner is chosen at random (we just want to be
* sure that preconditioning won't prevent us from converging
* to the feasible point):
* * unit preconditioner
* * random diagonal-based preconditioner
* * random scale-based preconditioner
* * F(x) = |x-x0|^P, where P={2,4} and x0 is randomly selected from [-1,+2]^N
* * with such simple boundaries and function it is easy to find
* analytic form of solution: S[i] = bound(x0[i], 0, 1)
* * we also check that both final solution and subsequent iterates
* are strictly feasible
*/
diffstep = 1.0E-6;
for(dkind=0; dkind<=1; dkind++)
{
for(preckind=0; preckind<=2; preckind++)
{
for(pkind=1; pkind<=2; pkind++)
{
for(n=1; n<=nmax; n++)
{
/*
* Generate X, BL, BU.
*/
p = 2*pkind;
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
bl.ptr.p_double[i] = (double)(0);
bu.ptr.p_double[i] = (double)(1);
x.ptr.p_double[i] = ae_randomreal(_state);
x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1;
}
/*
* Create and optimize
*/
if( dkind==0 )
{
minbccreate(n, &x, &state, _state);
}
if( dkind==1 )
{
minbccreatef(n, &x, diffstep, &state, _state);
}
minbcsetbc(&state, &bl, &bu, _state);
minbcsetcond(&state, weakepsg, 0.0, 0.0, 0, _state);
testminbcunit_setrandompreconditioner(&state, n, preckind, _state);
while(minbciteration(&state, _state))
{
if( state.needf||state.needfg )
{
state.f = (double)(0);
}
for(i=0; i<=n-1; i++)
{
if( state.needf||state.needfg )
{
state.f = state.f+ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p), _state);
}
if( state.needfg )
{
state.g.ptr.p_double[i] = p*ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state);
}
*feaserr = *feaserr||ae_fp_less(state.x.ptr.p_double[i],0.0);
*feaserr = *feaserr||ae_fp_greater(state.x.ptr.p_double[i],1.0);
}
}
minbcresults(&state, &x, &rep, _state);
if( rep.terminationtype<=0 )
{
*converr = ae_true;
ae_frame_leave(_state);
return;
}
/*
* * compare solution with analytic one
* * check feasibility
*/
v = 0.0;
for(i=0; i<=n-1; i++)
{
if( ae_fp_greater(x.ptr.p_double[i],(double)(0))&&ae_fp_less(x.ptr.p_double[i],(double)(1)) )
{
v = v+ae_sqr(p*ae_pow(x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state), _state);
}
*feaserr = *feaserr||ae_fp_less(x.ptr.p_double[i],0.0);
*feaserr = *feaserr||ae_fp_greater(x.ptr.p_double[i],1.0);
}
*converr = *converr||ae_fp_greater(ae_sqrt(v, _state),weakepsg);
}
}
}
}
/*
* Same as previous problem, but with minor modifications:
* * some bound constraints are 0<=x[i]<=1, some are Ci=x[i]=Ci
* * no linear constraints
* * preconditioner is chosen at random (we just want to be
* sure that preconditioning won't prevent us from converging
* to the feasible point):
* * unit preconditioner
* * random diagonal-based preconditioner
* * random scale-based preconditioner
* * F(x) = |x-x0|^P, where P={2,4} and x0 is randomly selected from [-1,+2]^N
* * with such simple boundaries and function it is easy to find
* analytic form of solution: S[i] = bound(x0[i], 0, 1)
* * we also check that both final solution and subsequent iterates
* are strictly feasible
*/
diffstep = 1.0E-6;
for(dkind=0; dkind<=1; dkind++)
{
for(preckind=0; preckind<=2; preckind++)
{
for(pkind=1; pkind<=2; pkind++)
{
for(n=1; n<=nmax; n++)
{
/*
* Generate X, BL, BU.
*/
p = 2*pkind;
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
bl.ptr.p_double[i] = (double)(0);
bu.ptr.p_double[i] = (double)(1);
}
else
{
bl.ptr.p_double[i] = ae_randomreal(_state);
bu.ptr.p_double[i] = bl.ptr.p_double[i];
}
x.ptr.p_double[i] = ae_randomreal(_state);
x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1;
}
/*
* Create and optimize
*/
if( dkind==0 )
{
minbccreate(n, &x, &state, _state);
}
if( dkind==1 )
{
minbccreatef(n, &x, diffstep, &state, _state);
}
minbcsetbc(&state, &bl, &bu, _state);
minbcsetcond(&state, weakepsg, 0.0, 0.0, 0, _state);
testminbcunit_setrandompreconditioner(&state, n, preckind, _state);
while(minbciteration(&state, _state))
{
if( state.needf||state.needfg )
{
state.f = (double)(0);
}
for(i=0; i<=n-1; i++)
{
if( state.needf||state.needfg )
{
state.f = state.f+ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p), _state);
}
if( state.needfg )
{
state.g.ptr.p_double[i] = p*ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state);
}
*feaserr = *feaserr||ae_fp_less(state.x.ptr.p_double[i],bl.ptr.p_double[i]);
*feaserr = *feaserr||ae_fp_greater(state.x.ptr.p_double[i],bu.ptr.p_double[i]);
}
}
minbcresults(&state, &x, &rep, _state);
if( rep.terminationtype<=0 )
{
*converr = ae_true;
ae_frame_leave(_state);
return;
}
/*
* * compare solution with analytic one
* * check feasibility
*/
v = 0.0;
for(i=0; i<=n-1; i++)
{
if( ae_fp_greater(x.ptr.p_double[i],bl.ptr.p_double[i])&&ae_fp_less(x.ptr.p_double[i],bu.ptr.p_double[i]) )
{
v = v+ae_sqr(p*ae_pow(x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state), _state);
}
*feaserr = *feaserr||ae_fp_less(x.ptr.p_double[i],bl.ptr.p_double[i]);
*feaserr = *feaserr||ae_fp_greater(x.ptr.p_double[i],bu.ptr.p_double[i]);
}
*converr = *converr||ae_fp_greater(ae_sqrt(v, _state),weakepsg);
}
}
}
}
/*
* Infeasible problem:
* * all bound constraints are 0 <= x[i] <= 1 except for one
* * that one is 0 >= x[i] >= 1
* * no linear constraints
* * preconditioner is chosen at random (we just want to be
* sure that preconditioning won't prevent us from detecting
* infeasible point):
* * unit preconditioner
* * random diagonal-based preconditioner
* * random scale-based preconditioner
* * F(x) = |x-x0|^P, where P={2,4} and x0 is randomly selected from [-1,+2]^N
* * algorithm must return correct error code on such problem
*/
for(preckind=0; preckind<=2; preckind++)
{
for(pkind=1; pkind<=2; pkind++)
{
for(n=1; n<=nmax; n++)
{
/*
* Generate X, BL, BU.
*/
p = 2*pkind;
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
bl.ptr.p_double[i] = (double)(0);
bu.ptr.p_double[i] = (double)(1);
x.ptr.p_double[i] = ae_randomreal(_state);
x0.ptr.p_double[i] = 3*ae_randomreal(_state)-1;
}
i = ae_randominteger(n, _state);
bl.ptr.p_double[i] = (double)(1);
bu.ptr.p_double[i] = (double)(0);
/*
* Create and optimize
*/
minbccreate(n, &x, &state, _state);
minbcsetbc(&state, &bl, &bu, _state);
minbcsetcond(&state, weakepsg, 0.0, 0.0, 0, _state);
testminbcunit_setrandompreconditioner(&state, n, preckind, _state);
while(minbciteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p), _state);
state.g.ptr.p_double[i] = p*ae_pow(state.x.ptr.p_double[i]-x0.ptr.p_double[i], (double)(p-1), _state);
}
continue;
}
/*
* Unknown protocol specified
*/
*interr = ae_true;
ae_frame_leave(_state);
return;
}
minbcresults(&state, &x, &rep, _state);
*feaserr = *feaserr||rep.terminationtype!=-3;
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
This function additional properties.
On failure sets Err to True (leaves it unchanged otherwise)
*************************************************************************/
static void testminbcunit_testother(ae_bool* err, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t passcount;
ae_int_t pass;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_vector bl;
ae_vector bu;
ae_vector x;
ae_vector xf;
ae_vector x0;
ae_vector x1;
ae_vector b;
ae_vector xlast;
ae_vector a;
ae_vector s;
ae_vector h;
ae_matrix fulla;
double fprev;
double xprev;
double stpmax;
double v;
ae_int_t pkind;
ae_int_t ckind;
ae_int_t mkind;
double vc;
double vm;
minbcstate state;
double epsx;
double epsg;
double eps;
double tmpeps;
minbcreport rep;
double diffstep;
ae_int_t dkind;
ae_bool wasf;
ae_bool wasfg;
double r;
hqrndstate rs;
ae_int_t spoiliteration;
ae_int_t stopiteration;
ae_int_t spoilvar;
double spoilval;
double ss;
ae_int_t stopcallidx;
ae_int_t callidx;
ae_int_t maxits;
ae_bool terminationrequested;
ae_frame_make(_state, &_frame_block);
memset(&bl, 0, sizeof(bl));
memset(&bu, 0, sizeof(bu));
memset(&x, 0, sizeof(x));
memset(&xf, 0, sizeof(xf));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&b, 0, sizeof(b));
memset(&xlast, 0, sizeof(xlast));
memset(&a, 0, sizeof(a));
memset(&s, 0, sizeof(s));
memset(&h, 0, sizeof(h));
memset(&fulla, 0, sizeof(fulla));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&rs, 0, sizeof(rs));
ae_vector_init(&bl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xf, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xlast, 0, DT_REAL, _state, ae_true);
ae_vector_init(&a, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&h, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&fulla, 0, 0, DT_REAL, _state, ae_true);
_minbcstate_init(&state, _state, ae_true);
_minbcreport_init(&rep, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
epsx = 1.0E-4;
epsg = 1.0E-8;
passcount = 10;
/*
* Try to reproduce bug 570 (optimizer hangs on problems where it is required
* to perform very small step - less than 1E-50 - in order to activate constraints).
*
* The problem being solved is:
*
* min x[0]+x[1]+...+x[n-1]
*
* subject to
*
* x[i]>=0, for i=0..n-1
*
* with initial point
*
* x[0] = 1.0E-100, x[1]=x[2]=...=0.5
*
* We try to reproduce this problem in different settings:
* * boundary-only constraints - we test that completion code is positive,
* and all x[] are EXACTLY zero
* * boundary constraints posed as general linear ones - we test that
* completion code is positive, and all x[] are APPROXIMATELY zero.
*/
n = 10;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 0.5;
bl.ptr.p_double[i] = 0.0;
bu.ptr.p_double[i] = _state->v_posinf;
}
x.ptr.p_double[0] = 1.0E-100;
minbccreate(n, &x, &state, _state);
minbcsetbc(&state, &bl, &bu, _state);
minbcsetcond(&state, (double)(0), (double)(0), (double)(0), 2*n, _state);
while(minbciteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+state.x.ptr.p_double[i];
state.g.ptr.p_double[i] = 1.0;
}
}
}
minbcresults(&state, &xf, &rep, _state);
ae_set_error_flag(err, rep.terminationtype<=0, __FILE__, __LINE__, "testminbcunit.ap:494");
if( rep.terminationtype>0 )
{
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(err, ae_fp_neq(xf.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testminbcunit.ap:497");
}
}
/*
* Test reports:
* * first value must be starting point
* * last value must be last point
*/
for(pass=1; pass<=passcount; pass++)
{
n = 50;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&xlast, n, _state);
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = (double)(10);
bl.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
bu.ptr.p_double[i] = _state->v_posinf;
}
minbccreate(n, &x, &state, _state);
minbcsetbc(&state, &bl, &bu, _state);
minbcsetcond(&state, 1.0E-64, (double)(0), (double)(0), 10, _state);
minbcsetxrep(&state, ae_true, _state);
fprev = ae_maxrealnumber;
while(minbciteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+ae_sqr((1+i)*state.x.ptr.p_double[i], _state);
state.g.ptr.p_double[i] = 2*(1+i)*state.x.ptr.p_double[i];
}
}
if( state.xupdated )
{
if( ae_fp_eq(fprev,ae_maxrealnumber) )
{
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(err, ae_fp_neq(state.x.ptr.p_double[i],x.ptr.p_double[i]), __FILE__, __LINE__, "testminbcunit.ap:538");
}
}
fprev = state.f;
ae_v_move(&xlast.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
}
}
minbcresults(&state, &x, &rep, _state);
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(err, ae_fp_neq(x.ptr.p_double[i],xlast.ptr.p_double[i]), __FILE__, __LINE__, "testminbcunit.ap:545");
}
}
/*
* Test differentiation vs. analytic gradient
* (first one issues NeedF requests, second one issues NeedFG requests)
*/
for(pass=1; pass<=passcount; pass++)
{
n = 10;
diffstep = 1.0E-6;
for(dkind=0; dkind<=1; dkind++)
{
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&xlast, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = (double)(1);
}
if( dkind==0 )
{
minbccreate(n, &x, &state, _state);
}
if( dkind==1 )
{
minbccreatef(n, &x, diffstep, &state, _state);
}
minbcsetcond(&state, 1.0E-6, (double)(0), epsx, 0, _state);
wasf = ae_false;
wasfg = ae_false;
while(minbciteration(&state, _state))
{
if( state.needf||state.needfg )
{
state.f = (double)(0);
}
for(i=0; i<=n-1; i++)
{
if( state.needf||state.needfg )
{
state.f = state.f+ae_sqr((1+i)*state.x.ptr.p_double[i], _state);
}
if( state.needfg )
{
state.g.ptr.p_double[i] = 2*(1+i)*state.x.ptr.p_double[i];
}
}
wasf = wasf||state.needf;
wasfg = wasfg||state.needfg;
}
minbcresults(&state, &x, &rep, _state);
if( dkind==0 )
{
ae_set_error_flag(err, wasf||!wasfg, __FILE__, __LINE__, "testminbcunit.ap:585");
}
if( dkind==1 )
{
ae_set_error_flag(err, !wasf||wasfg, __FILE__, __LINE__, "testminbcunit.ap:587");
}
}
}
/*
* Test that numerical differentiation uses scaling.
*
* In order to test that we solve simple optimization
* problem: min(x^2) with initial x equal to 0.0.
*
* We choose random DiffStep and S, then we check that
* optimizer evaluates function at +-DiffStep*S only.
*/
for(pass=1; pass<=passcount; pass++)
{
ae_vector_set_length(&x, 1, _state);
ae_vector_set_length(&s, 1, _state);
diffstep = ae_randomreal(_state)*1.0E-6;
s.ptr.p_double[0] = ae_exp(ae_randomreal(_state)*4-2, _state);
x.ptr.p_double[0] = (double)(0);
minbccreatef(1, &x, diffstep, &state, _state);
minbcsetcond(&state, 1.0E-6, (double)(0), epsx, 0, _state);
minbcsetscale(&state, &s, _state);
v = (double)(0);
while(minbciteration(&state, _state))
{
state.f = ae_sqr(state.x.ptr.p_double[0], _state);
v = ae_maxreal(v, ae_fabs(state.x.ptr.p_double[0], _state), _state);
}
minbcresults(&state, &x, &rep, _state);
r = v/(s.ptr.p_double[0]*diffstep);
ae_set_error_flag(err, ae_fp_greater(ae_fabs(ae_log(r, _state), _state),ae_log(1+1000*ae_machineepsilon, _state)), __FILE__, __LINE__, "testminbcunit.ap:618");
}
/*
* Test stpmax
*/
for(pass=1; pass<=passcount; pass++)
{
n = 1;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
x.ptr.p_double[0] = (double)(100);
bl.ptr.p_double[0] = 2*ae_randomreal(_state)-1;
bu.ptr.p_double[0] = _state->v_posinf;
stpmax = 0.05+0.05*ae_randomreal(_state);
minbccreate(n, &x, &state, _state);
minbcsetbc(&state, &bl, &bu, _state);
minbcsetcond(&state, epsg, (double)(0), epsx, 0, _state);
minbcsetxrep(&state, ae_true, _state);
minbcsetstpmax(&state, stpmax, _state);
xprev = x.ptr.p_double[0];
while(minbciteration(&state, _state))
{
if( state.needfg )
{
state.f = ae_exp(state.x.ptr.p_double[0], _state)+ae_exp(-state.x.ptr.p_double[0], _state);
state.g.ptr.p_double[0] = ae_exp(state.x.ptr.p_double[0], _state)-ae_exp(-state.x.ptr.p_double[0], _state);
ae_set_error_flag(err, ae_fp_greater(ae_fabs(state.x.ptr.p_double[0]-xprev, _state),(1+ae_sqrt(ae_machineepsilon, _state))*stpmax), __FILE__, __LINE__, "testminbcunit.ap:646");
}
if( state.xupdated )
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(state.x.ptr.p_double[0]-xprev, _state),(1+ae_sqrt(ae_machineepsilon, _state))*stpmax), __FILE__, __LINE__, "testminbcunit.ap:650");
xprev = state.x.ptr.p_double[0];
}
}
}
/*
* Ability to solve problems with function which is unbounded from below
*/
for(pass=1; pass<=passcount; pass++)
{
n = 1;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
bl.ptr.p_double[0] = 4*ae_randomreal(_state)+1;
bu.ptr.p_double[0] = bl.ptr.p_double[0]+1;
x.ptr.p_double[0] = 0.5*(bl.ptr.p_double[0]+bu.ptr.p_double[0]);
minbccreate(n, &x, &state, _state);
minbcsetbc(&state, &bl, &bu, _state);
minbcsetcond(&state, epsg, (double)(0), epsx, 0, _state);
while(minbciteration(&state, _state))
{
if( state.needfg )
{
state.f = -1.0E8*ae_sqr(state.x.ptr.p_double[0], _state);
state.g.ptr.p_double[0] = -2.0E8*state.x.ptr.p_double[0];
}
}
minbcresults(&state, &x, &rep, _state);
ae_set_error_flag(err, ae_fp_greater(ae_fabs(x.ptr.p_double[0]-bu.ptr.p_double[0], _state),epsx), __FILE__, __LINE__, "testminbcunit.ap:680");
}
/*
* Test correctness of the scaling:
* * initial point is random point from [+1,+2]^N
* * f(x) = SUM(A[i]*x[i]^4), C[i] is random from [0.01,100]
* * function is EFFECTIVELY unconstrained; it has formal constraints,
* but they are inactive at the solution; we try different variants
* in order to explore different control paths of the optimizer:
* 0) absense of constraints
* 1) bound constraints -100000<=x[i]<=100000
* * we use random scaling matrix
* * we test different variants of the preconditioning:
* 0) unit preconditioner
* 1) random diagonal from [0.01,100]
* 2) scale preconditioner
* * we set very stringent stopping conditions
* * and we test that in the extremum stopping conditions are
* satisfied subject to the current scaling coefficients.
*/
for(pass=1; pass<=passcount; pass++)
{
tmpeps = 1.0E-5;
for(n=1; n<=10; n++)
{
for(ckind=0; ckind<=1; ckind++)
{
for(pkind=0; pkind<=2; pkind++)
{
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&a, n, _state);
ae_vector_set_length(&s, n, _state);
ae_vector_set_length(&h, n, _state);
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = ae_randomreal(_state)+1;
bl.ptr.p_double[i] = (double)(-100000);
bu.ptr.p_double[i] = (double)(100000);
a.ptr.p_double[i] = ae_exp(ae_log((double)(10), _state)*(2*ae_randomreal(_state)-1), _state);
s.ptr.p_double[i] = ae_exp(ae_log((double)(10), _state)*(2*ae_randomreal(_state)-1), _state);
h.ptr.p_double[i] = ae_exp(ae_log((double)(10), _state)*(2*ae_randomreal(_state)-1), _state);
}
minbccreate(n, &x, &state, _state);
if( ckind==1 )
{
minbcsetbc(&state, &bl, &bu, _state);
}
if( pkind==1 )
{
minbcsetprecdiag(&state, &h, _state);
}
if( pkind==2 )
{
minbcsetprecscale(&state, _state);
}
minbcsetcond(&state, tmpeps, (double)(0), (double)(0), 0, _state);
minbcsetscale(&state, &s, _state);
while(minbciteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+a.ptr.p_double[i]*ae_sqr(state.x.ptr.p_double[i], _state);
state.g.ptr.p_double[i] = 2*a.ptr.p_double[i]*state.x.ptr.p_double[i];
}
}
}
minbcresults(&state, &x, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminbcunit.ap:747");
ae_frame_leave(_state);
return;
}
v = (double)(0);
for(i=0; i<=n-1; i++)
{
v = v+ae_sqr(s.ptr.p_double[i]*2*a.ptr.p_double[i]*x.ptr.p_double[i], _state);
}
v = ae_sqrt(v, _state);
ae_set_error_flag(err, ae_fp_greater(v,tmpeps), __FILE__, __LINE__, "testminbcunit.ap:754");
}
}
}
}
/*
* Check correctness of the "trimming".
*
* Trimming is a technique which is used to help algorithm
* cope with unbounded functions. In order to check this
* technique we will try to solve following optimization
* problem:
*
* min f(x) subject to no constraints on X
* { 1/(1-x) + 1/(1+x) + c*x, if -0.999999=0.999999
*
* where c is either 1.0 or 1.0E+4, M is either 1.0E8, 1.0E20 or +INF
* (we try different combinations)
*/
for(pass=1; pass<=passcount; pass++)
{
for(ckind=0; ckind<=1; ckind++)
{
for(mkind=0; mkind<=2; mkind++)
{
/*
* Choose c and M
*/
vc = (double)(1);
vm = (double)(1);
if( ckind==0 )
{
vc = 1.0;
}
if( ckind==1 )
{
vc = 1.0E+4;
}
if( mkind==0 )
{
vm = 1.0E+8;
}
if( mkind==1 )
{
vm = 1.0E+20;
}
if( mkind==2 )
{
vm = _state->v_posinf;
}
/*
* Create optimizer, solve optimization problem
*/
epsg = 1.0E-6*vc;
ae_vector_set_length(&x, 1, _state);
x.ptr.p_double[0] = 0.0;
minbccreate(1, &x, &state, _state);
minbcsetcond(&state, epsg, (double)(0), (double)(0), 0, _state);
while(minbciteration(&state, _state))
{
if( state.needfg )
{
if( ae_fp_less(-0.999999,state.x.ptr.p_double[0])&&ae_fp_less(state.x.ptr.p_double[0],0.999999) )
{
state.f = 1/(1-state.x.ptr.p_double[0])+1/(1+state.x.ptr.p_double[0])+vc*state.x.ptr.p_double[0];
state.g.ptr.p_double[0] = 1/ae_sqr(1-state.x.ptr.p_double[0], _state)-1/ae_sqr(1+state.x.ptr.p_double[0], _state)+vc;
}
else
{
state.f = vm;
state.g.ptr.p_double[0] = (double)(0);
}
}
}
minbcresults(&state, &x, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminbcunit.ap:822");
ae_frame_leave(_state);
return;
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(1/ae_sqr(1-x.ptr.p_double[0], _state)-1/ae_sqr(1+x.ptr.p_double[0], _state)+vc, _state),epsg), __FILE__, __LINE__, "testminbcunit.ap:825");
}
}
}
/*
* Test behaviour on noisy functions.
*
* Consider following problem:
* * f(x,y) = (x+1)^2 + (y+1)^2 + 10000*MachineEpsilon*RandomReal()
* * boundary constraints x>=0, y>=0
* * starting point (x0,y0)=(10*MachineEpsilon,1.0)
*
* Such problem contains small numerical noise. Without noise its
* solution is (xs,ys)=(0,0), which is easy to find. However, presence
* of the noise makes it hard to solve:
* * noisy f(x,y) is monotonically decreasing only when we perform
* steps orders of magnitude larger than 10000*MachineEpsilon
* * at small scales f(x,y) is non-monotonic and non-convex
* * however, our first step must be done towards
* (x1,y1) = (0,1-some_small_value), and length of such step is
* many times SMALLER than 10000*MachineEpsilon
* * second step, from (x1,y1) to (xs,ys), will be large enough to
* ignore numerical noise, so the only problem is to perform
* first step
*
* Naive implementation of BC should fail sometimes (sometimes -
* due to non-deterministic nature of noise) on such problem. However,
* our improved implementation should solve it correctly. We test
* several variations of inner stopping criteria.
*/
for(pass=1; pass<=passcount; pass++)
{
eps = 1.0E-9;
ae_vector_set_length(&x, 2, _state);
ae_vector_set_length(&bl, 2, _state);
ae_vector_set_length(&bu, 2, _state);
x.ptr.p_double[0] = 10*ae_machineepsilon;
x.ptr.p_double[1] = 1.0;
bl.ptr.p_double[0] = 0.0;
bu.ptr.p_double[0] = _state->v_posinf;
bl.ptr.p_double[1] = 0.0;
bu.ptr.p_double[1] = _state->v_posinf;
for(ckind=0; ckind<=2; ckind++)
{
minbccreate(2, &x, &state, _state);
minbcsetbc(&state, &bl, &bu, _state);
if( ckind==0 )
{
minbcsetcond(&state, eps, (double)(0), (double)(0), 0, _state);
}
if( ckind==1 )
{
minbcsetcond(&state, (double)(0), eps, (double)(0), 0, _state);
}
if( ckind==2 )
{
minbcsetcond(&state, (double)(0), (double)(0), eps, 0, _state);
}
while(minbciteration(&state, _state))
{
if( state.needfg )
{
state.f = ae_sqr(state.x.ptr.p_double[0]+1, _state)+ae_sqr(state.x.ptr.p_double[1]+1, _state)+10000*ae_machineepsilon*ae_randomreal(_state);
state.g.ptr.p_double[0] = 2*(state.x.ptr.p_double[0]+1);
state.g.ptr.p_double[1] = 2*(state.x.ptr.p_double[1]+1);
}
}
minbcresults(&state, &xf, &rep, _state);
if( (rep.terminationtype<=0||ae_fp_neq(xf.ptr.p_double[0],(double)(0)))||ae_fp_neq(xf.ptr.p_double[1],(double)(0)) )
{
ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminbcunit.ap:889");
ae_frame_leave(_state);
return;
}
}
}
/*
* Deterministic variation of the previous problem.
*
* Consider following problem:
* * boundary constraints x>=0, y>=0
* * starting point (x0,y0)=(10*MachineEpsilon,1.0)
* / (x+1)^2 + (y+1)^2, for (x,y)<>(x0,y0)
* * f(x,y) = |
* \ (x+1)^2 + (y+1)^2 - 0.1, for (x,y)=(x0,y0)
*
* Such problem contains deterministic numerical noise (-0.1 at
* starting point). Without noise its solution is easy to find.
* However, presence of the noise makes it hard to solve:
* * our first step must be done towards (x1,y1) = (0,1-some_small_value),
* but such step will increase function valye by approximately 0.1 -
* instead of decreasing it.
*
* Naive implementation of BC should fail on such problem. However,
* our improved implementation should solve it correctly. We test
* several variations of inner stopping criteria.
*/
for(pass=1; pass<=passcount; pass++)
{
eps = 1.0E-9;
ae_vector_set_length(&x, 2, _state);
ae_vector_set_length(&bl, 2, _state);
ae_vector_set_length(&bu, 2, _state);
x.ptr.p_double[0] = 10*ae_machineepsilon;
x.ptr.p_double[1] = 1.0;
bl.ptr.p_double[0] = 0.0;
bu.ptr.p_double[0] = _state->v_posinf;
bl.ptr.p_double[1] = 0.0;
bu.ptr.p_double[1] = _state->v_posinf;
for(ckind=0; ckind<=2; ckind++)
{
minbccreate(2, &x, &state, _state);
minbcsetbc(&state, &bl, &bu, _state);
if( ckind==0 )
{
minbcsetcond(&state, eps, (double)(0), (double)(0), 0, _state);
}
if( ckind==1 )
{
minbcsetcond(&state, (double)(0), eps, (double)(0), 0, _state);
}
if( ckind==2 )
{
minbcsetcond(&state, (double)(0), (double)(0), eps, 0, _state);
}
while(minbciteration(&state, _state))
{
if( state.needfg )
{
state.f = ae_sqr(state.x.ptr.p_double[0]+1, _state)+ae_sqr(state.x.ptr.p_double[1]+1, _state);
if( ae_fp_eq(state.x.ptr.p_double[0],x.ptr.p_double[0])&&ae_fp_eq(state.x.ptr.p_double[1],x.ptr.p_double[1]) )
{
state.f = state.f-0.1;
}
state.g.ptr.p_double[0] = 2*(state.x.ptr.p_double[0]+1);
state.g.ptr.p_double[1] = 2*(state.x.ptr.p_double[1]+1);
}
}
minbcresults(&state, &xf, &rep, _state);
if( (rep.terminationtype<=0||ae_fp_neq(xf.ptr.p_double[0],(double)(0)))||ae_fp_neq(xf.ptr.p_double[1],(double)(0)) )
{
ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testminbcunit.ap:952");
ae_frame_leave(_state);
return;
}
}
}
/*
* Test integrity checks for NAN/INF:
* * algorithm solves optimization problem, which is normal for some time (quadratic)
* * after 5-th step we choose random component of gradient and consistently spoil
* it by NAN or INF.
* * we check that correct termination code is returned (-8)
*/
n = 100;
for(pass=1; pass<=10; pass++)
{
spoiliteration = 5;
stopiteration = 8;
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
/*
* Gradient can be spoiled by +INF, -INF, NAN
*/
spoilvar = hqrnduniformi(&rs, n, _state);
i = hqrnduniformi(&rs, 3, _state);
spoilval = _state->v_nan;
if( i==0 )
{
spoilval = _state->v_neginf;
}
if( i==1 )
{
spoilval = _state->v_posinf;
}
}
else
{
/*
* Function value can be spoiled only by NAN
* (+INF can be recognized as legitimate value during optimization)
*/
spoilvar = -1;
spoilval = _state->v_nan;
}
spdmatrixrndcond(n, 1.0E5, &fulla, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
minbccreate(n, &x0, &state, _state);
minbcsetcond(&state, 0.0, 0.0, 0.0, stopiteration, _state);
minbcsetxrep(&state, ae_true, _state);
k = -1;
while(minbciteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.g.ptr.p_double[i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.f = state.f+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.g.ptr.p_double[i] = state.g.ptr.p_double[i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
if( k>=spoiliteration )
{
if( spoilvar<0 )
{
state.f = spoilval;
}
else
{
state.g.ptr.p_double[spoilvar] = spoilval;
}
}
continue;
}
if( state.xupdated )
{
inc(&k, _state);
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minbcresults(&state, &x1, &rep, _state);
ae_set_error_flag(err, rep.terminationtype!=-8, __FILE__, __LINE__, "testminbcunit.ap:1037");
}
/*
* Check algorithm ability to handle request for termination:
* * to terminate with correct return code = 8
* * to return point which was "current" at the moment of termination
*
* NOTE: we solve problem with "corrupted" preconditioner which makes it hard
* to converge in less than StopCallIdx iterations
*/
for(pass=1; pass<=50; pass++)
{
n = 3;
ss = (double)(100);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&xlast, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 6+ae_randomreal(_state);
}
ae_vector_set_length(&s, 3, _state);
s.ptr.p_double[0] = 0.00001;
s.ptr.p_double[1] = 0.00001;
s.ptr.p_double[2] = 10000.0;
stopcallidx = ae_randominteger(20, _state);
maxits = 25;
minbccreate(n, &x, &state, _state);
minbcsetcond(&state, (double)(0), (double)(0), (double)(0), maxits, _state);
minbcsetxrep(&state, ae_true, _state);
minbcsetprecdiag(&state, &s, _state);
callidx = 0;
terminationrequested = ae_false;
ae_v_move(&xlast.ptr.p_double[0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1));
while(minbciteration(&state, _state))
{
if( state.needfg )
{
state.f = ss*ae_sqr(ae_exp(state.x.ptr.p_double[0], _state)-2, _state)+ae_sqr(state.x.ptr.p_double[1], _state)+ae_sqr(state.x.ptr.p_double[2]-state.x.ptr.p_double[0], _state);
state.g.ptr.p_double[0] = 2*ss*(ae_exp(state.x.ptr.p_double[0], _state)-2)*ae_exp(state.x.ptr.p_double[0], _state)+2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0])*(-1);
state.g.ptr.p_double[1] = 2*state.x.ptr.p_double[1];
state.g.ptr.p_double[2] = 2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0]);
if( callidx==stopcallidx )
{
minbcrequesttermination(&state, _state);
terminationrequested = ae_true;
}
inc(&callidx, _state);
continue;
}
if( state.xupdated )
{
if( !terminationrequested )
{
ae_v_move(&xlast.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minbcresults(&state, &x, &rep, _state);
ae_set_error_flag(err, rep.terminationtype!=8, __FILE__, __LINE__, "testminbcunit.ap:1095");
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(err, ae_fp_neq(x.ptr.p_double[i],xlast.ptr.p_double[i]), __FILE__, __LINE__, "testminbcunit.ap:1097");
}
}
ae_frame_leave(_state);
}
/*************************************************************************
This function tests preconditioning
On failure sets Err to True (leaves it unchanged otherwise)
*************************************************************************/
static void testminbcunit_testpreconditioning(ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t pass;
ae_int_t n;
ae_vector x;
ae_vector x0;
ae_int_t i;
ae_int_t k;
ae_matrix v;
ae_vector bl;
ae_vector bu;
ae_vector vd;
ae_vector d;
ae_vector units;
ae_vector s;
ae_int_t cntb1;
ae_int_t cntb2;
ae_int_t cntg1;
ae_int_t cntg2;
double epsg;
ae_vector diagh;
minbcstate state;
minbcreport rep;
ae_int_t ckind;
ae_int_t fk;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&x0, 0, sizeof(x0));
memset(&v, 0, sizeof(v));
memset(&bl, 0, sizeof(bl));
memset(&bu, 0, sizeof(bu));
memset(&vd, 0, sizeof(vd));
memset(&d, 0, sizeof(d));
memset(&units, 0, sizeof(units));
memset(&s, 0, sizeof(s));
memset(&diagh, 0, sizeof(diagh));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&vd, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&units, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&diagh, 0, DT_REAL, _state, ae_true);
_minbcstate_init(&state, _state, ae_true);
_minbcreport_init(&rep, _state, ae_true);
/*
* Preconditioner test 1.
*
* If
* * B1 is default preconditioner with unit scale
* * G1 is diagonal preconditioner based on approximate diagonal of Hessian matrix
* * B2 is default preconditioner with non-unit scale S[i]=1/sqrt(h[i])
* * G2 is scale-based preconditioner with non-unit scale S[i]=1/sqrt(h[i])
* then B1 is worse than G1, B2 is worse than G2.
* "Worse" means more iterations to converge.
*
* Test problem setup:
* * f(x) = sum( ((i*i+1)*x[i])^2, i=0..N-1)
* * constraints:
* 0) absent
* 1) box
*
* N - problem size
* K - number of repeated passes (should be large enough to average out random factors)
*/
k = 100;
epsg = 1.0E-8;
for(n=10; n<=10; n++)
{
for(ckind=0; ckind<=1; ckind++)
{
fk = 1;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&units, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = (double)(0);
units.ptr.p_double[i] = (double)(1);
}
minbccreate(n, &x, &state, _state);
minbcsetcond(&state, epsg, 0.0, 0.0, 0, _state);
if( ckind==1 )
{
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
for(i=0; i<=n-1; i++)
{
bl.ptr.p_double[i] = (double)(-1);
bu.ptr.p_double[i] = (double)(1);
}
minbcsetbc(&state, &bl, &bu, _state);
}
/*
* Test it with default preconditioner VS. perturbed diagonal preconditioner
*/
minbcsetprecdefault(&state, _state);
minbcsetscale(&state, &units, _state);
cntb1 = 0;
for(pass=0; pass<=k-1; pass++)
{
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
minbcrestartfrom(&state, &x, _state);
while(minbciteration(&state, _state))
{
testminbcunit_calciip2(&state, n, fk, _state);
}
minbcresults(&state, &x, &rep, _state);
cntb1 = cntb1+rep.iterationscount;
*err = *err||rep.terminationtype<=0;
}
ae_vector_set_length(&diagh, n, _state);
for(i=0; i<=n-1; i++)
{
diagh.ptr.p_double[i] = 2*ae_pow((double)(i*i+1), (double)(2*fk), _state)*(0.8+0.4*ae_randomreal(_state));
}
minbcsetprecdiag(&state, &diagh, _state);
minbcsetscale(&state, &units, _state);
cntg1 = 0;
for(pass=0; pass<=k-1; pass++)
{
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
minbcrestartfrom(&state, &x, _state);
while(minbciteration(&state, _state))
{
testminbcunit_calciip2(&state, n, fk, _state);
}
minbcresults(&state, &x, &rep, _state);
cntg1 = cntg1+rep.iterationscount;
*err = *err||rep.terminationtype<=0;
}
*err = *err||cntb1=0, __FILE__, __LINE__, "testminbcunit.ap:1381");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx>=0, __FILE__, __LINE__, "testminbcunit.ap:1382");
ae_set_error_flag(wereerrors, ogrep.nonc1test0positive, __FILE__, __LINE__, "testminbcunit.ap:1383");
ae_set_error_flag(wereerrors, ogrep.nonc1test1positive, __FILE__, __LINE__, "testminbcunit.ap:1384");
/*
* Test gradient checking functionality, try various
* defect types:
* * accidental zeroing of some gradient component
* * accidental addition of 1.0 to some component
* * accidental multiplication by 2.0
* Try distorting both target and constraints.
*/
diffstep = 0.001;
n = 10;
for(skind=0; skind<=1; skind++)
{
for(defecttype=-1; defecttype<=2; defecttype++)
{
varidx = hqrnduniformi(&rs, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&s, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = ae_pow((double)(10), skind*(30*hqrnduniformr(&rs, _state)-15), _state);
x0.ptr.p_double[i] = (1.0+0.1*i)*s.ptr.p_double[i];
j = hqrnduniformi(&rs, 3, _state);
bndl.ptr.p_double[i] = -100*s.ptr.p_double[i];
bndu.ptr.p_double[i] = 100*s.ptr.p_double[i];
if( j==1 )
{
bndl.ptr.p_double[i] = x0.ptr.p_double[i];
}
if( j==2 )
{
bndu.ptr.p_double[i] = x0.ptr.p_double[i];
}
}
spdmatrixrndcond(n, 1.0E3, &a, _state);
spdmatrixrndcond(n, 1.0E3, &a1, _state);
minbccreate(n, &x0, &state, _state);
minbcoptguardgradient(&state, diffstep, _state);
minbcsetcond(&state, (double)(0), (double)(0), 1.0E-9, 10, _state);
minbcsetscale(&state, &s, _state);
minbcsetbc(&state, &bndl, &bndu, _state);
while(minbciteration(&state, _state))
{
if( state.needfg )
{
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(wereerrors, ae_fp_less(state.x.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminbcunit.ap:1432");
ae_set_error_flag(wereerrors, ae_fp_greater(state.x.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminbcunit.ap:1433");
}
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.f = state.f+0.5*(state.x.ptr.p_double[i]/s.ptr.p_double[i])*v;
state.g.ptr.p_double[i] = v;
}
if( defecttype==0 )
{
state.g.ptr.p_double[varidx] = (double)(0);
}
if( defecttype==1 )
{
state.g.ptr.p_double[varidx] = state.g.ptr.p_double[varidx]+1;
}
if( defecttype==2 )
{
state.g.ptr.p_double[varidx] = state.g.ptr.p_double[varidx]*2;
}
for(i=0; i<=n-1; i++)
{
state.g.ptr.p_double[i] = state.g.ptr.p_double[i]/s.ptr.p_double[i];
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minbcresults(&state, &x1, &rep, _state);
minbcoptguardresults(&state, &ogrep, _state);
/*
* Check that something is returned
*/
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminbcunit.ap:1466");
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1467");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Compute reference values for true and spoiled Jacobian at X0
*/
ae_set_error_flag(wereerrors, !isfinitevector(&ogrep.badgradxbase, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1474");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_matrix_set_length(&jactrue, 1, n, _state);
ae_matrix_set_length(&jacdefect, 1, n, _state);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+ogrep.badgradxbase.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
jactrue.ptr.pp_double[0][i] = v;
jacdefect.ptr.pp_double[0][i] = v;
}
if( defecttype==0 )
{
jacdefect.ptr.pp_double[0][varidx] = (double)(0);
}
if( defecttype==1 )
{
jacdefect.ptr.pp_double[0][varidx] = jacdefect.ptr.pp_double[0][varidx]+1;
}
if( defecttype==2 )
{
jacdefect.ptr.pp_double[0][varidx] = jacdefect.ptr.pp_double[0][varidx]*2;
}
for(i=0; i<=n-1; i++)
{
jactrue.ptr.pp_double[0][i] = jactrue.ptr.pp_double[0][i]/s.ptr.p_double[i];
jacdefect.ptr.pp_double[0][i] = jacdefect.ptr.pp_double[0][i]/s.ptr.p_double[i];
}
/*
* Check OptGuard report
*/
ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgraduser, 1, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1502");
ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgradnum, 1, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1503");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
if( defecttype>=0 )
{
ae_set_error_flag(wereerrors, !ogrep.badgradsuspected, __FILE__, __LINE__, "testminbcunit.ap:1508");
ae_set_error_flag(wereerrors, ogrep.badgradfidx!=0, __FILE__, __LINE__, "testminbcunit.ap:1509");
ae_set_error_flag(wereerrors, ogrep.badgradvidx!=varidx, __FILE__, __LINE__, "testminbcunit.ap:1510");
}
else
{
ae_set_error_flag(wereerrors, ogrep.badgradsuspected, __FILE__, __LINE__, "testminbcunit.ap:1514");
ae_set_error_flag(wereerrors, ogrep.badgradfidx!=-1, __FILE__, __LINE__, "testminbcunit.ap:1515");
ae_set_error_flag(wereerrors, ogrep.badgradvidx!=-1, __FILE__, __LINE__, "testminbcunit.ap:1516");
}
for(j=0; j<=n-1; j++)
{
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jactrue.ptr.pp_double[0][j]-ogrep.badgradnum.ptr.pp_double[0][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testminbcunit.ap:1520");
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jacdefect.ptr.pp_double[0][j]-ogrep.badgraduser.ptr.pp_double[0][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testminbcunit.ap:1521");
}
}
}
/*
* A test for detection of C1 continuity violations in the target.
*
* Target function is a sum of |(x,c_i)| for i=1..N.
* No constraints is present.
* Analytic gradient is provided.
*
* OptGuard should be able to detect violations in more than
* 99.9% of runs; it means that 100 runs should have no more than 4
* failures in all cases (even after multiple repeated tests; according
* to the binomial distribution quantiles).
*
* We select some N and perform exhaustive search for this N.
*/
passcount = 100;
maxfails = 4;
maxc1test0fails = 10;
maxc1test1fails = 10;
n = 1+hqrnduniformi(&rs, 10, _state);
failurecounter = 0;
c1test0fails = 0;
c1test1fails = 0;
avgstr0len = (double)(0);
avglng0len = (double)(0);
avgstr1len = (double)(0);
avglng1len = (double)(0);
for(pass=1; pass<=passcount; pass++)
{
/*
* Formulate problem
*/
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
/*
* Create and try to solve
*/
minbccreate(n, &x0, &state, _state);
minbcsetcond(&state, (double)(0), (double)(0), 1.0E-9, 50, _state);
minbcsetscale(&state, &s, _state);
minbcoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminbcunit_maxoptguardlevel, _state), _state);
while(minbciteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.g.ptr.p_double[i] = (double)(0);
}
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.f = state.f+ae_fabs(v, _state);
v = (double)(ae_sign(v, _state));
for(j=0; j<=n-1; j++)
{
state.g.ptr.p_double[j] = state.g.ptr.p_double[j]+v*a.ptr.pp_double[i][j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minbcresults(&state, &x1, &rep, _state);
minbcoptguardresults(&state, &ogrep, _state);
/*
* Check basic properties of the solution
*/
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1602");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminbcunit.ap:1603");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Check generic OptGuard report: distinguish between "hard"
* failures which result in immediate termination
* (C0 violation being reported) and "soft" ones
* (C1 violation is NOT reported) which accumulate
* until we exhaust limit.
*/
ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminbcunit.ap:1614");
ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminbcunit.ap:1615");
failed = ae_false;
failed = failed||optguardallclear(&ogrep, _state);
failed = failed||!ogrep.nonc1suspected;
failed = failed||ogrep.nonc1fidx!=0;
if( failed )
{
inc(&failurecounter, _state);
}
/*
* Check C1 continuity test #0
*/
minbcoptguardnonc1test0results(&state, &ognonc1test0strrep, &ognonc1test0lngrep, _state);
minbcoptguardnonc1test1results(&state, &ognonc1test1strrep, &ognonc1test1lngrep, _state);
if( ogrep.nonc1test0positive )
{
ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminbcunit.ap:1630");
ae_set_error_flag(wereerrors, !ognonc1test0strrep.positive, __FILE__, __LINE__, "testminbcunit.ap:1631");
ae_set_error_flag(wereerrors, !ognonc1test0lngrep.positive, __FILE__, __LINE__, "testminbcunit.ap:1632");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testminbcunit.ap:1633");
testminbcunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0strrep, &a, n, _state);
testminbcunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0lngrep, &a, n, _state);
avgstr0len = avgstr0len+(double)ognonc1test0strrep.cnt/(double)passcount;
avglng0len = avglng0len+(double)ognonc1test0lngrep.cnt/(double)passcount;
}
else
{
ae_set_error_flag(wereerrors, ognonc1test0strrep.positive, __FILE__, __LINE__, "testminbcunit.ap:1641");
ae_set_error_flag(wereerrors, ognonc1test0lngrep.positive, __FILE__, __LINE__, "testminbcunit.ap:1642");
testminbcunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0strrep, &a, n, _state);
testminbcunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0lngrep, &a, n, _state);
inc(&c1test0fails, _state);
}
if( ogrep.nonc1test1positive )
{
ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testminbcunit.ap:1649");
ae_set_error_flag(wereerrors, !ognonc1test1strrep.positive, __FILE__, __LINE__, "testminbcunit.ap:1650");
ae_set_error_flag(wereerrors, !ognonc1test1lngrep.positive, __FILE__, __LINE__, "testminbcunit.ap:1651");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testminbcunit.ap:1652");
testminbcunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1strrep, &a, n, _state);
testminbcunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1lngrep, &a, n, _state);
avgstr1len = avgstr1len+(double)ognonc1test1strrep.cnt/(double)passcount;
avglng1len = avglng1len+(double)ognonc1test1lngrep.cnt/(double)passcount;
}
else
{
ae_set_error_flag(wereerrors, ognonc1test1strrep.positive, __FILE__, __LINE__, "testminbcunit.ap:1660");
ae_set_error_flag(wereerrors, ognonc1test1lngrep.positive, __FILE__, __LINE__, "testminbcunit.ap:1661");
testminbcunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1strrep, &a, n, _state);
testminbcunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1lngrep, &a, n, _state);
inc(&c1test1fails, _state);
}
}
ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testminbcunit.ap:1668");
ae_set_error_flag(wereerrors, c1test0fails>maxc1test0fails, __FILE__, __LINE__, "testminbcunit.ap:1669");
ae_set_error_flag(wereerrors, c1test1fails>maxc1test1fails, __FILE__, __LINE__, "testminbcunit.ap:1670");
ae_set_error_flag(wereerrors, ae_fp_less_eq(avglng0len,avgstr0len), __FILE__, __LINE__, "testminbcunit.ap:1671");
ae_set_error_flag(wereerrors, ae_fp_less_eq(avglng1len,avgstr1len), __FILE__, __LINE__, "testminbcunit.ap:1672");
/*
* Detection of C1 continuity violations in the target under numerical differentiation:
* * target function is a sum of |(x,c_i)| for i=1..N.
* * no constraints is present.
* * analytic gradient is provided.
*
* OptGuard should always be able to detect violations in more than
* 99% of runs (note: reduced strength when compared with analytic gradient);
* it means that 100 runs should have no more than 10 failures in all cases
* (even after multiple repeated tests; according to the binomial distribution
* quantiles).
*
* We select some N and perform exhaustive search for this N.
*/
diffstep = 0.0001;
passcount = 100;
maxfails = 10;
n = 1+hqrnduniformi(&rs, 10, _state);
failurecounter = 0;
for(pass=1; pass<=passcount; pass++)
{
/*
* Formulate problem
*/
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = 0.01*ae_pow((double)(2), 0.33*hqrndnormal(&rs, _state), _state);
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
/*
* Create and try to solve
*/
minbccreatef(n, &x0, diffstep, &state, _state);
minbcsetcond(&state, (double)(0), (double)(0), 1.0E-9, 50, _state);
minbcoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminbcunit_maxoptguardlevel, _state), _state);
while(minbciteration(&state, _state))
{
if( state.needf )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.f = state.f+ae_fabs(v, _state);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minbcresults(&state, &x1, &rep, _state);
minbcoptguardresults(&state, &ogrep, _state);
/*
* Check basic properties of the solution
*/
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1738");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminbcunit.ap:1739");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Check OptGuard report: distinguish between "hard"
* failures which result in immediate termination
* (C0 violation being reported) and "soft" ones
* (C1 violation is NOT reported) which accumulate
* until we exhaust limit.
*/
ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testminbcunit.ap:1750");
ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testminbcunit.ap:1751");
failed = ae_false;
failed = failed||optguardallclear(&ogrep, _state);
failed = failed||!ogrep.nonc1suspected;
failed = failed||ogrep.nonc1fidx!=0;
if( failed )
{
inc(&failurecounter, _state);
}
}
ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testminbcunit.ap:1759");
/*
* Make sure than no false positives are reported for larger
* problems where numerical noise can be an issue:
* * N=100 dimensions
* * positive-definite quadratic programming problem
* * upper limit on iterations count, MaxIts=25
* We simply test that OptGuard does not return error code.
*/
n = 100;
spdmatrixrndcond(n, 1.0E2, &a, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
x0.ptr.p_double[i] = ae_pow(2.0, hqrndnormal(&rs, _state), _state);
}
minbccreate(n, &x0, &state, _state);
minbcoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testminbcunit_maxoptguardlevel, _state), _state);
minbcsetcond(&state, (double)(0), (double)(0), 1.0E-9, 25, _state);
while(minbciteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.g.ptr.p_double[i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.f = state.f+0.5*state.x.ptr.p_double[i]*a.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.g.ptr.p_double[i] = state.g.ptr.p_double[i]+a.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minbcresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1802");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminbcunit.ap:1803");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
minbcoptguardresults(&state, &ogrep, _state);
ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testminbcunit.ap:1807");
ae_frame_leave(_state);
}
/*************************************************************************
This function sets random preconditioner:
* unit one, for PrecKind=0
* diagonal-based one, for PrecKind=1
* scale-based one, for PrecKind=2
*************************************************************************/
static void testminbcunit_setrandompreconditioner(minbcstate* state,
ae_int_t n,
ae_int_t preckind,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector p;
ae_int_t i;
ae_frame_make(_state, &_frame_block);
memset(&p, 0, sizeof(p));
ae_vector_init(&p, 0, DT_REAL, _state, ae_true);
if( preckind==1 )
{
ae_vector_set_length(&p, n, _state);
for(i=0; i<=n-1; i++)
{
p.ptr.p_double[i] = ae_exp(6*ae_randomreal(_state)-3, _state);
}
minbcsetprecdiag(state, &p, _state);
}
else
{
minbcsetprecdefault(state, _state);
}
ae_frame_leave(_state);
}
/*************************************************************************
This function tests report of "non-C1" test #0 for task #0
given by matrix A.
On failure sets error flag.
*************************************************************************/
static void testminbcunit_testoptguardc1test0reportfortask0(ae_bool* err,
optguardnonc1test0report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
double vv;
double va;
double vb;
ae_bool hasc1discontinuities;
if( rep->positive )
{
/*
* Check positive report, first checks
*/
ae_set_error_flag(err, rep->fidx!=0, __FILE__, __LINE__, "testminbcunit.ap:1858");
ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testminbcunit.ap:1859");
ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testminbcunit.ap:1860");
ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testminbcunit.ap:1861");
ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testminbcunit.ap:1862");
ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testminbcunit.ap:1863");
ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testminbcunit.ap:1864");
ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testminbcunit.ap:1865");
ae_set_error_flag(err, rep->f.cnt!=rep->cnt, __FILE__, __LINE__, "testminbcunit.ap:1866");
ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1867");
ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1868");
ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testminbcunit.ap:1869");
ae_set_error_flag(err, !isfinitevector(&rep->f, rep->cnt, _state), __FILE__, __LINE__, "testminbcunit.ap:1870");
if( *err )
{
return;
}
/*
* Check consistency of X0, D, Stp and F
*/
for(k=0; k<=rep->cnt-2; k++)
{
ae_set_error_flag(err, ae_fp_greater_eq(rep->stp.ptr.p_double[k],rep->stp.ptr.p_double[k+1]), __FILE__, __LINE__, "testminbcunit.ap:1878");
}
for(k=0; k<=rep->cnt-1; k++)
{
v = (double)(0);
for(i=0; i<=n-1; i++)
{
vv = (double)(0);
for(j=0; j<=n-1; j++)
{
vv = vv+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[k]);
}
v = v+ae_fabs(vv, _state);
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-rep->f.ptr.p_double[k], _state),1.0E-6*ae_maxreal(ae_fabs(v, _state), (double)(1), _state)), __FILE__, __LINE__, "testminbcunit.ap:1891");
}
/*
* Check that interval [#StpIdxA,#StpIdxB] contains at least one discontinuity
*/
hasc1discontinuities = ae_false;
for(i=0; i<=n-1; i++)
{
va = (double)(0);
vb = (double)(0);
for(j=0; j<=n-1; j++)
{
va = va+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxa]);
vb = vb+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxb]);
}
hasc1discontinuities = hasc1discontinuities||ae_sign(va, _state)!=ae_sign(vb, _state);
}
ae_set_error_flag(err, !hasc1discontinuities, __FILE__, __LINE__, "testminbcunit.ap:1909");
}
else
{
/*
* Check negative report: fields must be empty
*/
ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testminbcunit.ap:1916");
ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testminbcunit.ap:1917");
ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testminbcunit.ap:1918");
ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testminbcunit.ap:1919");
ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testminbcunit.ap:1920");
ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testminbcunit.ap:1921");
ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testminbcunit.ap:1922");
ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testminbcunit.ap:1923");
ae_set_error_flag(err, rep->f.cnt!=0, __FILE__, __LINE__, "testminbcunit.ap:1924");
}
}
/*************************************************************************
This function tests report of "non-C1" test #1 for task #0
given by matrix A.
On failure sets error flag.
*************************************************************************/
static void testminbcunit_testoptguardc1test1reportfortask0(ae_bool* err,
optguardnonc1test1report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
double vv;
double va;
double vb;
ae_bool tooclose;
ae_bool hasc1discontinuities;
if( rep->positive )
{
/*
* Check positive report, first checks
*/
ae_set_error_flag(err, rep->fidx!=0, __FILE__, __LINE__, "testminbcunit.ap:1952");
ae_set_error_flag(err, rep->vidx<0, __FILE__, __LINE__, "testminbcunit.ap:1953");
ae_set_error_flag(err, rep->vidx>n, __FILE__, __LINE__, "testminbcunit.ap:1954");
ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testminbcunit.ap:1955");
ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testminbcunit.ap:1956");
ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testminbcunit.ap:1957");
ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testminbcunit.ap:1958");
ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testminbcunit.ap:1959");
ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testminbcunit.ap:1960");
ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testminbcunit.ap:1961");
ae_set_error_flag(err, rep->g.cnt!=rep->cnt, __FILE__, __LINE__, "testminbcunit.ap:1962");
ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1963");
ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testminbcunit.ap:1964");
ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testminbcunit.ap:1965");
ae_set_error_flag(err, !isfinitevector(&rep->g, rep->cnt, _state), __FILE__, __LINE__, "testminbcunit.ap:1966");
if( *err )
{
return;
}
/*
* Check consistency of X0, D, Stp and G
*/
for(k=0; k<=rep->cnt-2; k++)
{
ae_set_error_flag(err, ae_fp_greater_eq(rep->stp.ptr.p_double[k],rep->stp.ptr.p_double[k+1]), __FILE__, __LINE__, "testminbcunit.ap:1974");
}
for(k=0; k<=rep->cnt-1; k++)
{
v = (double)(0);
tooclose = ae_false;
for(i=0; i<=n-1; i++)
{
vv = (double)(0);
for(j=0; j<=n-1; j++)
{
vv = vv+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[k]);
}
v = v+ae_sign(vv, _state)*a->ptr.pp_double[i][rep->vidx];
tooclose = tooclose||ae_fp_less(ae_fabs(vv, _state),1.0E-4);
}
if( !tooclose )
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-rep->g.ptr.p_double[k], _state),1.0E-6*ae_maxreal(ae_fabs(v, _state), (double)(1), _state)), __FILE__, __LINE__, "testminbcunit.ap:1988");
}
}
/*
* Check that interval [#StpIdxA,#StpIdxB] contains at least one discontinuity
*/
tooclose = ae_false;
hasc1discontinuities = ae_false;
for(i=0; i<=n-1; i++)
{
va = (double)(0);
vb = (double)(0);
for(j=0; j<=n-1; j++)
{
va = va+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxa]);
vb = vb+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxb]);
}
tooclose = (tooclose||ae_fp_less(ae_fabs(va, _state),1.0E-8))||ae_fp_less(ae_fabs(vb, _state),1.0E-8);
hasc1discontinuities = hasc1discontinuities||ae_sign(va, _state)!=ae_sign(vb, _state);
}
if( !tooclose )
{
ae_set_error_flag(err, !hasc1discontinuities, __FILE__, __LINE__, "testminbcunit.ap:2009");
}
}
else
{
/*
* Check negative report: fields must be empty
*/
ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testminbcunit.ap:2016");
ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testminbcunit.ap:2017");
ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testminbcunit.ap:2018");
ae_set_error_flag(err, rep->vidx!=-1, __FILE__, __LINE__, "testminbcunit.ap:2019");
ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testminbcunit.ap:2020");
ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testminbcunit.ap:2021");
ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testminbcunit.ap:2022");
ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testminbcunit.ap:2023");
ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testminbcunit.ap:2024");
ae_set_error_flag(err, rep->g.cnt!=0, __FILE__, __LINE__, "testminbcunit.ap:2025");
}
}
static double testminnsunit_scalingtesttol = 1.0E-6;
static ae_int_t testminnsunit_scalingtestcnt = 5;
static void testminnsunit_basictest0uc(ae_bool* errors, ae_state *_state);
static void testminnsunit_basictest1uc(ae_bool* errors, ae_state *_state);
static void testminnsunit_basictest0bc(ae_bool* errors, ae_state *_state);
static void testminnsunit_basictest1bc(ae_bool* errors, ae_state *_state);
static void testminnsunit_basictest0lc(ae_bool* errors, ae_state *_state);
static void testminnsunit_basictest1lc(ae_bool* errors, ae_state *_state);
static void testminnsunit_basictest0nlc(ae_bool* errors, ae_state *_state);
static void testminnsunit_testuc(ae_bool* primaryerrors,
ae_bool* othererrors,
ae_state *_state);
static void testminnsunit_testbc(ae_bool* primaryerrors,
ae_bool* othererrors,
ae_state *_state);
static void testminnsunit_testlc(ae_bool* primaryerrors,
ae_bool* othererrors,
ae_state *_state);
static void testminnsunit_testnlc(ae_bool* primaryerrors,
ae_bool* othererrors,
ae_state *_state);
static void testminnsunit_testother(ae_bool* othererrors,
ae_state *_state);
ae_bool testminns(ae_bool silent, ae_state *_state)
{
ae_bool wereerrors;
ae_bool ucerrors;
ae_bool bcerrors;
ae_bool lcerrors;
ae_bool nlcerrors;
ae_bool othererrors;
ae_bool result;
wereerrors = ae_false;
ucerrors = ae_false;
bcerrors = ae_false;
lcerrors = ae_false;
nlcerrors = ae_false;
othererrors = ae_false;
/*
* Basic tests
*/
testminnsunit_basictest0nlc(&nlcerrors, _state);
testminnsunit_basictest0uc(&ucerrors, _state);
testminnsunit_basictest1uc(&ucerrors, _state);
testminnsunit_basictest0bc(&bcerrors, _state);
testminnsunit_basictest1bc(&bcerrors, _state);
testminnsunit_basictest0lc(&lcerrors, _state);
testminnsunit_basictest1lc(&lcerrors, _state);
/*
* Special tests
*/
testminnsunit_testother(&othererrors, _state);
/*
* Full scale tests
*/
testminnsunit_testuc(&ucerrors, &othererrors, _state);
testminnsunit_testbc(&bcerrors, &othererrors, _state);
testminnsunit_testlc(&lcerrors, &othererrors, _state);
testminnsunit_testnlc(&nlcerrors, &othererrors, _state);
/*
* end
*/
wereerrors = (((ucerrors||bcerrors)||lcerrors)||nlcerrors)||othererrors;
if( !silent )
{
printf("TESTING MINNS OPTIMIZATION\n");
printf("TESTS:\n");
printf("* UNCONSTRAINED ");
if( ucerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* BOUND CONSTRAINED ");
if( bcerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* LINEARLY CONSTRAINED ");
if( lcerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* NONLINEARLY CONSTRAINED ");
if( nlcerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* OTHER PROPERTIES ");
if( othererrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( wereerrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !wereerrors;
return result;
}
/*************************************************************************
Basic unconstrained test
*************************************************************************/
static void testminnsunit_basictest0uc(ae_bool* errors, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t i;
ae_vector x0;
ae_vector x1;
ae_vector d;
minnsstate s;
minnsreport rep;
double sumits;
double sumnfev;
ae_int_t pass;
ae_int_t passcount;
ae_frame_make(_state, &_frame_block);
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&d, 0, sizeof(d));
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
_minnsstate_init(&s, _state, ae_true);
_minnsreport_init(&rep, _state, ae_true);
n = 5;
passcount = 10;
sumits = (double)(0);
sumnfev = (double)(0);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&d, n, _state);
for(pass=1; pass<=10; pass++)
{
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
d.ptr.p_double[i] = ae_pow((double)(10), 2*ae_randomreal(_state)-1, _state);
}
minnscreate(n, &x0, &s, _state);
minnssetalgoags(&s, 0.1, 0.0, _state);
while(minnsiteration(&s, _state))
{
if( s.needfij )
{
s.fi.ptr.p_double[0] = 0.0;
for(i=0; i<=n-1; i++)
{
s.fi.ptr.p_double[0] = s.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(s.x.ptr.p_double[i], _state);
s.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(s.x.ptr.p_double[i], _state);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&s, &x1, &rep, _state);
ae_set_error_flag(errors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:143");
if( *errors )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errors, !ae_isfinite(x1.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[i], _state),0.001), __FILE__, __LINE__, "testminnsunit.ap:147");
}
sumits = sumits+(double)rep.iterationscount/(double)passcount;
sumnfev = sumnfev+(double)rep.nfev/(double)passcount;
}
ae_frame_leave(_state);
}
/*************************************************************************
Basic unconstrained test: nonsmooth Rosenbrock posed as unconstrained problem.
[ ]
minimize [ 10*|x0^2-x1| + (1-x0)^2 + 100*max(sqrt(2)*x0-1,0) + 100*max(2*x1-1,0) ]
[ ]
It's exact solution is x0=1/sqrt(2), x1=1/2
*************************************************************************/
static void testminnsunit_basictest1uc(ae_bool* errors, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
double v0;
double v1;
ae_vector x0;
ae_vector x1;
minnsstate s;
minnsreport rep;
ae_frame_make(_state, &_frame_block);
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
_minnsstate_init(&s, _state, ae_true);
_minnsreport_init(&rep, _state, ae_true);
n = 2;
ae_vector_set_length(&x0, n, _state);
x0.ptr.p_double[0] = (double)(0);
x0.ptr.p_double[1] = (double)(0);
minnscreate(n, &x0, &s, _state);
minnssetalgoags(&s, 0.1, 0.0, _state);
while(minnsiteration(&s, _state))
{
if( s.needfij )
{
v0 = s.x.ptr.p_double[0];
v1 = s.x.ptr.p_double[1];
s.fi.ptr.p_double[0] = 10*ae_fabs(ae_sqr(v0, _state)-v1, _state)+ae_sqr(v0-1, _state);
s.j.ptr.pp_double[0][0] = 10*ae_sign(ae_sqr(v0, _state)-v1, _state)*2*v0+2*(v0-1);
s.j.ptr.pp_double[0][1] = (double)(10*ae_sign(ae_sqr(v0, _state)-v1, _state)*(-1));
if( ae_fp_greater(ae_sqrt((double)(2), _state)*v0-1,0.0) )
{
s.fi.ptr.p_double[0] = s.fi.ptr.p_double[0]+100*(ae_sqrt((double)(2), _state)*v0-1);
s.j.ptr.pp_double[0][0] = s.j.ptr.pp_double[0][0]+100*ae_sqrt((double)(2), _state);
}
if( ae_fp_greater(2*v1-1,0.0) )
{
s.fi.ptr.p_double[0] = s.fi.ptr.p_double[0]+100*(2*v1-1);
s.j.ptr.pp_double[0][1] = s.j.ptr.pp_double[0][1]+100*2;
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&s, &x1, &rep, _state);
ae_set_error_flag(errors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:204");
if( *errors )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(errors, !ae_isfinite(x1.ptr.p_double[0], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[0]-1/ae_sqrt((double)(2), _state), _state),0.001), __FILE__, __LINE__, "testminnsunit.ap:207");
ae_set_error_flag(errors, !ae_isfinite(x1.ptr.p_double[1], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[1]-(double)1/(double)2, _state),0.001), __FILE__, __LINE__, "testminnsunit.ap:208");
ae_frame_leave(_state);
}
/*************************************************************************
Basic box constrained test
*************************************************************************/
static void testminnsunit_basictest0bc(ae_bool* errors, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t i;
ae_vector x0;
ae_vector x1;
ae_vector d;
ae_vector bl;
ae_vector bu;
minnsstate s;
minnsreport rep;
double sumits;
double sumnfev;
ae_int_t pass;
ae_int_t passcount;
double v0;
double v1;
ae_frame_make(_state, &_frame_block);
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&d, 0, sizeof(d));
memset(&bl, 0, sizeof(bl));
memset(&bu, 0, sizeof(bu));
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bu, 0, DT_REAL, _state, ae_true);
_minnsstate_init(&s, _state, ae_true);
_minnsreport_init(&rep, _state, ae_true);
n = 5;
passcount = 10;
sumits = (double)(0);
sumnfev = (double)(0);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
ae_vector_set_length(&d, n, _state);
for(pass=1; pass<=10; pass++)
{
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
d.ptr.p_double[i] = ae_pow((double)(10), 2*ae_randomreal(_state)-1, _state);
v0 = 2*ae_randomreal(_state)-1;
v1 = 2*ae_randomreal(_state)-1;
bl.ptr.p_double[i] = ae_minreal(v0, v1, _state);
bu.ptr.p_double[i] = ae_maxreal(v0, v1, _state);
}
minnscreate(n, &x0, &s, _state);
minnssetalgoags(&s, 0.1, 0.0, _state);
minnssetbc(&s, &bl, &bu, _state);
while(minnsiteration(&s, _state))
{
if( s.needfij )
{
s.fi.ptr.p_double[0] = 0.0;
for(i=0; i<=n-1; i++)
{
s.fi.ptr.p_double[0] = s.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(s.x.ptr.p_double[i], _state);
s.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(s.x.ptr.p_double[i], _state);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&s, &x1, &rep, _state);
ae_set_error_flag(errors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:263");
if( *errors )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errors, !ae_isfinite(x1.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-boundval(0.0, bl.ptr.p_double[i], bu.ptr.p_double[i], _state), _state),0.001), __FILE__, __LINE__, "testminnsunit.ap:267");
}
sumits = sumits+(double)rep.iterationscount/(double)passcount;
sumnfev = sumnfev+(double)rep.nfev/(double)passcount;
}
ae_frame_leave(_state);
}
/*************************************************************************
Basic constrained test: nonsmooth Rosenbrock posed as box constrained problem.
[ ]
minimize [ 10*|x0^2-x1| + (1-x0)^2 ]
[ ]
s.t. x0<=1/sqrt(2), x1<=0.5
It's exact solution is x0=1/sqrt(2), x1=1/2
*************************************************************************/
static void testminnsunit_basictest1bc(ae_bool* errors, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
double v0;
double v1;
ae_vector x0;
ae_vector x1;
ae_vector bndl;
ae_vector bndu;
minnsstate s;
minnsreport rep;
ae_frame_make(_state, &_frame_block);
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
_minnsstate_init(&s, _state, ae_true);
_minnsreport_init(&rep, _state, ae_true);
n = 2;
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
x0.ptr.p_double[0] = (double)(0);
x0.ptr.p_double[1] = (double)(0);
bndl.ptr.p_double[0] = _state->v_neginf;
bndl.ptr.p_double[1] = _state->v_neginf;
bndu.ptr.p_double[0] = 1/ae_sqrt((double)(2), _state);
bndu.ptr.p_double[1] = (double)1/(double)2;
minnscreate(n, &x0, &s, _state);
minnssetbc(&s, &bndl, &bndu, _state);
minnssetalgoags(&s, 0.1, 0.0, _state);
while(minnsiteration(&s, _state))
{
if( s.needfij )
{
v0 = s.x.ptr.p_double[0];
v1 = s.x.ptr.p_double[1];
s.fi.ptr.p_double[0] = 10*ae_fabs(ae_sqr(v0, _state)-v1, _state)+ae_sqr(v0-1, _state);
s.j.ptr.pp_double[0][0] = 10*ae_sign(ae_sqr(v0, _state)-v1, _state)*2*v0+2*(v0-1);
s.j.ptr.pp_double[0][1] = (double)(10*ae_sign(ae_sqr(v0, _state)-v1, _state)*(-1));
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&s, &x1, &rep, _state);
ae_set_error_flag(errors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:323");
if( *errors )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(errors, !ae_isfinite(x1.ptr.p_double[0], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[0]-1/ae_sqrt((double)(2), _state), _state),0.001), __FILE__, __LINE__, "testminnsunit.ap:326");
ae_set_error_flag(errors, !ae_isfinite(x1.ptr.p_double[1], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[1]-(double)1/(double)2, _state),0.001), __FILE__, __LINE__, "testminnsunit.ap:327");
ae_frame_leave(_state);
}
/*************************************************************************
Basic linearly constrained test
*************************************************************************/
static void testminnsunit_basictest0lc(ae_bool* errors, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_vector x0;
ae_vector x1;
ae_matrix c;
ae_vector ct;
double d;
minnsstate s;
minnsreport rep;
double sumits;
double sumnfev;
ae_int_t pass;
ae_int_t passcount;
ae_int_t nc;
ae_frame_make(_state, &_frame_block);
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&c, 0, sizeof(c));
memset(&ct, 0, sizeof(ct));
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
_minnsstate_init(&s, _state, ae_true);
_minnsreport_init(&rep, _state, ae_true);
d = -10.0;
n = 5;
passcount = 10;
sumits = (double)(0);
sumnfev = (double)(0);
ae_vector_set_length(&x0, n, _state);
ae_matrix_set_length(&c, 2*n, n+1, _state);
ae_vector_set_length(&ct, 2*n, _state);
for(pass=1; pass<=10; pass++)
{
nc = 0;
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
if( ae_fp_less(ae_randomreal(_state),0.5) )
{
for(j=0; j<=n; j++)
{
c.ptr.pp_double[nc][j] = 0.0;
}
c.ptr.pp_double[nc][i] = 1.0+ae_randomreal(_state);
ct.ptr.p_int[nc] = 0;
inc(&nc, _state);
}
else
{
for(j=0; j<=n; j++)
{
c.ptr.pp_double[nc+0][j] = 0.0;
c.ptr.pp_double[nc+1][j] = 0.0;
}
c.ptr.pp_double[nc+0][i] = 1.0+ae_randomreal(_state);
c.ptr.pp_double[nc+1][i] = 1.0+ae_randomreal(_state);
ct.ptr.p_int[nc+0] = 1;
ct.ptr.p_int[nc+1] = -1;
nc = nc+2;
}
}
minnscreate(n, &x0, &s, _state);
minnssetalgoags(&s, 0.1, 0.0, _state);
minnssetlc(&s, &c, &ct, nc, _state);
while(minnsiteration(&s, _state))
{
if( s.needfij )
{
s.fi.ptr.p_double[0] = 0.0;
for(i=0; i<=n-1; i++)
{
s.fi.ptr.p_double[0] = d*ae_sqr(s.x.ptr.p_double[i], _state);
s.j.ptr.pp_double[0][i] = d*2*s.x.ptr.p_double[i];
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&s, &x1, &rep, _state);
ae_set_error_flag(errors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:404");
if( *errors )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errors, !ae_isfinite(x1.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[i], _state),0.001), __FILE__, __LINE__, "testminnsunit.ap:408");
}
sumits = sumits+(double)rep.iterationscount/(double)passcount;
sumnfev = sumnfev+(double)rep.nfev/(double)passcount;
}
ae_frame_leave(_state);
}
/*************************************************************************
Basic constrained test: nonsmooth Rosenbrock posed as linearly constrained problem.
[ ]
minimize [ 10*|x0^2-x1| + (1-x0)^2 ]
[ ]
s.t. x0<=1/sqrt(2), x1<=0.5
It's exact solution is x0=1/sqrt(2), x1=1/2
*************************************************************************/
static void testminnsunit_basictest1lc(ae_bool* errors, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
double v0;
double v1;
ae_vector x0;
ae_vector x1;
ae_matrix c;
ae_vector ct;
minnsstate s;
minnsreport rep;
ae_frame_make(_state, &_frame_block);
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&c, 0, sizeof(c));
memset(&ct, 0, sizeof(ct));
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
_minnsstate_init(&s, _state, ae_true);
_minnsreport_init(&rep, _state, ae_true);
n = 2;
ae_vector_set_length(&x0, n, _state);
ae_matrix_set_length(&c, 2, n+1, _state);
ae_vector_set_length(&ct, 2, _state);
x0.ptr.p_double[0] = (double)(0);
x0.ptr.p_double[1] = (double)(0);
c.ptr.pp_double[0][0] = 1.0;
c.ptr.pp_double[0][1] = 0.0;
c.ptr.pp_double[0][2] = 1/ae_sqrt((double)(2), _state);
c.ptr.pp_double[1][0] = 0.0;
c.ptr.pp_double[1][1] = 1.0;
c.ptr.pp_double[1][2] = (double)1/(double)2;
ct.ptr.p_int[0] = -1;
ct.ptr.p_int[1] = -1;
minnscreate(n, &x0, &s, _state);
minnssetlc(&s, &c, &ct, 2, _state);
minnssetalgoags(&s, 0.1, 0.0, _state);
while(minnsiteration(&s, _state))
{
if( s.needfij )
{
v0 = s.x.ptr.p_double[0];
v1 = s.x.ptr.p_double[1];
s.fi.ptr.p_double[0] = 10*ae_fabs(ae_sqr(v0, _state)-v1, _state)+ae_sqr(v0-1, _state);
s.j.ptr.pp_double[0][0] = 10*ae_sign(ae_sqr(v0, _state)-v1, _state)*2*v0+2*(v0-1);
s.j.ptr.pp_double[0][1] = (double)(10*ae_sign(ae_sqr(v0, _state)-v1, _state)*(-1));
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&s, &x1, &rep, _state);
ae_set_error_flag(errors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:470");
if( *errors )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(errors, !ae_isfinite(x1.ptr.p_double[0], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[0]-1/ae_sqrt((double)(2), _state), _state),0.001), __FILE__, __LINE__, "testminnsunit.ap:473");
ae_set_error_flag(errors, !ae_isfinite(x1.ptr.p_double[1], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[1]-(double)1/(double)2, _state),0.001), __FILE__, __LINE__, "testminnsunit.ap:474");
ae_frame_leave(_state);
}
/*************************************************************************
Basic nonlinearly constrained test
*************************************************************************/
static void testminnsunit_basictest0nlc(ae_bool* errors, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_vector x0;
ae_vector x1;
ae_matrix ec;
ae_matrix ic;
ae_int_t nec;
ae_int_t nic;
double d;
minnsstate s;
minnsreport rep;
double sumits;
double sumnfev;
ae_int_t pass;
ae_int_t passcount;
ae_frame_make(_state, &_frame_block);
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&ec, 0, sizeof(ec));
memset(&ic, 0, sizeof(ic));
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ec, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ic, 0, 0, DT_REAL, _state, ae_true);
_minnsstate_init(&s, _state, ae_true);
_minnsreport_init(&rep, _state, ae_true);
d = -10.0;
n = 5;
passcount = 10;
sumits = (double)(0);
sumnfev = (double)(0);
ae_vector_set_length(&x0, n, _state);
ae_matrix_set_length(&ec, 2*n, n+1, _state);
ae_matrix_set_length(&ic, 2*n, n+1, _state);
for(pass=1; pass<=10; pass++)
{
nec = 0;
nic = 0;
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
if( ae_fp_less(ae_randomreal(_state),0.5) )
{
for(j=0; j<=n; j++)
{
ec.ptr.pp_double[nec][j] = 0.0;
}
ec.ptr.pp_double[nec][i] = 1.0+ae_randomreal(_state);
inc(&nec, _state);
}
else
{
for(j=0; j<=n; j++)
{
ic.ptr.pp_double[nic+0][j] = 0.0;
ic.ptr.pp_double[nic+1][j] = 0.0;
}
ic.ptr.pp_double[nic+0][i] = 1.0+ae_randomreal(_state);
ic.ptr.pp_double[nic+1][i] = -1.0-ae_randomreal(_state);
nic = nic+2;
}
}
minnscreate(n, &x0, &s, _state);
minnssetalgoags(&s, 0.1, 100.0, _state);
minnssetnlc(&s, nec, nic, _state);
while(minnsiteration(&s, _state))
{
if( s.needfij )
{
s.fi.ptr.p_double[0] = 0.0;
for(j=0; j<=n-1; j++)
{
s.fi.ptr.p_double[0] = d*ae_sqr(s.x.ptr.p_double[j], _state);
s.j.ptr.pp_double[0][j] = d*2*s.x.ptr.p_double[j];
}
for(i=0; i<=nec-1; i++)
{
s.fi.ptr.p_double[1+i] = -ec.ptr.pp_double[i][n];
for(j=0; j<=n-1; j++)
{
s.fi.ptr.p_double[1+i] = s.fi.ptr.p_double[1+i]+s.x.ptr.p_double[j]*ec.ptr.pp_double[i][j];
s.j.ptr.pp_double[1+i][j] = ec.ptr.pp_double[i][j];
}
}
for(i=0; i<=nic-1; i++)
{
s.fi.ptr.p_double[1+nec+i] = -ic.ptr.pp_double[i][n];
for(j=0; j<=n-1; j++)
{
s.fi.ptr.p_double[1+nec+i] = s.fi.ptr.p_double[1+nec+i]+s.x.ptr.p_double[j]*ic.ptr.pp_double[i][j];
s.j.ptr.pp_double[1+nec+i][j] = ic.ptr.pp_double[i][j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&s, &x1, &rep, _state);
ae_set_error_flag(errors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:567");
if( *errors )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errors, !ae_isfinite(x1.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[i], _state),0.001), __FILE__, __LINE__, "testminnsunit.ap:571");
}
sumits = sumits+(double)rep.iterationscount/(double)passcount;
sumnfev = sumnfev+(double)rep.nfev/(double)passcount;
}
ae_frame_leave(_state);
}
/*************************************************************************
Unconstrained test
*************************************************************************/
static void testminnsunit_testuc(ae_bool* primaryerrors,
ae_bool* othererrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t i;
ae_vector x0;
ae_vector x0s;
ae_vector x1;
ae_vector x1s;
ae_vector d;
ae_vector xc;
ae_vector s;
ae_vector xrfirst;
ae_vector xrlast;
minnsstate state;
minnsreport rep;
double v;
ae_int_t pass;
ae_bool requirexrep;
double epsrad;
ae_bool werexreports;
double repferr;
double xtol;
ae_frame_make(_state, &_frame_block);
memset(&x0, 0, sizeof(x0));
memset(&x0s, 0, sizeof(x0s));
memset(&x1, 0, sizeof(x1));
memset(&x1s, 0, sizeof(x1s));
memset(&d, 0, sizeof(d));
memset(&xc, 0, sizeof(xc));
memset(&s, 0, sizeof(s));
memset(&xrfirst, 0, sizeof(xrfirst));
memset(&xrlast, 0, sizeof(xrlast));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xrfirst, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xrlast, 0, DT_REAL, _state, ae_true);
_minnsstate_init(&state, _state, ae_true);
_minnsreport_init(&rep, _state, ae_true);
for(pass=1; pass<=10; pass++)
{
for(n=1; n<=5; n++)
{
/*
* First test:
* * test that problem is successfully solved
* * test that X-reports are performed correctly - present
* when requested, return first and last points correctly,
* not present by default, function value is reported
* correctly.
* * we use non-unit scale, randomly chosen one, which results
* in badly conditioned problems (to check robustness)
*/
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xc, n, _state);
ae_vector_set_length(&d, n, _state);
ae_vector_set_length(&s, n, _state);
ae_vector_set_length(&xrfirst, n, _state);
ae_vector_set_length(&xrlast, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 10*(2*ae_randomreal(_state)-1);
xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
d.ptr.p_double[i] = ae_pow((double)(10), 2*(2*ae_randomreal(_state)-1), _state);
s.ptr.p_double[i] = ae_pow((double)(10), 2*(2*ae_randomreal(_state)-1), _state);
}
requirexrep = ae_fp_greater(ae_randomreal(_state),0.5);
epsrad = 0.01*ae_pow((double)(10), -2*ae_randomreal(_state), _state);
xtol = 15.0*epsrad;
minnscreate(n, &x0, &state, _state);
minnssetalgoags(&state, 0.1, 0.0, _state);
minnssetcond(&state, epsrad, 0, _state);
minnssetscale(&state, &s, _state);
if( requirexrep )
{
minnssetxrep(&state, ae_true, _state);
}
werexreports = ae_false;
repferr = 0.0;
while(minnsiteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = 0.0;
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
}
continue;
}
if( state.xupdated )
{
if( !werexreports )
{
ae_v_move(&xrfirst.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
}
ae_v_move(&xrlast.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
werexreports = ae_true;
v = 0.0;
for(i=0; i<=n-1; i++)
{
v = v+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
}
repferr = ae_maxreal(repferr, ae_fabs(v-state.f, _state), _state);
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&state, &x1, &rep, _state);
ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:668");
ae_set_error_flag(othererrors, werexreports&&!requirexrep, __FILE__, __LINE__, "testminnsunit.ap:669");
ae_set_error_flag(othererrors, requirexrep&&!werexreports, __FILE__, __LINE__, "testminnsunit.ap:670");
ae_set_error_flag(othererrors, ae_fp_greater(repferr,10000*ae_machineepsilon), __FILE__, __LINE__, "testminnsunit.ap:671");
if( *primaryerrors||(*othererrors) )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(primaryerrors, !ae_isfinite(x1.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-xc.ptr.p_double[i], _state)/s.ptr.p_double[i],xtol), __FILE__, __LINE__, "testminnsunit.ap:676");
if( requirexrep )
{
ae_set_error_flag(othererrors, !ae_isfinite(xrfirst.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x0.ptr.p_double[i]-xrfirst.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testminnsunit.ap:679");
ae_set_error_flag(othererrors, !ae_isfinite(xrlast.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-xrlast.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testminnsunit.ap:680");
}
}
/*
* Test numerical differentiation:
* * test that problem is successfully solved
* * test that correct function value is reported
*/
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xc, n, _state);
ae_vector_set_length(&d, n, _state);
ae_vector_set_length(&s, n, _state);
ae_vector_set_length(&xrlast, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 10*(2*ae_randomreal(_state)-1);
xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
d.ptr.p_double[i] = ae_pow((double)(10), 2*(2*ae_randomreal(_state)-1), _state);
s.ptr.p_double[i] = ae_pow((double)(10), 2*(2*ae_randomreal(_state)-1), _state);
}
epsrad = 0.01*ae_pow((double)(10), -2*ae_randomreal(_state), _state);
xtol = 15.0*epsrad;
minnscreatef(n, &x0, epsrad/100, &state, _state);
minnssetalgoags(&state, 0.1, 0.0, _state);
minnssetcond(&state, epsrad, 0, _state);
minnssetscale(&state, &s, _state);
minnssetxrep(&state, ae_true, _state);
repferr = 0.0;
while(minnsiteration(&state, _state))
{
if( state.needfi )
{
state.fi.ptr.p_double[0] = 0.0;
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
}
continue;
}
if( state.xupdated )
{
v = 0.0;
for(i=0; i<=n-1; i++)
{
v = v+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
}
repferr = ae_maxreal(repferr, ae_fabs(v-state.f, _state), _state);
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&state, &x1, &rep, _state);
ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:731");
ae_set_error_flag(othererrors, ae_fp_greater(repferr,10000*ae_machineepsilon), __FILE__, __LINE__, "testminnsunit.ap:732");
if( *primaryerrors||(*othererrors) )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(primaryerrors, !ae_isfinite(x1.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-xc.ptr.p_double[i], _state)/s.ptr.p_double[i],xtol), __FILE__, __LINE__, "testminnsunit.ap:736");
}
/*
* Test scaling: we perform several steps on unit-scale problem,
* then we perform same amount of steps on re-scaled problem,
* starting from same point (but scaled according to chosen scale).
*
* Correctly written optimizer should perform essentially same steps
* (up to scale) on both problems. At least, it holds within first
* several steps, before rounding errors start to accumulate.
*
* NOTE: we also check that correctly scaled points are reported.
* And, as side effect, we check MinNSRestartFrom().
*
* NOTE: we use moderate scale and diagonal coefficients in order
* to have well-conditioned system. We test correctness of
* formulae here, not robustness of algorithm.
*/
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xc, n, _state);
ae_vector_set_length(&x0s, n, _state);
ae_vector_set_length(&d, n, _state);
ae_vector_set_length(&s, n, _state);
ae_vector_set_length(&xrlast, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = ae_pow((double)(10), 2*ae_randomreal(_state)-1, _state);
d.ptr.p_double[i] = ae_pow((double)(10), 2*ae_randomreal(_state)-1, _state);
x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x0s.ptr.p_double[i] = x0.ptr.p_double[i]*s.ptr.p_double[i];
}
minnscreate(n, &x0, &state, _state);
minnssetalgoags(&state, 0.1, 0.0, _state);
minnssetcond(&state, 0.0, testminnsunit_scalingtestcnt, _state);
minnssetxrep(&state, ae_false, _state);
while(minnsiteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = 0.0;
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&state, &x1, &rep, _state);
ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:788");
if( *primaryerrors||(*othererrors) )
{
ae_frame_leave(_state);
return;
}
minnssetscale(&state, &s, _state);
minnssetxrep(&state, ae_true, _state);
minnsrestartfrom(&state, &x0s, _state);
werexreports = ae_false;
while(minnsiteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = 0.0;
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]/s.ptr.p_double[i]-xc.ptr.p_double[i], _state);
state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(state.x.ptr.p_double[i]/s.ptr.p_double[i]-xc.ptr.p_double[i], _state)/s.ptr.p_double[i];
}
continue;
}
if( state.xupdated )
{
ae_v_move(&xrlast.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
werexreports = ae_true;
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&state, &x1s, &rep, _state);
ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:818");
if( *primaryerrors||(*othererrors) )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(primaryerrors, (!ae_isfinite(x1.ptr.p_double[i], _state)||!ae_isfinite(x1s.ptr.p_double[i], _state))||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-x1s.ptr.p_double[i]/s.ptr.p_double[i], _state),1.0E-4), __FILE__, __LINE__, "testminnsunit.ap:823");
ae_set_error_flag(othererrors, !ae_isfinite(xrlast.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1s.ptr.p_double[i]-xrlast.ptr.p_double[i], _state),testminnsunit_scalingtesttol), __FILE__, __LINE__, "testminnsunit.ap:827");
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Box constrained test
*************************************************************************/
static void testminnsunit_testbc(ae_bool* primaryerrors,
ae_bool* othererrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_vector x0;
ae_vector x0s;
ae_vector x1;
ae_vector x1s;
ae_vector b;
ae_vector d;
ae_vector xc;
ae_vector s;
ae_vector bndl;
ae_vector bndu;
ae_vector scaledbndl;
ae_vector scaledbndu;
ae_vector xrfirst;
ae_vector xrlast;
ae_matrix a;
minnsstate state;
minnsreport rep;
double v;
double v0;
double v1;
ae_int_t pass;
ae_int_t passcount;
ae_bool requirexrep;
double epsrad;
ae_bool werexreports;
double repferr;
double xtol;
ae_int_t maxn;
double conda;
double gnorm;
ae_frame_make(_state, &_frame_block);
memset(&x0, 0, sizeof(x0));
memset(&x0s, 0, sizeof(x0s));
memset(&x1, 0, sizeof(x1));
memset(&x1s, 0, sizeof(x1s));
memset(&b, 0, sizeof(b));
memset(&d, 0, sizeof(d));
memset(&xc, 0, sizeof(xc));
memset(&s, 0, sizeof(s));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(&scaledbndl, 0, sizeof(scaledbndl));
memset(&scaledbndu, 0, sizeof(scaledbndu));
memset(&xrfirst, 0, sizeof(xrfirst));
memset(&xrlast, 0, sizeof(xrlast));
memset(&a, 0, sizeof(a));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&scaledbndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&scaledbndu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xrfirst, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xrlast, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
_minnsstate_init(&state, _state, ae_true);
_minnsreport_init(&rep, _state, ae_true);
passcount = 10;
maxn = 5;
/*
* First test:
* * sparse function
* * test that problem is successfully solved
* * non-unit scale is used, which results in badly conditioned problem
* * check that all iterates are feasible (box-constrained)
*/
for(pass=1; pass<=passcount; pass++)
{
for(n=1; n<=maxn; n++)
{
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&xc, n, _state);
ae_vector_set_length(&d, n, _state);
ae_vector_set_length(&s, n, _state);
ae_vector_set_length(&xrfirst, n, _state);
ae_vector_set_length(&xrlast, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 10*(2*ae_randomreal(_state)-1);
xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
d.ptr.p_double[i] = ae_pow((double)(10), 2*(2*ae_randomreal(_state)-1), _state);
s.ptr.p_double[i] = ae_pow((double)(10), 2*(2*ae_randomreal(_state)-1), _state);
bndl.ptr.p_double[i] = _state->v_neginf;
bndu.ptr.p_double[i] = _state->v_posinf;
k = ae_randominteger(5, _state);
if( k==1 )
{
bndl.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
if( k==2 )
{
bndu.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
if( k==3 )
{
v0 = 2*ae_randomreal(_state)-1;
v1 = 2*ae_randomreal(_state)-1;
bndl.ptr.p_double[i] = ae_minreal(v0, v1, _state);
bndu.ptr.p_double[i] = ae_maxreal(v0, v1, _state);
}
if( k==4 )
{
bndl.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
bndu.ptr.p_double[i] = bndl.ptr.p_double[i];
}
}
requirexrep = ae_fp_greater(ae_randomreal(_state),0.5);
epsrad = 0.01*ae_pow((double)(10), -2*ae_randomreal(_state), _state);
xtol = 15.0*epsrad;
minnscreate(n, &x0, &state, _state);
minnssetalgoags(&state, 0.1, 0.0, _state);
minnssetcond(&state, epsrad, 0, _state);
minnssetbc(&state, &bndl, &bndu, _state);
minnssetscale(&state, &s, _state);
if( requirexrep )
{
minnssetxrep(&state, ae_true, _state);
}
werexreports = ae_false;
repferr = 0.0;
while(minnsiteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = 0.0;
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
}
continue;
}
if( state.xupdated )
{
if( !werexreports )
{
ae_v_move(&xrfirst.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
}
ae_v_move(&xrlast.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
werexreports = ae_true;
v = 0.0;
for(i=0; i<=n-1; i++)
{
v = v+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
}
repferr = ae_maxreal(repferr, ae_fabs(v-state.f, _state), _state);
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(primaryerrors, ae_fp_less(state.x.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminnsunit.ap:944");
ae_set_error_flag(primaryerrors, ae_fp_greater(state.x.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminnsunit.ap:945");
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&state, &x1, &rep, _state);
ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:953");
ae_set_error_flag(othererrors, werexreports&&!requirexrep, __FILE__, __LINE__, "testminnsunit.ap:954");
ae_set_error_flag(othererrors, requirexrep&&!werexreports, __FILE__, __LINE__, "testminnsunit.ap:955");
ae_set_error_flag(othererrors, ae_fp_greater(repferr,10000*ae_machineepsilon), __FILE__, __LINE__, "testminnsunit.ap:956");
if( *primaryerrors||(*othererrors) )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(primaryerrors, !ae_isfinite(x1.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-boundval(xc.ptr.p_double[i], bndl.ptr.p_double[i], bndu.ptr.p_double[i], _state), _state)/s.ptr.p_double[i],xtol), __FILE__, __LINE__, "testminnsunit.ap:961");
ae_set_error_flag(primaryerrors, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminnsunit.ap:962");
ae_set_error_flag(primaryerrors, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminnsunit.ap:963");
if( requirexrep )
{
ae_set_error_flag(othererrors, !ae_isfinite(xrfirst.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(boundval(x0.ptr.p_double[i], bndl.ptr.p_double[i], bndu.ptr.p_double[i], _state)-xrfirst.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testminnsunit.ap:966");
ae_set_error_flag(othererrors, !ae_isfinite(xrlast.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-xrlast.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testminnsunit.ap:967");
}
}
}
}
/*
* A bit harder test:
* * dense quadratic function (smooth), may be prone to different
* rounding-related issues
* * non-negativity box constraints
* * unit scale is used
* * extreme stopping criteria (EpsX=1.0E-12)
* * single pass for each problem size
* * check that constrained gradient at solution is small
*/
conda = 1.0E3;
epsrad = 1.0E-12;
for(n=1; n<=10; n++)
{
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&b, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 1.0;
b.ptr.p_double[i] = ae_randomreal(_state)-0.5;
bndl.ptr.p_double[i] = 0.0;
bndu.ptr.p_double[i] = _state->v_posinf;
}
spdmatrixrndcond(n, conda, &a, _state);
minnscreate(n, &x0, &state, _state);
minnssetalgoags(&state, 0.1, 0.0, _state);
minnssetcond(&state, epsrad, 0, _state);
minnssetbc(&state, &bndl, &bndu, _state);
while(minnsiteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = 0.0;
for(i=0; i<=n-1; i++)
{
state.j.ptr.pp_double[0][i] = 0.0;
}
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+b.ptr.p_double[i]*state.x.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*a.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
for(i=0; i<=n-1; i++)
{
state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]+a.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&state, &x1, &rep, _state);
ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1030");
if( *primaryerrors||(*othererrors) )
{
ae_frame_leave(_state);
return;
}
gnorm = 0.0;
for(i=0; i<=n-1; i++)
{
v = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
v = v+a.ptr.pp_double[i][j]*x1.ptr.p_double[j];
}
if( ae_fp_eq(x1.ptr.p_double[i],bndl.ptr.p_double[i])&&ae_fp_greater(v,(double)(0)) )
{
v = (double)(0);
}
if( ae_fp_eq(x1.ptr.p_double[i],bndu.ptr.p_double[i])&&ae_fp_less(v,(double)(0)) )
{
v = (double)(0);
}
gnorm = gnorm+ae_sqr(v, _state);
ae_set_error_flag(primaryerrors, ae_fp_less(x1.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminnsunit.ap:1045");
ae_set_error_flag(primaryerrors, ae_fp_greater(x1.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminnsunit.ap:1046");
}
gnorm = ae_sqrt(gnorm, _state);
ae_set_error_flag(primaryerrors, ae_fp_greater(gnorm,1.0E-5), __FILE__, __LINE__, "testminnsunit.ap:1049");
}
/*
* Test on HIGHLY nonconvex bound constrained problem.
* Algorithm should be able to stop.
*
* NOTE: because algorithm can be attracted to saddle points,
* x[i] may be -1, +1 or approximately zero.
*/
for(pass=1; pass<=passcount; pass++)
{
for(n=1; n<=maxn; n++)
{
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = ae_randomreal(_state)-0.5;
bndl.ptr.p_double[i] = -1.0;
bndu.ptr.p_double[i] = 1.0;
}
epsrad = 0.0001;
xtol = 15.0*epsrad;
minnscreate(n, &x0, &state, _state);
minnssetalgoags(&state, 0.1, 0.0, _state);
minnssetcond(&state, epsrad, 0, _state);
minnssetbc(&state, &bndl, &bndu, _state);
v = -1000.0;
while(minnsiteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = 0.0;
for(i=0; i<=n-1; i++)
{
v0 = ae_fabs(state.x.ptr.p_double[i], _state);
v1 = (double)(ae_sign(state.x.ptr.p_double[i], _state));
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+v*(v0+v0*v0);
state.j.ptr.pp_double[0][i] = v*(v1+2*v0*v1);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&state, &x1, &rep, _state);
ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1095");
for(i=0; i<=n-1; i++)
{
v = ae_fabs(x1.ptr.p_double[i], _state);
ae_set_error_flag(primaryerrors, !ae_isfinite(x1.ptr.p_double[i], _state), __FILE__, __LINE__, "testminnsunit.ap:1099");
ae_set_error_flag(primaryerrors, ae_fp_neq(v,1.0)&&ae_fp_greater(v,xtol), __FILE__, __LINE__, "testminnsunit.ap:1100");
}
}
}
/*
* Test numerical differentiation:
* * test that problem is successfully solved
* * test that correct function value is reported
* * test that all iterates are within bound-constrained area
*/
for(pass=1; pass<=passcount; pass++)
{
for(n=1; n<=maxn; n++)
{
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xc, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&d, n, _state);
ae_vector_set_length(&s, n, _state);
ae_vector_set_length(&xrlast, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 10*(2*ae_randomreal(_state)-1);
xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
d.ptr.p_double[i] = ae_pow((double)(10), 2*(2*ae_randomreal(_state)-1), _state);
s.ptr.p_double[i] = ae_pow((double)(10), 2*(2*ae_randomreal(_state)-1), _state);
bndl.ptr.p_double[i] = _state->v_neginf;
bndu.ptr.p_double[i] = _state->v_posinf;
k = ae_randominteger(5, _state);
if( k==1 )
{
bndl.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
if( k==2 )
{
bndu.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
if( k==3 )
{
v0 = 2*ae_randomreal(_state)-1;
v1 = 2*ae_randomreal(_state)-1;
bndl.ptr.p_double[i] = ae_minreal(v0, v1, _state);
bndu.ptr.p_double[i] = ae_maxreal(v0, v1, _state);
}
if( k==4 )
{
bndl.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
bndu.ptr.p_double[i] = bndl.ptr.p_double[i];
}
}
epsrad = 0.01*ae_pow((double)(10), -2*ae_randomreal(_state), _state);
xtol = 15.0*epsrad;
minnscreatef(n, &x0, epsrad/100, &state, _state);
minnssetalgoags(&state, 0.1, 0.0, _state);
minnssetcond(&state, epsrad, 0, _state);
minnssetscale(&state, &s, _state);
minnssetbc(&state, &bndl, &bndu, _state);
minnssetxrep(&state, ae_true, _state);
repferr = 0.0;
while(minnsiteration(&state, _state))
{
if( state.needfi )
{
state.fi.ptr.p_double[0] = 0.0;
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
ae_set_error_flag(primaryerrors, ae_fp_less(state.x.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminnsunit.ap:1164");
ae_set_error_flag(primaryerrors, ae_fp_greater(state.x.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminnsunit.ap:1165");
}
continue;
}
if( state.xupdated )
{
v = 0.0;
for(i=0; i<=n-1; i++)
{
v = v+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
ae_set_error_flag(primaryerrors, ae_fp_less(state.x.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminnsunit.ap:1176");
ae_set_error_flag(primaryerrors, ae_fp_greater(state.x.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminnsunit.ap:1177");
}
repferr = ae_maxreal(repferr, ae_fabs(v-state.f, _state), _state);
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&state, &x1, &rep, _state);
ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1186");
ae_set_error_flag(othererrors, ae_fp_greater(repferr,10000*ae_machineepsilon), __FILE__, __LINE__, "testminnsunit.ap:1187");
if( *primaryerrors||(*othererrors) )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(primaryerrors, !ae_isfinite(x1.ptr.p_double[i], _state)||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-boundval(xc.ptr.p_double[i], bndl.ptr.p_double[i], bndu.ptr.p_double[i], _state), _state)/s.ptr.p_double[i],xtol), __FILE__, __LINE__, "testminnsunit.ap:1191");
}
}
}
/*
* Test scaling: we perform several steps on unit-scale problem,
* then we perform same amount of steps on re-scaled problem,
* starting from same point (but scaled according to chosen scale).
*
* Correctly written optimizer should perform essentially same steps
* (up to scale) on both problems. At least, it holds within first
* several steps, before rounding errors start to accumulate.
*
* NOTE: we also check that correctly scaled points are reported.
* And, as side effect, we check MinNSRestartFrom().
*
* NOTE: we use very low scale and diagonal coefficients in order
* to have well-conditioned system. We test correctness of
* formulae here, not robustness of algorithm.
*/
for(pass=1; pass<=passcount; pass++)
{
for(n=1; n<=maxn; n++)
{
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xc, n, _state);
ae_vector_set_length(&x0s, n, _state);
ae_vector_set_length(&d, n, _state);
ae_vector_set_length(&s, n, _state);
ae_vector_set_length(&xrlast, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
ae_vector_set_length(&scaledbndl, n, _state);
ae_vector_set_length(&scaledbndu, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = ae_pow((double)(10), ae_randomreal(_state)-0.5, _state);
d.ptr.p_double[i] = ae_pow((double)(10), ae_randomreal(_state)-0.5, _state);
x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x0s.ptr.p_double[i] = x0.ptr.p_double[i]*s.ptr.p_double[i];
bndl.ptr.p_double[i] = _state->v_neginf;
bndu.ptr.p_double[i] = _state->v_posinf;
k = ae_randominteger(5, _state);
if( k==1 )
{
bndl.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
if( k==2 )
{
bndu.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
if( k==3 )
{
v0 = 2*ae_randomreal(_state)-1;
v1 = 2*ae_randomreal(_state)-1;
bndl.ptr.p_double[i] = ae_minreal(v0, v1, _state);
bndu.ptr.p_double[i] = ae_maxreal(v0, v1, _state);
}
if( k==4 )
{
bndl.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
bndu.ptr.p_double[i] = bndl.ptr.p_double[i];
}
scaledbndl.ptr.p_double[i] = bndl.ptr.p_double[i]*s.ptr.p_double[i];
scaledbndu.ptr.p_double[i] = bndu.ptr.p_double[i]*s.ptr.p_double[i];
}
minnscreate(n, &x0, &state, _state);
minnssetalgoags(&state, 0.01, 0.0, _state);
minnssetcond(&state, 0.0, testminnsunit_scalingtestcnt, _state);
minnssetbc(&state, &bndl, &bndu, _state);
minnssetxrep(&state, ae_false, _state);
while(minnsiteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = 0.0;
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&state, &x1, &rep, _state);
ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1272");
if( *primaryerrors||(*othererrors) )
{
ae_frame_leave(_state);
return;
}
minnssetscale(&state, &s, _state);
minnssetbc(&state, &scaledbndl, &scaledbndu, _state);
minnsrestartfrom(&state, &x0s, _state);
while(minnsiteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = 0.0;
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]/s.ptr.p_double[i]-xc.ptr.p_double[i], _state);
state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(state.x.ptr.p_double[i]/s.ptr.p_double[i]-xc.ptr.p_double[i], _state)/s.ptr.p_double[i];
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&state, &x1s, &rep, _state);
ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1293");
if( *primaryerrors||(*othererrors) )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(primaryerrors, (!ae_isfinite(x1.ptr.p_double[i], _state)||!ae_isfinite(x1s.ptr.p_double[i], _state))||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-x1s.ptr.p_double[i]/s.ptr.p_double[i], _state),testminnsunit_scalingtesttol), __FILE__, __LINE__, "testminnsunit.ap:1297");
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Linearly constrained test
*************************************************************************/
static void testminnsunit_testlc(ae_bool* primaryerrors,
ae_bool* othererrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t nc;
ae_vector x0;
ae_vector x0s;
ae_vector x1;
ae_vector x2;
ae_vector x1s;
ae_vector d;
ae_vector xc;
ae_vector s;
ae_vector bndl;
ae_vector bndu;
ae_matrix c;
ae_matrix scaledc;
ae_vector ct;
ae_vector scaledbndl;
ae_vector scaledbndu;
ae_vector xrfirst;
ae_vector xrlast;
minnsstate state;
minnsreport rep;
double v;
double v0;
double v1;
double vv;
double flast0;
double flast1;
ae_int_t pass;
double epsrad;
double repferr;
double xtol;
double ftol;
double rho;
ae_frame_make(_state, &_frame_block);
memset(&x0, 0, sizeof(x0));
memset(&x0s, 0, sizeof(x0s));
memset(&x1, 0, sizeof(x1));
memset(&x2, 0, sizeof(x2));
memset(&x1s, 0, sizeof(x1s));
memset(&d, 0, sizeof(d));
memset(&xc, 0, sizeof(xc));
memset(&s, 0, sizeof(s));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(&c, 0, sizeof(c));
memset(&scaledc, 0, sizeof(scaledc));
memset(&ct, 0, sizeof(ct));
memset(&scaledbndl, 0, sizeof(scaledbndl));
memset(&scaledbndu, 0, sizeof(scaledbndu));
memset(&xrfirst, 0, sizeof(xrfirst));
memset(&xrlast, 0, sizeof(xrlast));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&scaledc, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
ae_vector_init(&scaledbndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&scaledbndu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xrfirst, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xrlast, 0, DT_REAL, _state, ae_true);
_minnsstate_init(&state, _state, ae_true);
_minnsreport_init(&rep, _state, ae_true);
for(pass=1; pass<=10; pass++)
{
for(n=1; n<=5; n++)
{
/*
* First test:
* * smooth problem
* * subject to random linear constraints
* * with non-unit scale
*
* We:
* * compare function value at constrained solution with function
* value for penalized unconstrained problem. We do not compare
* actual X-values returned, because they are highly unstable -
* function values at minimum show better stability.
* * check that correct function values are reported
*/
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xc, n, _state);
ae_vector_set_length(&d, n, _state);
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 10*(2*ae_randomreal(_state)-1);
xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
d.ptr.p_double[i] = 1+ae_randomreal(_state);
s.ptr.p_double[i] = 1+ae_randomreal(_state);
}
nc = ae_randominteger((n+1)/2, _state);
if( nc>0 )
{
ae_matrix_set_length(&c, nc, n+1, _state);
ae_vector_set_length(&ct, nc, _state);
for(i=0; i<=nc-1; i++)
{
ct.ptr.p_int[i] = ae_randominteger(3, _state)-1;
for(j=0; j<=n; j++)
{
c.ptr.pp_double[i][j] = ae_randomreal(_state)-0.5;
}
}
}
epsrad = 0.00001;
ftol = 0.01;
minnscreate(n, &x0, &state, _state);
minnssetalgoags(&state, 0.1, 0.0, _state);
minnssetcond(&state, epsrad, 0, _state);
minnssetscale(&state, &s, _state);
minnssetxrep(&state, ae_true, _state);
minnssetlc(&state, &c, &ct, nc, _state);
repferr = 0.0;
flast0 = _state->v_nan;
while(minnsiteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = 0.0;
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_sqr(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*(2*(state.x.ptr.p_double[i]-xc.ptr.p_double[i]));
}
continue;
}
if( state.xupdated )
{
flast0 = 0.0;
for(i=0; i<=n-1; i++)
{
flast0 = flast0+d.ptr.p_double[i]*ae_sqr(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
}
repferr = ae_maxreal(repferr, ae_fabs(flast0-state.f, _state), _state);
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&state, &x1, &rep, _state);
ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1402");
ae_set_error_flag(primaryerrors, !ae_isfinite(flast0, _state), __FILE__, __LINE__, "testminnsunit.ap:1403");
ae_set_error_flag(othererrors, ae_fp_greater(repferr,10000*ae_machineepsilon), __FILE__, __LINE__, "testminnsunit.ap:1404");
if( *primaryerrors||(*othererrors) )
{
ae_frame_leave(_state);
return;
}
minnssetlc(&state, &c, &ct, 0, _state);
minnsrestartfrom(&state, &x0, _state);
rho = 1000.0;
repferr = 0.0;
flast1 = _state->v_nan;
while(minnsiteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = 0.0;
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_sqr(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*(2*(state.x.ptr.p_double[i]-xc.ptr.p_double[i]));
}
for(i=0; i<=nc-1; i++)
{
v = ae_v_dotproduct(&state.x.ptr.p_double[0], 1, &c.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
v = v-c.ptr.pp_double[i][n];
vv = 0.0;
if( ct.ptr.p_int[i]<0 )
{
vv = (double)(ae_sign(ae_maxreal(v, 0.0, _state), _state));
v = ae_maxreal(v, 0.0, _state);
}
if( ct.ptr.p_int[i]==0 )
{
vv = (double)(ae_sign(v, _state));
v = ae_fabs(v, _state);
}
if( ct.ptr.p_int[i]>0 )
{
vv = (double)(-ae_sign(ae_maxreal(-v, 0.0, _state), _state));
v = ae_maxreal(-v, 0.0, _state);
}
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+rho*v;
for(j=0; j<=n-1; j++)
{
state.j.ptr.pp_double[0][j] = state.j.ptr.pp_double[0][j]+rho*vv*c.ptr.pp_double[i][j];
}
}
continue;
}
if( state.xupdated )
{
flast1 = 0.0;
for(i=0; i<=n-1; i++)
{
flast1 = flast1+d.ptr.p_double[i]*ae_sqr(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&state, &x2, &rep, _state);
ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1462");
ae_set_error_flag(primaryerrors, !ae_isfinite(flast1, _state), __FILE__, __LINE__, "testminnsunit.ap:1463");
if( *primaryerrors||(*othererrors) )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(primaryerrors, ae_fp_greater(ae_fabs(flast0-flast1, _state),ftol), __FILE__, __LINE__, "testminnsunit.ap:1466");
/*
* Test on HIGHLY nonconvex linearly constrained problem.
* Algorithm should be able to stop at the bounds.
*/
ae_vector_set_length(&x0, n, _state);
ae_matrix_set_length(&c, 2*n, n+1, _state);
ae_vector_set_length(&ct, 2*n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = ae_randomreal(_state)-0.5;
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[2*i+0][j] = 0.0;
c.ptr.pp_double[2*i+1][j] = 0.0;
}
c.ptr.pp_double[2*i+0][i] = 1.0;
c.ptr.pp_double[2*i+0][n] = -1.0;
ct.ptr.p_int[2*i+0] = 1;
c.ptr.pp_double[2*i+1][i] = 1.0;
c.ptr.pp_double[2*i+1][n] = 1.0;
ct.ptr.p_int[2*i+1] = -1;
}
epsrad = 0.0001;
xtol = 15.0*epsrad;
minnscreate(n, &x0, &state, _state);
minnssetalgoags(&state, 0.1, 0.0, _state);
minnssetcond(&state, epsrad, 0, _state);
minnssetlc(&state, &c, &ct, 2*n, _state);
v = -1000.0;
while(minnsiteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = 0.0;
for(i=0; i<=n-1; i++)
{
v0 = ae_fabs(state.x.ptr.p_double[i], _state);
v1 = (double)(ae_sign(state.x.ptr.p_double[i], _state));
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+v*(v0+v0*v0);
state.j.ptr.pp_double[0][i] = v*(v1+2*v0*v1);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&state, &x1, &rep, _state);
ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1516");
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(primaryerrors, !ae_isfinite(x1.ptr.p_double[i], _state), __FILE__, __LINE__, "testminnsunit.ap:1519");
ae_set_error_flag(primaryerrors, (ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-1, _state),xtol)&&ae_fp_greater(ae_fabs(x1.ptr.p_double[i], _state),xtol))&&ae_fp_greater(ae_fabs(x1.ptr.p_double[i]+1, _state),xtol), __FILE__, __LINE__, "testminnsunit.ap:1520");
}
/*
* Test scaling: we perform several steps on unit-scale problem,
* then we perform same amount of steps on re-scaled problem,
* starting from same point (but scaled according to chosen scale).
*
* Correctly written optimizer should perform essentially same steps
* (up to scale) on both problems. At least, it holds within first
* several steps, before rounding errors start to accumulate.
*
* NOTE: we also check that correctly scaled points are reported.
* And, as side effect, we check MinNSRestartFrom().
*
* NOTE: we use moderate scale and diagonal coefficients in order
* to have well-conditioned system. We test correctness of
* formulae here, not robustness of algorithm.
*/
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xc, n, _state);
ae_vector_set_length(&x0s, n, _state);
ae_vector_set_length(&d, n, _state);
ae_vector_set_length(&s, n, _state);
ae_vector_set_length(&xrlast, n, _state);
ae_matrix_set_length(&c, 2*n, n+1, _state);
ae_matrix_set_length(&scaledc, 2*n, n+1, _state);
ae_vector_set_length(&ct, 2*n, _state);
for(i=0; i<=2*n-1; i++)
{
ct.ptr.p_int[i] = 0;
for(j=0; j<=n; j++)
{
c.ptr.pp_double[i][j] = (double)(0);
}
}
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = ae_pow((double)(10), 2*ae_randomreal(_state)-1, _state);
d.ptr.p_double[i] = ae_pow((double)(10), 2*ae_randomreal(_state)-1, _state);
x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x0s.ptr.p_double[i] = x0.ptr.p_double[i]*s.ptr.p_double[i];
k = ae_randominteger(5, _state);
if( k==1 )
{
c.ptr.pp_double[2*i+0][i] = 1.0;
c.ptr.pp_double[2*i+0][n] = 2*ae_randomreal(_state)-1;
ct.ptr.p_int[2*i+0] = 1;
}
if( k==2 )
{
c.ptr.pp_double[2*i+0][i] = 1.0;
c.ptr.pp_double[2*i+0][n] = 2*ae_randomreal(_state)-1;
ct.ptr.p_int[2*i+0] = -1;
}
if( k==3 )
{
v0 = 2*ae_randomreal(_state)-1;
v1 = 2*ae_randomreal(_state)-1;
c.ptr.pp_double[2*i+0][i] = 1.0;
c.ptr.pp_double[2*i+0][n] = ae_minreal(v0, v1, _state);
c.ptr.pp_double[2*i+1][i] = 1.0;
c.ptr.pp_double[2*i+1][n] = ae_maxreal(v0, v1, _state);
ct.ptr.p_int[2*i+0] = 1;
ct.ptr.p_int[2*i+1] = -1;
}
if( k==4 )
{
c.ptr.pp_double[2*i+0][i] = 1.0;
c.ptr.pp_double[2*i+0][n] = 2*ae_randomreal(_state)-1;
ct.ptr.p_int[2*i+0] = 0;
}
}
for(i=0; i<=2*n-1; i++)
{
for(j=0; j<=n-1; j++)
{
scaledc.ptr.pp_double[i][j] = c.ptr.pp_double[i][j]/s.ptr.p_double[j];
}
scaledc.ptr.pp_double[i][n] = c.ptr.pp_double[i][n];
}
minnscreate(n, &x0, &state, _state);
minnssetalgoags(&state, 0.1, 0.0, _state);
minnssetcond(&state, 0.0, testminnsunit_scalingtestcnt, _state);
minnssetlc(&state, &c, &ct, 2*n, _state);
minnssetxrep(&state, ae_false, _state);
while(minnsiteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = 0.0;
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&state, &x1, &rep, _state);
ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1622");
if( *primaryerrors||(*othererrors) )
{
ae_frame_leave(_state);
return;
}
minnssetscale(&state, &s, _state);
minnssetlc(&state, &scaledc, &ct, 2*n, _state);
minnsrestartfrom(&state, &x0s, _state);
while(minnsiteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = 0.0;
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]/s.ptr.p_double[i]-xc.ptr.p_double[i], _state);
state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(state.x.ptr.p_double[i]/s.ptr.p_double[i]-xc.ptr.p_double[i], _state)/s.ptr.p_double[i];
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&state, &x1s, &rep, _state);
ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1643");
if( *primaryerrors||(*othererrors) )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(primaryerrors, (!ae_isfinite(x1.ptr.p_double[i], _state)||!ae_isfinite(x1s.ptr.p_double[i], _state))||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-x1s.ptr.p_double[i]/s.ptr.p_double[i], _state),testminnsunit_scalingtesttol), __FILE__, __LINE__, "testminnsunit.ap:1647");
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Nonlinearly constrained test
*************************************************************************/
static void testminnsunit_testnlc(ae_bool* primaryerrors,
ae_bool* othererrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_int_t nc;
ae_int_t nec;
ae_vector x0;
ae_vector x0s;
ae_vector x1;
ae_vector x2;
ae_vector x1s;
ae_vector d;
ae_vector xc;
ae_vector s;
ae_vector bndl;
ae_vector bndu;
ae_vector b;
ae_vector r;
ae_matrix c;
ae_matrix scaledc;
ae_vector ct;
ae_vector scaledbndl;
ae_vector scaledbndu;
ae_vector xrfirst;
ae_vector xrlast;
minnsstate state;
minnsreport rep;
double v;
ae_int_t pass;
ae_int_t passcount;
double epsrad;
double xtol;
double rho;
ae_int_t maxn;
double diffstep;
ae_frame_make(_state, &_frame_block);
memset(&x0, 0, sizeof(x0));
memset(&x0s, 0, sizeof(x0s));
memset(&x1, 0, sizeof(x1));
memset(&x2, 0, sizeof(x2));
memset(&x1s, 0, sizeof(x1s));
memset(&d, 0, sizeof(d));
memset(&xc, 0, sizeof(xc));
memset(&s, 0, sizeof(s));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(&b, 0, sizeof(b));
memset(&r, 0, sizeof(r));
memset(&c, 0, sizeof(c));
memset(&scaledc, 0, sizeof(scaledc));
memset(&ct, 0, sizeof(ct));
memset(&scaledbndl, 0, sizeof(scaledbndl));
memset(&scaledbndu, 0, sizeof(scaledbndu));
memset(&xrfirst, 0, sizeof(xrfirst));
memset(&xrlast, 0, sizeof(xrlast));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&r, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&scaledc, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
ae_vector_init(&scaledbndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&scaledbndu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xrfirst, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xrlast, 0, DT_REAL, _state, ae_true);
_minnsstate_init(&state, _state, ae_true);
_minnsreport_init(&rep, _state, ae_true);
passcount = 10;
maxn = 5;
rho = 100.0;
/*
* First test:
* * simple problem
* * subject to random nonlinear constraints of form r[i]*x[i] OPERATION 0.0,
* where OPERATION is <= or =
* * with non-unit scale
*
* We:
* * compare numerical solution with analytic one, which can be
* easily calculated
*/
for(pass=1; pass<=passcount; pass++)
{
for(n=1; n<=maxn; n++)
{
for(nc=1; nc<=n; nc++)
{
for(nec=0; nec<=nc; nec++)
{
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xc, n, _state);
ae_vector_set_length(&d, n, _state);
ae_vector_set_length(&r, n, _state);
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
xc.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
d.ptr.p_double[i] = ae_pow((double)(10), ae_randomreal(_state)-0.5, _state);
s.ptr.p_double[i] = ae_pow((double)(10), ae_randomreal(_state)-0.5, _state);
r.ptr.p_double[i] = (2*ae_randominteger(2, _state)-1)*(0.1+ae_randomreal(_state));
}
epsrad = 0.001;
xtol = 0.01;
minnscreate(n, &x0, &state, _state);
minnssetalgoags(&state, 0.1, rho, _state);
minnssetcond(&state, epsrad, 0, _state);
minnssetscale(&state, &s, _state);
minnssetnlc(&state, nec, nc-nec, _state);
while(minnsiteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = 0.0;
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+d.ptr.p_double[i]*ae_fabs(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
state.j.ptr.pp_double[0][i] = d.ptr.p_double[i]*ae_sign(state.x.ptr.p_double[i]-xc.ptr.p_double[i], _state);
}
for(i=1; i<=nc; i++)
{
state.fi.ptr.p_double[i] = state.x.ptr.p_double[i-1]*r.ptr.p_double[i-1];
for(j=0; j<=n-1; j++)
{
state.j.ptr.pp_double[i][j] = 0.0;
}
state.j.ptr.pp_double[i][i-1] = r.ptr.p_double[i-1];
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minnsresults(&state, &x1, &rep, _state);
ae_set_error_flag(primaryerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminnsunit.ap:1743");
if( *primaryerrors||(*othererrors) )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
v = xc.ptr.p_double[i];
if( i=nec&&i=nec&&i=0.999999
*
* where c is either 1.0 or 1.0E+6, M is either 1.0E8, 1.0E20 or +INF
* (we try different combinations)
*/
for(ckind=0; ckind<=1; ckind++)
{
for(mkind=0; mkind<=2; mkind++)
{
/*
* Choose c and M
*/
vc = 1.0;
vm = 1.0E+8;
if( ckind==1 )
{
vc = 1.0E+6;
}
if( mkind==1 )
{
vm = 1.0E+20;
}
if( mkind==2 )
{
vm = _state->v_posinf;
}
/*
* Create optimizer, solve optimization problem
*/
epsg = 1.0E-6*vc;
ae_vector_set_length(&x, 1, _state);
x.ptr.p_double[0] = 0.0;
mincgcreate(1, &x, &state, _state);
mincgsetcond(&state, epsg, (double)(0), (double)(0), 0, _state);
mincgsetcgtype(&state, cgtype, _state);
while(mincgiteration(&state, _state))
{
if( state.needfg )
{
if( ae_fp_less(-0.999999,state.x.ptr.p_double[0])&&ae_fp_less(state.x.ptr.p_double[0],0.999999) )
{
state.f = 1/(1-state.x.ptr.p_double[0])+1/(1+state.x.ptr.p_double[0])+vc*state.x.ptr.p_double[0];
state.g.ptr.p_double[0] = 1/ae_sqr(1-state.x.ptr.p_double[0], _state)-1/ae_sqr(1+state.x.ptr.p_double[0], _state)+vc;
}
else
{
state.f = vm;
}
}
}
mincgresults(&state, &x, &rep, _state);
if( rep.terminationtype<=0 )
{
*err = ae_true;
ae_frame_leave(_state);
return;
}
*err = *err||ae_fp_greater(ae_fabs(1/ae_sqr(1-x.ptr.p_double[0], _state)-1/ae_sqr(1+x.ptr.p_double[0], _state)+vc, _state),epsg);
}
}
}
/*
* Test integrity checks for NAN/INF:
* * algorithm solves optimization problem, which is normal for some time (quadratic)
* * after 5-th step we choose random component of gradient and consistently spoil
* it by NAN or INF.
* * we check that correct termination code is returned (-8)
*/
n = 100;
for(pass=1; pass<=10; pass++)
{
spoiliteration = 5;
stopiteration = 8;
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
/*
* Gradient can be spoiled by +INF, -INF, NAN
*/
spoilvar = hqrnduniformi(&rs, n, _state);
i = hqrnduniformi(&rs, 3, _state);
spoilval = _state->v_nan;
if( i==0 )
{
spoilval = _state->v_neginf;
}
if( i==1 )
{
spoilval = _state->v_posinf;
}
}
else
{
/*
* Function value can be spoiled only by NAN
* (+INF can be recognized as legitimate value during optimization)
*/
spoilvar = -1;
spoilval = _state->v_nan;
}
spdmatrixrndcond(n, 1.0E5, &fulla, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
mincgcreate(n, &x0, &state, _state);
mincgsetcond(&state, 0.0, 0.0, 0.0, stopiteration, _state);
mincgsetxrep(&state, ae_true, _state);
k = -1;
while(mincgiteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.g.ptr.p_double[i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.f = state.f+0.5*state.x.ptr.p_double[i]*fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.g.ptr.p_double[i] = state.g.ptr.p_double[i]+fulla.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
if( k>=spoiliteration )
{
if( spoilvar<0 )
{
state.f = spoilval;
}
else
{
state.g.ptr.p_double[spoilvar] = spoilval;
}
}
continue;
}
if( state.xupdated )
{
inc(&k, _state);
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
mincgresults(&state, &x1, &rep, _state);
ae_set_error_flag(err, rep.terminationtype!=-8, __FILE__, __LINE__, "testmincgunit.ap:1151");
}
/*
* Check algorithm ability to handle request for termination:
* * to terminate with correct return code = 8
* * to return point which was "current" at the moment of termination
*/
for(pass=1; pass<=50; pass++)
{
n = 3;
ss = (double)(100);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&xlast, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 6+ae_randomreal(_state);
}
stopcallidx = ae_randominteger(20, _state);
maxits = 25;
mincgcreate(n, &x, &state, _state);
mincgsetcond(&state, (double)(0), (double)(0), (double)(0), maxits, _state);
mincgsetxrep(&state, ae_true, _state);
callidx = 0;
terminationrequested = ae_false;
ae_v_move(&xlast.ptr.p_double[0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1));
while(mincgiteration(&state, _state))
{
if( state.needfg )
{
state.f = ss*ae_sqr(ae_exp(state.x.ptr.p_double[0], _state)-2, _state)+ae_sqr(state.x.ptr.p_double[1], _state)+ae_sqr(state.x.ptr.p_double[2]-state.x.ptr.p_double[0], _state);
state.g.ptr.p_double[0] = 2*ss*(ae_exp(state.x.ptr.p_double[0], _state)-2)*ae_exp(state.x.ptr.p_double[0], _state)+2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0])*(-1);
state.g.ptr.p_double[1] = 2*state.x.ptr.p_double[1];
state.g.ptr.p_double[2] = 2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0]);
if( callidx==stopcallidx )
{
mincgrequesttermination(&state, _state);
terminationrequested = ae_true;
}
inc(&callidx, _state);
continue;
}
if( state.xupdated )
{
if( !terminationrequested )
{
ae_v_move(&xlast.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
mincgresults(&state, &x, &rep, _state);
ae_set_error_flag(err, rep.terminationtype!=8, __FILE__, __LINE__, "testmincgunit.ap:1201");
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(err, ae_fp_neq(x.ptr.p_double[i],xlast.ptr.p_double[i]), __FILE__, __LINE__, "testmincgunit.ap:1203");
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Calculate test function #2
Simple variation of #1, much more nonlinear, which makes unlikely premature
convergence of algorithm .
*************************************************************************/
static void testmincgunit_testfunc2(mincgstate* state, ae_state *_state)
{
if( ae_fp_less(state->x.ptr.p_double[0],(double)(100)) )
{
if( state->needf||state->needfg )
{
state->f = ae_sqr(ae_exp(state->x.ptr.p_double[0], _state)-2, _state)+ae_sqr(ae_sqr(state->x.ptr.p_double[1], _state), _state)+ae_sqr(state->x.ptr.p_double[2]-state->x.ptr.p_double[0], _state);
}
if( state->needfg )
{
state->g.ptr.p_double[0] = 2*(ae_exp(state->x.ptr.p_double[0], _state)-2)*ae_exp(state->x.ptr.p_double[0], _state)+2*(state->x.ptr.p_double[0]-state->x.ptr.p_double[2]);
state->g.ptr.p_double[1] = 4*state->x.ptr.p_double[1]*ae_sqr(state->x.ptr.p_double[1], _state);
state->g.ptr.p_double[2] = 2*(state->x.ptr.p_double[2]-state->x.ptr.p_double[0]);
}
}
else
{
if( state->needf||state->needfg )
{
state->f = ae_sqrt(ae_maxrealnumber, _state);
}
if( state->needfg )
{
state->g.ptr.p_double[0] = ae_sqrt(ae_maxrealnumber, _state);
state->g.ptr.p_double[1] = (double)(0);
state->g.ptr.p_double[2] = (double)(0);
}
}
}
/*************************************************************************
Calculate test function #3
Simple variation of #1, much more nonlinear, with non-zero value at minimum.
It achieve two goals:
* makes unlikely premature convergence of algorithm .
* solves some issues with EpsF stopping condition which arise when
F(minimum) is zero
*************************************************************************/
static void testmincgunit_testfunc3(mincgstate* state, ae_state *_state)
{
double s;
s = 0.001;
if( ae_fp_less(state->x.ptr.p_double[0],(double)(100)) )
{
if( state->needf||state->needfg )
{
state->f = ae_sqr(ae_exp(state->x.ptr.p_double[0], _state)-2, _state)+ae_sqr(ae_sqr(state->x.ptr.p_double[1], _state)+s, _state)+ae_sqr(state->x.ptr.p_double[2]-state->x.ptr.p_double[0], _state);
}
if( state->needfg )
{
state->g.ptr.p_double[0] = 2*(ae_exp(state->x.ptr.p_double[0], _state)-2)*ae_exp(state->x.ptr.p_double[0], _state)+2*(state->x.ptr.p_double[0]-state->x.ptr.p_double[2]);
state->g.ptr.p_double[1] = 2*(ae_sqr(state->x.ptr.p_double[1], _state)+s)*2*state->x.ptr.p_double[1];
state->g.ptr.p_double[2] = 2*(state->x.ptr.p_double[2]-state->x.ptr.p_double[0]);
}
}
else
{
if( state->needf||state->needfg )
{
state->f = ae_sqrt(ae_maxrealnumber, _state);
}
if( state->needfg )
{
state->g.ptr.p_double[0] = ae_sqrt(ae_maxrealnumber, _state);
state->g.ptr.p_double[1] = (double)(0);
state->g.ptr.p_double[2] = (double)(0);
}
}
}
/*************************************************************************
Calculate test function IIP2
f(x) = sum( ((i*i+1)*x[i])^2, i=0..N-1)
It has high condition number which makes fast convergence unlikely without
good preconditioner.
*************************************************************************/
static void testmincgunit_calciip2(mincgstate* state,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
if( state->needf||state->needfg )
{
state->f = (double)(0);
}
for(i=0; i<=n-1; i++)
{
if( state->needf||state->needfg )
{
state->f = state->f+ae_sqr((double)(i*i+1), _state)*ae_sqr(state->x.ptr.p_double[i], _state);
}
if( state->needfg )
{
state->g.ptr.p_double[i] = ae_sqr((double)(i*i+1), _state)*2*state->x.ptr.p_double[i];
}
}
}
/*************************************************************************
Calculate test function f(x) = 0.5*(x-x0)'*A*(x-x0), A = D+V'*Vd*V
*************************************************************************/
static void testmincgunit_calclowrank(mincgstate* state,
ae_int_t n,
ae_int_t vcnt,
/* Real */ ae_vector* d,
/* Real */ ae_matrix* v,
/* Real */ ae_vector* vd,
/* Real */ ae_vector* x0,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
double dx;
double t;
double t2;
state->f = (double)(0);
for(i=0; i<=n-1; i++)
{
state->g.ptr.p_double[i] = (double)(0);
}
for(i=0; i<=n-1; i++)
{
dx = state->x.ptr.p_double[i]-x0->ptr.p_double[i];
state->f = state->f+0.5*dx*d->ptr.p_double[i]*dx;
state->g.ptr.p_double[i] = state->g.ptr.p_double[i]+d->ptr.p_double[i]*dx;
}
for(i=0; i<=vcnt-1; i++)
{
t = (double)(0);
for(j=0; j<=n-1; j++)
{
t = t+v->ptr.pp_double[i][j]*(state->x.ptr.p_double[j]-x0->ptr.p_double[j]);
}
state->f = state->f+0.5*t*vd->ptr.p_double[i]*t;
t2 = t*vd->ptr.p_double[i];
ae_v_addd(&state->g.ptr.p_double[0], 1, &v->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), t2);
}
}
/*************************************************************************
This function tests preconditioning
On failure sets Err to True (leaves it unchanged otherwise)
*************************************************************************/
static void testmincgunit_testpreconditioning(ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t pass;
ae_int_t n;
ae_vector x;
ae_vector x0;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t vs;
ae_matrix v;
ae_vector vd;
ae_vector d;
ae_vector s;
ae_int_t cntb1;
ae_int_t cntg1;
ae_int_t cntb2;
ae_int_t cntg2;
ae_vector diagh;
mincgstate state;
mincgreport rep;
ae_int_t cgtype;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&x0, 0, sizeof(x0));
memset(&v, 0, sizeof(v));
memset(&vd, 0, sizeof(vd));
memset(&d, 0, sizeof(d));
memset(&s, 0, sizeof(s));
memset(&diagh, 0, sizeof(diagh));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&vd, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&diagh, 0, DT_REAL, _state, ae_true);
_mincgstate_init(&state, _state, ae_true);
_mincgreport_init(&rep, _state, ae_true);
k = 50;
for(cgtype=-1; cgtype<=1; cgtype++)
{
/*
* Preconditioner test 1.
*
* If
* * B1 is default preconditioner
* * G1 is diagonal precomditioner based on approximate diagonal of Hessian matrix
* then "bad" preconditioner is worse than "good" one.
* "Worse" means more iterations to converge.
*
*
* We test it using f(x) = sum( ((i*i+1)*x[i])^2, i=0..N-1).
*
* N - problem size
* K - number of repeated passes (should be large enough to average out random factors)
*/
for(n=10; n<=15; n++)
{
ae_vector_set_length(&x, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = (double)(0);
}
mincgcreate(n, &x, &state, _state);
mincgsetcgtype(&state, cgtype, _state);
/*
* Test it with default preconditioner
*/
mincgsetprecdefault(&state, _state);
cntb1 = 0;
for(pass=0; pass<=k-1; pass++)
{
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
mincgrestartfrom(&state, &x, _state);
while(mincgiteration(&state, _state))
{
testmincgunit_calciip2(&state, n, _state);
}
mincgresults(&state, &x, &rep, _state);
cntb1 = cntb1+rep.iterationscount;
*err = *err||rep.terminationtype<=0;
}
/*
* Test it with perturbed diagonal preconditioner
*/
ae_vector_set_length(&diagh, n, _state);
for(i=0; i<=n-1; i++)
{
diagh.ptr.p_double[i] = 2*ae_sqr((double)(i*i+1), _state)*(0.8+0.4*ae_randomreal(_state));
}
mincgsetprecdiag(&state, &diagh, _state);
cntg1 = 0;
for(pass=0; pass<=k-1; pass++)
{
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
mincgrestartfrom(&state, &x, _state);
while(mincgiteration(&state, _state))
{
testmincgunit_calciip2(&state, n, _state);
}
mincgresults(&state, &x, &rep, _state);
cntg1 = cntg1+rep.iterationscount;
*err = *err||rep.terminationtype<=0;
}
/*
* Compare
*/
*err = *err||cntb10 )
{
ae_matrix_set_length(&v, vs, n, _state);
ae_vector_set_length(&vd, vs, _state);
for(i=0; i<=vs-1; i++)
{
for(j=0; j<=n-1; j++)
{
v.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
vd.ptr.p_double[i] = ae_exp(2*ae_randomreal(_state), _state);
}
}
mincgcreate(n, &x, &state, _state);
mincgsetcgtype(&state, cgtype, _state);
/*
* Test it with default preconditioner
*/
mincgsetprecdefault(&state, _state);
cntb1 = 0;
for(pass=0; pass<=k-1; pass++)
{
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
mincgrestartfrom(&state, &x, _state);
while(mincgiteration(&state, _state))
{
testmincgunit_calclowrank(&state, n, vs, &d, &v, &vd, &x0, _state);
}
mincgresults(&state, &x, &rep, _state);
cntb1 = cntb1+rep.iterationscount;
*err = *err||rep.terminationtype<=0;
}
/*
* Test it with low rank preconditioner
*/
mincgsetpreclowrankfast(&state, &d, &vd, &v, vs, _state);
cntg1 = 0;
for(pass=0; pass<=k-1; pass++)
{
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
mincgrestartfrom(&state, &x, _state);
while(mincgiteration(&state, _state))
{
testmincgunit_calclowrank(&state, n, vs, &d, &v, &vd, &x0, _state);
}
mincgresults(&state, &x, &rep, _state);
cntg1 = cntg1+rep.iterationscount;
*err = *err||rep.terminationtype<=0;
}
/*
* Compare
*/
*err = *err||cntb1=0, __FILE__, __LINE__, "testmincgunit.ap:1336");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx>=0, __FILE__, __LINE__, "testmincgunit.ap:1337");
ae_set_error_flag(wereerrors, ogrep.nonc1test0positive, __FILE__, __LINE__, "testmincgunit.ap:1338");
ae_set_error_flag(wereerrors, ogrep.nonc1test1positive, __FILE__, __LINE__, "testmincgunit.ap:1339");
/*
* Test gradient checking functionality, try various
* defect types:
* * accidental zeroing of some gradient component
* * accidental addition of 1.0 to some component
* * accidental multiplication by 2.0
* Try distorting both target and constraints.
*/
diffstep = 0.001;
n = 10;
for(skind=0; skind<=1; skind++)
{
for(defecttype=-1; defecttype<=2; defecttype++)
{
varidx = hqrnduniformi(&rs, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = ae_pow((double)(10), skind*(30*hqrnduniformr(&rs, _state)-15), _state);
x0.ptr.p_double[i] = (1.0+0.1*i)*s.ptr.p_double[i];
}
spdmatrixrndcond(n, 1.0E3, &a, _state);
spdmatrixrndcond(n, 1.0E3, &a1, _state);
mincgcreate(n, &x0, &state, _state);
mincgoptguardgradient(&state, diffstep, _state);
mincgsetcond(&state, (double)(0), (double)(0), 1.0E-9, 10, _state);
mincgsetscale(&state, &s, _state);
while(mincgiteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.f = state.f+0.5*(state.x.ptr.p_double[i]/s.ptr.p_double[i])*v;
state.g.ptr.p_double[i] = v;
}
if( defecttype==0 )
{
state.g.ptr.p_double[varidx] = (double)(0);
}
if( defecttype==1 )
{
state.g.ptr.p_double[varidx] = state.g.ptr.p_double[varidx]+1;
}
if( defecttype==2 )
{
state.g.ptr.p_double[varidx] = state.g.ptr.p_double[varidx]*2;
}
for(i=0; i<=n-1; i++)
{
state.g.ptr.p_double[i] = state.g.ptr.p_double[i]/s.ptr.p_double[i];
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
mincgresults(&state, &x1, &rep, _state);
mincgoptguardresults(&state, &ogrep, _state);
/*
* Check that something is returned
*/
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testmincgunit.ap:1403");
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1404");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Compute reference values for true and spoiled Jacobian at X0
*/
ae_set_error_flag(wereerrors, !isfinitevector(&ogrep.badgradxbase, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1411");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_matrix_set_length(&jactrue, 1, n, _state);
ae_matrix_set_length(&jacdefect, 1, n, _state);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+ogrep.badgradxbase.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
jactrue.ptr.pp_double[0][i] = v;
jacdefect.ptr.pp_double[0][i] = v;
}
if( defecttype==0 )
{
jacdefect.ptr.pp_double[0][varidx] = (double)(0);
}
if( defecttype==1 )
{
jacdefect.ptr.pp_double[0][varidx] = jacdefect.ptr.pp_double[0][varidx]+1;
}
if( defecttype==2 )
{
jacdefect.ptr.pp_double[0][varidx] = jacdefect.ptr.pp_double[0][varidx]*2;
}
for(i=0; i<=n-1; i++)
{
jactrue.ptr.pp_double[0][i] = jactrue.ptr.pp_double[0][i]/s.ptr.p_double[i];
jacdefect.ptr.pp_double[0][i] = jacdefect.ptr.pp_double[0][i]/s.ptr.p_double[i];
}
/*
* Check OptGuard report
*/
ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgraduser, 1, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1439");
ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgradnum, 1, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1440");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
if( defecttype>=0 )
{
ae_set_error_flag(wereerrors, !ogrep.badgradsuspected, __FILE__, __LINE__, "testmincgunit.ap:1445");
ae_set_error_flag(wereerrors, ogrep.badgradfidx!=0, __FILE__, __LINE__, "testmincgunit.ap:1446");
ae_set_error_flag(wereerrors, ogrep.badgradvidx!=varidx, __FILE__, __LINE__, "testmincgunit.ap:1447");
}
else
{
ae_set_error_flag(wereerrors, ogrep.badgradsuspected, __FILE__, __LINE__, "testmincgunit.ap:1451");
ae_set_error_flag(wereerrors, ogrep.badgradfidx!=-1, __FILE__, __LINE__, "testmincgunit.ap:1452");
ae_set_error_flag(wereerrors, ogrep.badgradvidx!=-1, __FILE__, __LINE__, "testmincgunit.ap:1453");
}
for(j=0; j<=n-1; j++)
{
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jactrue.ptr.pp_double[0][j]-ogrep.badgradnum.ptr.pp_double[0][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testmincgunit.ap:1457");
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jacdefect.ptr.pp_double[0][j]-ogrep.badgraduser.ptr.pp_double[0][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testmincgunit.ap:1458");
}
}
}
/*
* A test for detection of C1 continuity violations in the target.
*
* Target function is a sum of |(x,c_i)| for i=1..N.
* No constraints is present.
* Analytic gradient is provided.
*
* OptGuard should be able to detect violations in more than
* 99.9% of runs; it means that 100 runs should have no more than 4
* failures in all cases (even after multiple repeated tests; according
* to the binomial distribution quantiles).
*
* We select some N and perform exhaustive search for this N.
*/
passcount = 100;
maxfails = 4;
maxc1test0fails = 10;
maxc1test1fails = 10;
n = 1+hqrnduniformi(&rs, 10, _state);
failurecounter = 0;
c1test0fails = 0;
c1test1fails = 0;
avgstr0len = (double)(0);
avglng0len = (double)(0);
avgstr1len = (double)(0);
avglng1len = (double)(0);
for(pass=1; pass<=passcount; pass++)
{
/*
* Formulate problem
*/
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
/*
* Create and try to solve
*/
mincgcreate(n, &x0, &state, _state);
mincgsetcond(&state, (double)(0), (double)(0), 1.0E-9, 50, _state);
mincgsetscale(&state, &s, _state);
mincgoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testmincgunit_maxoptguardlevel, _state), _state);
while(mincgiteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.g.ptr.p_double[i] = (double)(0);
}
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.f = state.f+ae_fabs(v, _state);
v = (double)(ae_sign(v, _state));
for(j=0; j<=n-1; j++)
{
state.g.ptr.p_double[j] = state.g.ptr.p_double[j]+v*a.ptr.pp_double[i][j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
mincgresults(&state, &x1, &rep, _state);
mincgoptguardresults(&state, &ogrep, _state);
/*
* Check basic properties of the solution
*/
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1539");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testmincgunit.ap:1540");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Check generic OptGuard report: distinguish between "hard"
* failures which result in immediate termination
* (C0 violation being reported) and "soft" ones
* (C1 violation is NOT reported) which accumulate
* until we exhaust limit.
*/
ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testmincgunit.ap:1551");
ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testmincgunit.ap:1552");
failed = ae_false;
failed = failed||optguardallclear(&ogrep, _state);
failed = failed||!ogrep.nonc1suspected;
failed = failed||ogrep.nonc1fidx!=0;
if( failed )
{
inc(&failurecounter, _state);
}
/*
* Check C1 continuity test #0
*/
mincgoptguardnonc1test0results(&state, &ognonc1test0strrep, &ognonc1test0lngrep, _state);
mincgoptguardnonc1test1results(&state, &ognonc1test1strrep, &ognonc1test1lngrep, _state);
if( ogrep.nonc1test0positive )
{
ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testmincgunit.ap:1567");
ae_set_error_flag(wereerrors, !ognonc1test0strrep.positive, __FILE__, __LINE__, "testmincgunit.ap:1568");
ae_set_error_flag(wereerrors, !ognonc1test0lngrep.positive, __FILE__, __LINE__, "testmincgunit.ap:1569");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testmincgunit.ap:1570");
testmincgunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0strrep, &a, n, _state);
testmincgunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0lngrep, &a, n, _state);
avgstr0len = avgstr0len+(double)ognonc1test0strrep.cnt/(double)passcount;
avglng0len = avglng0len+(double)ognonc1test0lngrep.cnt/(double)passcount;
}
else
{
ae_set_error_flag(wereerrors, ognonc1test0strrep.positive, __FILE__, __LINE__, "testmincgunit.ap:1578");
ae_set_error_flag(wereerrors, ognonc1test0lngrep.positive, __FILE__, __LINE__, "testmincgunit.ap:1579");
testmincgunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0strrep, &a, n, _state);
testmincgunit_testoptguardc1test0reportfortask0(wereerrors, &ognonc1test0lngrep, &a, n, _state);
inc(&c1test0fails, _state);
}
if( ogrep.nonc1test1positive )
{
ae_set_error_flag(wereerrors, !ogrep.nonc1suspected, __FILE__, __LINE__, "testmincgunit.ap:1586");
ae_set_error_flag(wereerrors, !ognonc1test1strrep.positive, __FILE__, __LINE__, "testmincgunit.ap:1587");
ae_set_error_flag(wereerrors, !ognonc1test1lngrep.positive, __FILE__, __LINE__, "testmincgunit.ap:1588");
ae_set_error_flag(wereerrors, ogrep.nonc1fidx!=0, __FILE__, __LINE__, "testmincgunit.ap:1589");
testmincgunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1strrep, &a, n, _state);
testmincgunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1lngrep, &a, n, _state);
avgstr1len = avgstr1len+(double)ognonc1test1strrep.cnt/(double)passcount;
avglng1len = avglng1len+(double)ognonc1test1lngrep.cnt/(double)passcount;
}
else
{
ae_set_error_flag(wereerrors, ognonc1test1strrep.positive, __FILE__, __LINE__, "testmincgunit.ap:1597");
ae_set_error_flag(wereerrors, ognonc1test1lngrep.positive, __FILE__, __LINE__, "testmincgunit.ap:1598");
testmincgunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1strrep, &a, n, _state);
testmincgunit_testoptguardc1test1reportfortask0(wereerrors, &ognonc1test1lngrep, &a, n, _state);
inc(&c1test1fails, _state);
}
}
ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testmincgunit.ap:1605");
ae_set_error_flag(wereerrors, c1test0fails>maxc1test0fails, __FILE__, __LINE__, "testmincgunit.ap:1606");
ae_set_error_flag(wereerrors, c1test1fails>maxc1test1fails, __FILE__, __LINE__, "testmincgunit.ap:1607");
ae_set_error_flag(wereerrors, ae_fp_less_eq(avglng0len,avgstr0len), __FILE__, __LINE__, "testmincgunit.ap:1608");
ae_set_error_flag(wereerrors, ae_fp_less_eq(avglng1len,avgstr1len), __FILE__, __LINE__, "testmincgunit.ap:1609");
/*
* Detection of C1 continuity violations in the target under numerical differentiation:
* * target function is a sum of |(x,c_i)| for i=1..N.
* * no constraints is present.
* * analytic gradient is provided.
*
* OptGuard should always be able to detect violations in more than
* 99% of runs (note: reduced strength when compared with analytic gradient);
* it means that 100 runs should have no more than 10 failures in all cases
* (even after multiple repeated tests; according to the binomial distribution
* quantiles).
*
* We select some N and perform exhaustive search for this N.
*/
diffstep = 0.0001;
passcount = 100;
maxfails = 10;
n = 1+hqrnduniformi(&rs, 10, _state);
failurecounter = 0;
for(pass=1; pass<=passcount; pass++)
{
/*
* Formulate problem
*/
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&s, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = 0.01*ae_pow((double)(2), 0.33*hqrndnormal(&rs, _state), _state);
}
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
/*
* Create and try to solve
*/
mincgcreatef(n, &x0, diffstep, &state, _state);
mincgsetcond(&state, (double)(0), (double)(0), 1.0E-9, 50, _state);
mincgoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testmincgunit_maxoptguardlevel, _state), _state);
while(mincgiteration(&state, _state))
{
if( state.needf )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.f = state.f+ae_fabs(v, _state);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
mincgresults(&state, &x1, &rep, _state);
mincgoptguardresults(&state, &ogrep, _state);
/*
* Check basic properties of the solution
*/
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1674");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testmincgunit.ap:1675");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Check OptGuard report: distinguish between "hard"
* failures which result in immediate termination
* (C0 violation being reported) and "soft" ones
* (C1 violation is NOT reported) which accumulate
* until we exhaust limit.
*/
ae_set_error_flag(wereerrors, ogrep.nonc0suspected, __FILE__, __LINE__, "testmincgunit.ap:1686");
ae_set_error_flag(wereerrors, ogrep.nonc0fidx>=0, __FILE__, __LINE__, "testmincgunit.ap:1687");
failed = ae_false;
failed = failed||optguardallclear(&ogrep, _state);
failed = failed||!ogrep.nonc1suspected;
failed = failed||ogrep.nonc1fidx!=0;
if( failed )
{
inc(&failurecounter, _state);
}
}
ae_set_error_flag(wereerrors, failurecounter>maxfails, __FILE__, __LINE__, "testmincgunit.ap:1695");
/*
* Make sure than no false positives are reported for larger
* problems where numerical noise can be an issue:
* * N=100 dimensions
* * positive-definite quadratic programming problem
* * upper limit on iterations count, MaxIts=25
* We simply test that OptGuard does not return error code.
*/
n = 100;
spdmatrixrndcond(n, 1.0E2, &a, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = hqrndnormal(&rs, _state);
x0.ptr.p_double[i] = ae_pow(2.0, hqrndnormal(&rs, _state), _state);
}
mincgcreate(n, &x0, &state, _state);
mincgoptguardsmoothness(&state, 1+hqrnduniformi(&rs, testmincgunit_maxoptguardlevel, _state), _state);
mincgsetcond(&state, (double)(0), (double)(0), 1.0E-9, 25, _state);
while(mincgiteration(&state, _state))
{
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+b.ptr.p_double[i]*state.x.ptr.p_double[i];
state.g.ptr.p_double[i] = b.ptr.p_double[i];
for(j=0; j<=n-1; j++)
{
state.f = state.f+0.5*state.x.ptr.p_double[i]*a.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
state.g.ptr.p_double[i] = state.g.ptr.p_double[i]+a.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
mincgresults(&state, &x1, &rep, _state);
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1738");
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testmincgunit.ap:1739");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
mincgoptguardresults(&state, &ogrep, _state);
ae_set_error_flag(wereerrors, !optguardallclear(&ogrep, _state), __FILE__, __LINE__, "testmincgunit.ap:1743");
ae_frame_leave(_state);
}
/*************************************************************************
This function tests report of "non-C1" test #0 for task #0
given by matrix A.
On failure sets error flag.
*************************************************************************/
static void testmincgunit_testoptguardc1test0reportfortask0(ae_bool* err,
optguardnonc1test0report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
double vv;
double va;
double vb;
ae_bool hasc1discontinuities;
if( rep->positive )
{
/*
* Check positive report, first checks
*/
ae_set_error_flag(err, rep->fidx!=0, __FILE__, __LINE__, "testmincgunit.ap:1770");
ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testmincgunit.ap:1771");
ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testmincgunit.ap:1772");
ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testmincgunit.ap:1773");
ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testmincgunit.ap:1774");
ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testmincgunit.ap:1775");
ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testmincgunit.ap:1776");
ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testmincgunit.ap:1777");
ae_set_error_flag(err, rep->f.cnt!=rep->cnt, __FILE__, __LINE__, "testmincgunit.ap:1778");
ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1779");
ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1780");
ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testmincgunit.ap:1781");
ae_set_error_flag(err, !isfinitevector(&rep->f, rep->cnt, _state), __FILE__, __LINE__, "testmincgunit.ap:1782");
if( *err )
{
return;
}
/*
* Check consistency of X0, D, Stp and F
*/
for(k=0; k<=rep->cnt-2; k++)
{
ae_set_error_flag(err, ae_fp_greater_eq(rep->stp.ptr.p_double[k],rep->stp.ptr.p_double[k+1]), __FILE__, __LINE__, "testmincgunit.ap:1790");
}
for(k=0; k<=rep->cnt-1; k++)
{
v = (double)(0);
for(i=0; i<=n-1; i++)
{
vv = (double)(0);
for(j=0; j<=n-1; j++)
{
vv = vv+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[k]);
}
v = v+ae_fabs(vv, _state);
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-rep->f.ptr.p_double[k], _state),1.0E-6*ae_maxreal(ae_fabs(v, _state), (double)(1), _state)), __FILE__, __LINE__, "testmincgunit.ap:1803");
}
/*
* Check that interval [#StpIdxA,#StpIdxB] contains at least one discontinuity
*/
hasc1discontinuities = ae_false;
for(i=0; i<=n-1; i++)
{
va = (double)(0);
vb = (double)(0);
for(j=0; j<=n-1; j++)
{
va = va+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxa]);
vb = vb+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxb]);
}
hasc1discontinuities = hasc1discontinuities||ae_sign(va, _state)!=ae_sign(vb, _state);
}
ae_set_error_flag(err, !hasc1discontinuities, __FILE__, __LINE__, "testmincgunit.ap:1821");
}
else
{
/*
* Check negative report: fields must be empty
*/
ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testmincgunit.ap:1828");
ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testmincgunit.ap:1829");
ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testmincgunit.ap:1830");
ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testmincgunit.ap:1831");
ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testmincgunit.ap:1832");
ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testmincgunit.ap:1833");
ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testmincgunit.ap:1834");
ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testmincgunit.ap:1835");
ae_set_error_flag(err, rep->f.cnt!=0, __FILE__, __LINE__, "testmincgunit.ap:1836");
}
}
/*************************************************************************
This function tests report of "non-C1" test #1 for task #0
given by matrix A.
On failure sets error flag.
*************************************************************************/
static void testmincgunit_testoptguardc1test1reportfortask0(ae_bool* err,
optguardnonc1test1report* rep,
/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
double vv;
double va;
double vb;
ae_bool tooclose;
ae_bool hasc1discontinuities;
if( rep->positive )
{
/*
* Check positive report, first checks
*/
ae_set_error_flag(err, rep->fidx!=0, __FILE__, __LINE__, "testmincgunit.ap:1864");
ae_set_error_flag(err, rep->vidx<0, __FILE__, __LINE__, "testmincgunit.ap:1865");
ae_set_error_flag(err, rep->vidx>n, __FILE__, __LINE__, "testmincgunit.ap:1866");
ae_set_error_flag(err, rep->n!=n, __FILE__, __LINE__, "testmincgunit.ap:1867");
ae_set_error_flag(err, !(0<=rep->stpidxa), __FILE__, __LINE__, "testmincgunit.ap:1868");
ae_set_error_flag(err, !(rep->stpidxastpidxb), __FILE__, __LINE__, "testmincgunit.ap:1869");
ae_set_error_flag(err, !(rep->stpidxbcnt), __FILE__, __LINE__, "testmincgunit.ap:1870");
ae_set_error_flag(err, rep->x0.cnt!=rep->n, __FILE__, __LINE__, "testmincgunit.ap:1871");
ae_set_error_flag(err, rep->d.cnt!=rep->n, __FILE__, __LINE__, "testmincgunit.ap:1872");
ae_set_error_flag(err, rep->stp.cnt!=rep->cnt, __FILE__, __LINE__, "testmincgunit.ap:1873");
ae_set_error_flag(err, rep->g.cnt!=rep->cnt, __FILE__, __LINE__, "testmincgunit.ap:1874");
ae_set_error_flag(err, !isfinitevector(&rep->x0, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1875");
ae_set_error_flag(err, !isfinitevector(&rep->d, n, _state), __FILE__, __LINE__, "testmincgunit.ap:1876");
ae_set_error_flag(err, !isfinitevector(&rep->stp, rep->cnt, _state), __FILE__, __LINE__, "testmincgunit.ap:1877");
ae_set_error_flag(err, !isfinitevector(&rep->g, rep->cnt, _state), __FILE__, __LINE__, "testmincgunit.ap:1878");
if( *err )
{
return;
}
/*
* Check consistency of X0, D, Stp and G
*/
for(k=0; k<=rep->cnt-2; k++)
{
ae_set_error_flag(err, ae_fp_greater_eq(rep->stp.ptr.p_double[k],rep->stp.ptr.p_double[k+1]), __FILE__, __LINE__, "testmincgunit.ap:1886");
}
for(k=0; k<=rep->cnt-1; k++)
{
v = (double)(0);
tooclose = ae_false;
for(i=0; i<=n-1; i++)
{
vv = (double)(0);
for(j=0; j<=n-1; j++)
{
vv = vv+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[k]);
}
v = v+ae_sign(vv, _state)*a->ptr.pp_double[i][rep->vidx];
tooclose = tooclose||ae_fp_less(ae_fabs(vv, _state),1.0E-4);
}
if( !tooclose )
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-rep->g.ptr.p_double[k], _state),1.0E-6*ae_maxreal(ae_fabs(v, _state), (double)(1), _state)), __FILE__, __LINE__, "testmincgunit.ap:1900");
}
}
/*
* Check that interval [#StpIdxA,#StpIdxB] contains at least one discontinuity
*/
tooclose = ae_false;
hasc1discontinuities = ae_false;
for(i=0; i<=n-1; i++)
{
va = (double)(0);
vb = (double)(0);
for(j=0; j<=n-1; j++)
{
va = va+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxa]);
vb = vb+a->ptr.pp_double[i][j]*(rep->x0.ptr.p_double[j]+rep->d.ptr.p_double[j]*rep->stp.ptr.p_double[rep->stpidxb]);
}
tooclose = (tooclose||ae_fp_less(ae_fabs(va, _state),1.0E-8))||ae_fp_less(ae_fabs(vb, _state),1.0E-8);
hasc1discontinuities = hasc1discontinuities||ae_sign(va, _state)!=ae_sign(vb, _state);
}
if( !tooclose )
{
ae_set_error_flag(err, !hasc1discontinuities, __FILE__, __LINE__, "testmincgunit.ap:1921");
}
}
else
{
/*
* Check negative report: fields must be empty
*/
ae_set_error_flag(err, rep->stpidxa!=-1, __FILE__, __LINE__, "testmincgunit.ap:1928");
ae_set_error_flag(err, rep->stpidxb!=-1, __FILE__, __LINE__, "testmincgunit.ap:1929");
ae_set_error_flag(err, rep->fidx!=-1, __FILE__, __LINE__, "testmincgunit.ap:1930");
ae_set_error_flag(err, rep->vidx!=-1, __FILE__, __LINE__, "testmincgunit.ap:1931");
ae_set_error_flag(err, rep->cnt!=0, __FILE__, __LINE__, "testmincgunit.ap:1932");
ae_set_error_flag(err, rep->n!=0, __FILE__, __LINE__, "testmincgunit.ap:1933");
ae_set_error_flag(err, rep->x0.cnt!=0, __FILE__, __LINE__, "testmincgunit.ap:1934");
ae_set_error_flag(err, rep->d.cnt!=0, __FILE__, __LINE__, "testmincgunit.ap:1935");
ae_set_error_flag(err, rep->stp.cnt!=0, __FILE__, __LINE__, "testmincgunit.ap:1936");
ae_set_error_flag(err, rep->g.cnt!=0, __FILE__, __LINE__, "testmincgunit.ap:1937");
}
}
static void testminlmunit_testu(ae_bool* errorflag,
ae_bool* statefieldsconsistencyflag,
ae_state *_state);
static void testminlmunit_testbc(ae_bool* errorflag, ae_state *_state);
static void testminlmunit_testlc(ae_bool* errorflag, ae_state *_state);
static void testminlmunit_testother(ae_bool* errorflag,
ae_bool* statefieldsconsistencyflag,
ae_state *_state);
static void testminlmunit_testoptguard(ae_bool* wereerrors,
ae_state *_state);
static ae_bool testminlmunit_rkindvsstatecheck(ae_int_t rkind,
minlmstate* state,
ae_state *_state);
static void testminlmunit_axmb(minlmstate* state,
/* Real */ ae_matrix* a,
/* Real */ ae_vector* b,
ae_int_t n,
ae_state *_state);
static void testminlmunit_tryreproducefixedbugs(ae_bool* err,
ae_state *_state);
static void testminlmunit_testfunc1(ae_int_t n,
ae_int_t m,
/* Real */ ae_matrix* c,
/* Real */ ae_vector* x,
double* f,
ae_bool needf,
/* Real */ ae_vector* fi,
ae_bool needfi,
/* Real */ ae_matrix* jac,
ae_bool needjac,
ae_state *_state);
ae_bool testminlm(ae_bool silent, ae_state *_state)
{
ae_bool waserrors;
ae_bool uerrors;
ae_bool bcerrors;
ae_bool lcerrors;
ae_bool scerror;
ae_bool othererrors;
ae_bool optguarderr;
ae_bool result;
waserrors = ae_false;
scerror = ae_false;
othererrors = ae_false;
uerrors = ae_false;
bcerrors = ae_false;
lcerrors = ae_false;
/*
* Various tests
*/
testminlmunit_testother(&othererrors, &scerror, _state);
/*
* Tests sorted by constraint types
*/
testminlmunit_testu(&uerrors, &scerror, _state);
testminlmunit_testbc(&bcerrors, _state);
testminlmunit_testlc(&lcerrors, _state);
/*
* Try to reproduce previously fixed bugs
*/
testminlmunit_tryreproducefixedbugs(&othererrors, _state);
/*
* Test for MinLMGradientCheck
*/
optguarderr = ae_false;
testminlmunit_testoptguard(&optguarderr, _state);
/*
* end
*/
waserrors = ((((uerrors||bcerrors)||lcerrors)||scerror)||othererrors)||optguarderr;
if( !silent )
{
printf("TESTING LEVENBERG-MARQUARDT OPTIMIZATION\n");
printf("PROBLEM TYPES:\n");
printf("* UNCONSTRAINED ");
if( uerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* BOX CONSTRAINED ");
if( bcerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* LINEARLY CONSTRAINED ");
if( lcerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("STATE FIELDS CONSISTENCY: ");
if( scerror )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("OTHER PROPERTIES: ");
if( othererrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("OPTGUARD: ");
if( optguarderr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
return result;
}
/*************************************************************************
Test for unconstrained problems.
On failure sets error flag, leaves it unchanged on success.
*************************************************************************/
static void testminlmunit_testu(ae_bool* errorflag,
ae_bool* statefieldsconsistencyflag,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t m;
ae_int_t i;
ae_vector x;
ae_vector xe;
ae_vector b;
double h;
ae_int_t rkind;
ae_matrix a;
double v;
double s;
double eps;
double epsx;
ae_int_t maxits;
ae_int_t ckind;
minlmstate state;
minlmreport rep;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&xe, 0, sizeof(xe));
memset(&b, 0, sizeof(b));
memset(&a, 0, sizeof(a));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xe, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
_minlmstate_init(&state, _state, ae_true);
_minlmreport_init(&rep, _state, ae_true);
/*
* Reference problem.
* See comments for RKindVsStateCheck() for more info about RKind.
*
* NOTES: we also test negative RKind's corresponding to "inexact" schemes
* which use approximate finite difference Jacobian.
*/
ae_vector_set_length(&x, 3, _state);
n = 3;
m = 3;
h = 0.0001;
for(rkind=-2; rkind<=5; rkind++)
{
x.ptr.p_double[0] = 100*ae_randomreal(_state)-50;
x.ptr.p_double[1] = 100*ae_randomreal(_state)-50;
x.ptr.p_double[2] = 100*ae_randomreal(_state)-50;
if( rkind==-2 )
{
minlmcreatev(n, m, &x, h, &state, _state);
minlmsetacctype(&state, 1, _state);
}
if( rkind==-1 )
{
minlmcreatev(n, m, &x, h, &state, _state);
minlmsetacctype(&state, 0, _state);
}
if( rkind==0 )
{
minlmcreatefj(n, m, &x, &state, _state);
}
if( rkind==1 )
{
minlmcreatefgj(n, m, &x, &state, _state);
}
if( rkind==2 )
{
minlmcreatefgh(n, &x, &state, _state);
}
if( rkind==3 )
{
minlmcreatevj(n, m, &x, &state, _state);
minlmsetacctype(&state, 0, _state);
}
if( rkind==4 )
{
minlmcreatevj(n, m, &x, &state, _state);
minlmsetacctype(&state, 1, _state);
}
if( rkind==5 )
{
minlmcreatevj(n, m, &x, &state, _state);
minlmsetacctype(&state, 2, _state);
}
while(minlmiteration(&state, _state))
{
/*
* (x-2)^2 + y^2 + (z-x)^2
*/
if( state.needfi )
{
state.fi.ptr.p_double[0] = state.x.ptr.p_double[0]-2;
state.fi.ptr.p_double[1] = state.x.ptr.p_double[1];
state.fi.ptr.p_double[2] = state.x.ptr.p_double[2]-state.x.ptr.p_double[0];
}
if( state.needfij )
{
state.fi.ptr.p_double[0] = state.x.ptr.p_double[0]-2;
state.fi.ptr.p_double[1] = state.x.ptr.p_double[1];
state.fi.ptr.p_double[2] = state.x.ptr.p_double[2]-state.x.ptr.p_double[0];
state.j.ptr.pp_double[0][0] = (double)(1);
state.j.ptr.pp_double[0][1] = (double)(0);
state.j.ptr.pp_double[0][2] = (double)(0);
state.j.ptr.pp_double[1][0] = (double)(0);
state.j.ptr.pp_double[1][1] = (double)(1);
state.j.ptr.pp_double[1][2] = (double)(0);
state.j.ptr.pp_double[2][0] = (double)(-1);
state.j.ptr.pp_double[2][1] = (double)(0);
state.j.ptr.pp_double[2][2] = (double)(1);
}
if( (state.needf||state.needfg)||state.needfgh )
{
state.f = ae_sqr(state.x.ptr.p_double[0]-2, _state)+ae_sqr(state.x.ptr.p_double[1], _state)+ae_sqr(state.x.ptr.p_double[2]-state.x.ptr.p_double[0], _state);
}
if( state.needfg||state.needfgh )
{
state.g.ptr.p_double[0] = 2*(state.x.ptr.p_double[0]-2)+2*(state.x.ptr.p_double[0]-state.x.ptr.p_double[2]);
state.g.ptr.p_double[1] = 2*state.x.ptr.p_double[1];
state.g.ptr.p_double[2] = 2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0]);
}
if( state.needfgh )
{
state.h.ptr.pp_double[0][0] = (double)(4);
state.h.ptr.pp_double[0][1] = (double)(0);
state.h.ptr.pp_double[0][2] = (double)(-2);
state.h.ptr.pp_double[1][0] = (double)(0);
state.h.ptr.pp_double[1][1] = (double)(2);
state.h.ptr.pp_double[1][2] = (double)(0);
state.h.ptr.pp_double[2][0] = (double)(-2);
state.h.ptr.pp_double[2][1] = (double)(0);
state.h.ptr.pp_double[2][2] = (double)(2);
}
ae_set_error_flag(statefieldsconsistencyflag, !testminlmunit_rkindvsstatecheck(rkind, &state, _state), __FILE__, __LINE__, "testminlmunit.ap:212");
}
minlmresults(&state, &x, &rep, _state);
ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:215");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x.ptr.p_double[0]-2, _state),0.001), __FILE__, __LINE__, "testminlmunit.ap:216");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x.ptr.p_double[1], _state),0.001), __FILE__, __LINE__, "testminlmunit.ap:217");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x.ptr.p_double[2]-2, _state),0.001), __FILE__, __LINE__, "testminlmunit.ap:218");
}
/*
* 1D problem #1
*
* NOTES: we also test negative RKind's corresponding to "inexact" schemes
* which use approximate finite difference Jacobian.
*/
for(rkind=-2; rkind<=5; rkind++)
{
ae_vector_set_length(&x, 1, _state);
n = 1;
m = 1;
h = 0.00001;
x.ptr.p_double[0] = 100*ae_randomreal(_state)-50;
if( rkind==-2 )
{
minlmcreatev(n, m, &x, h, &state, _state);
minlmsetacctype(&state, 1, _state);
}
if( rkind==-1 )
{
minlmcreatev(n, m, &x, h, &state, _state);
minlmsetacctype(&state, 0, _state);
}
if( rkind==0 )
{
minlmcreatefj(n, m, &x, &state, _state);
}
if( rkind==1 )
{
minlmcreatefgj(n, m, &x, &state, _state);
}
if( rkind==2 )
{
minlmcreatefgh(n, &x, &state, _state);
}
if( rkind==3 )
{
minlmcreatevj(n, m, &x, &state, _state);
minlmsetacctype(&state, 0, _state);
}
if( rkind==4 )
{
minlmcreatevj(n, m, &x, &state, _state);
minlmsetacctype(&state, 1, _state);
}
if( rkind==5 )
{
minlmcreatevj(n, m, &x, &state, _state);
minlmsetacctype(&state, 2, _state);
}
while(minlmiteration(&state, _state))
{
if( state.needfi )
{
state.fi.ptr.p_double[0] = ae_sin(state.x.ptr.p_double[0], _state);
}
if( state.needfij )
{
state.fi.ptr.p_double[0] = ae_sin(state.x.ptr.p_double[0], _state);
state.j.ptr.pp_double[0][0] = ae_cos(state.x.ptr.p_double[0], _state);
}
if( (state.needf||state.needfg)||state.needfgh )
{
state.f = ae_sqr(ae_sin(state.x.ptr.p_double[0], _state), _state);
}
if( state.needfg||state.needfgh )
{
state.g.ptr.p_double[0] = 2*ae_sin(state.x.ptr.p_double[0], _state)*ae_cos(state.x.ptr.p_double[0], _state);
}
if( state.needfgh )
{
state.h.ptr.pp_double[0][0] = 2*(ae_cos(state.x.ptr.p_double[0], _state)*ae_cos(state.x.ptr.p_double[0], _state)-ae_sin(state.x.ptr.p_double[0], _state)*ae_sin(state.x.ptr.p_double[0], _state));
}
ae_set_error_flag(statefieldsconsistencyflag, !testminlmunit_rkindvsstatecheck(rkind, &state, _state), __FILE__, __LINE__, "testminlmunit.ap:281");
}
minlmresults(&state, &x, &rep, _state);
ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:284");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x.ptr.p_double[0]/ae_pi-ae_round(x.ptr.p_double[0]/ae_pi, _state), _state),0.001), __FILE__, __LINE__, "testminlmunit.ap:285");
}
/*
* Linear equations: test normal optimization and optimization with restarts
*/
for(n=1; n<=10; n++)
{
/*
* Prepare task
*/
h = 0.00001;
rmatrixrndcond(n, (double)(100), &a, _state);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&xe, n, _state);
ae_vector_set_length(&b, n, _state);
for(i=0; i<=n-1; i++)
{
xe.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &xe.ptr.p_double[0], 1, ae_v_len(0,n-1));
b.ptr.p_double[i] = v;
}
/*
* Test different RKind
*
* NOTES: we also test negative RKind's corresponding to "inexact" schemes
* which use approximate finite difference Jacobian.
*/
for(rkind=-2; rkind<=5; rkind++)
{
/*
* Solve task (first attempt)
*/
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
if( rkind==-2 )
{
minlmcreatev(n, n, &x, h, &state, _state);
minlmsetacctype(&state, 1, _state);
}
if( rkind==-1 )
{
minlmcreatev(n, n, &x, h, &state, _state);
minlmsetacctype(&state, 0, _state);
}
if( rkind==0 )
{
minlmcreatefj(n, n, &x, &state, _state);
}
if( rkind==1 )
{
minlmcreatefgj(n, n, &x, &state, _state);
}
if( rkind==2 )
{
minlmcreatefgh(n, &x, &state, _state);
}
if( rkind==3 )
{
minlmcreatevj(n, n, &x, &state, _state);
minlmsetacctype(&state, 0, _state);
}
if( rkind==4 )
{
minlmcreatevj(n, n, &x, &state, _state);
minlmsetacctype(&state, 1, _state);
}
if( rkind==5 )
{
minlmcreatevj(n, n, &x, &state, _state);
minlmsetacctype(&state, 2, _state);
}
while(minlmiteration(&state, _state))
{
testminlmunit_axmb(&state, &a, &b, n, _state);
ae_set_error_flag(statefieldsconsistencyflag, !testminlmunit_rkindvsstatecheck(rkind, &state, _state), __FILE__, __LINE__, "testminlmunit.ap:357");
}
minlmresults(&state, &x, &rep, _state);
ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:360");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x.ptr.p_double[i]-xe.ptr.p_double[i], _state),0.001), __FILE__, __LINE__, "testminlmunit.ap:364");
}
/*
* Now we try to restart algorithm from new point
*/
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
minlmrestartfrom(&state, &x, _state);
while(minlmiteration(&state, _state))
{
testminlmunit_axmb(&state, &a, &b, n, _state);
ae_set_error_flag(statefieldsconsistencyflag, !testminlmunit_rkindvsstatecheck(rkind, &state, _state), __FILE__, __LINE__, "testminlmunit.ap:375");
}
minlmresults(&state, &x, &rep, _state);
ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:378");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x.ptr.p_double[i]-xe.ptr.p_double[i], _state),0.001), __FILE__, __LINE__, "testminlmunit.ap:382");
}
}
}
/*
* Testing convergence properties using
* different optimizer types and different conditions.
*
* Only limited subset of optimizers is tested because some
* optimizers converge too quickly.
*/
s = (double)(100);
for(rkind=0; rkind<=5; rkind++)
{
/*
* Skip FGH optimizer - it converges too quickly
*/
if( rkind==2 )
{
continue;
}
/*
* Test
*/
for(ckind=0; ckind<=1; ckind++)
{
eps = (double)(0);
epsx = (double)(0);
maxits = 0;
if( ckind==0 )
{
epsx = 1.0E-6;
eps = 1.0E-4;
}
if( ckind==1 )
{
maxits = 2;
eps = 0.05;
}
ae_vector_set_length(&x, 3, _state);
n = 3;
m = 3;
for(i=0; i<=2; i++)
{
x.ptr.p_double[i] = (double)(6);
}
if( rkind==0 )
{
minlmcreatefj(n, m, &x, &state, _state);
}
if( rkind==1 )
{
minlmcreatefgj(n, m, &x, &state, _state);
}
ae_assert(rkind!=2, "Assertion failed", _state);
if( rkind==3 )
{
minlmcreatevj(n, m, &x, &state, _state);
minlmsetacctype(&state, 0, _state);
}
if( rkind==4 )
{
minlmcreatevj(n, m, &x, &state, _state);
minlmsetacctype(&state, 1, _state);
}
if( rkind==5 )
{
minlmcreatevj(n, m, &x, &state, _state);
minlmsetacctype(&state, 2, _state);
}
minlmsetcond(&state, epsx, maxits, _state);
while(minlmiteration(&state, _state))
{
if( state.needfi||state.needfij )
{
state.fi.ptr.p_double[0] = s*(ae_exp(state.x.ptr.p_double[0], _state)-2);
state.fi.ptr.p_double[1] = ae_sqr(state.x.ptr.p_double[1], _state)+1;
state.fi.ptr.p_double[2] = state.x.ptr.p_double[2]-state.x.ptr.p_double[0];
}
if( state.needfij )
{
state.j.ptr.pp_double[0][0] = s*ae_exp(state.x.ptr.p_double[0], _state);
state.j.ptr.pp_double[0][1] = (double)(0);
state.j.ptr.pp_double[0][2] = (double)(0);
state.j.ptr.pp_double[1][0] = (double)(0);
state.j.ptr.pp_double[1][1] = 2*state.x.ptr.p_double[1];
state.j.ptr.pp_double[1][2] = (double)(0);
state.j.ptr.pp_double[2][0] = (double)(-1);
state.j.ptr.pp_double[2][1] = (double)(0);
state.j.ptr.pp_double[2][2] = (double)(1);
}
if( (state.needf||state.needfg)||state.needfgh )
{
state.f = s*ae_sqr(ae_exp(state.x.ptr.p_double[0], _state)-2, _state)+ae_sqr(ae_sqr(state.x.ptr.p_double[1], _state)+1, _state)+ae_sqr(state.x.ptr.p_double[2]-state.x.ptr.p_double[0], _state);
}
if( state.needfg||state.needfgh )
{
state.g.ptr.p_double[0] = s*2*(ae_exp(state.x.ptr.p_double[0], _state)-2)*ae_exp(state.x.ptr.p_double[0], _state)+2*(state.x.ptr.p_double[0]-state.x.ptr.p_double[2]);
state.g.ptr.p_double[1] = 2*(ae_sqr(state.x.ptr.p_double[1], _state)+1)*2*state.x.ptr.p_double[1];
state.g.ptr.p_double[2] = 2*(state.x.ptr.p_double[2]-state.x.ptr.p_double[0]);
}
if( state.needfgh )
{
state.h.ptr.pp_double[0][0] = s*(4*ae_sqr(ae_exp(state.x.ptr.p_double[0], _state), _state)-4*ae_exp(state.x.ptr.p_double[0], _state))+2;
state.h.ptr.pp_double[0][1] = (double)(0);
state.h.ptr.pp_double[0][2] = (double)(-2);
state.h.ptr.pp_double[1][0] = (double)(0);
state.h.ptr.pp_double[1][1] = 12*ae_sqr(state.x.ptr.p_double[1], _state)+4;
state.h.ptr.pp_double[1][2] = (double)(0);
state.h.ptr.pp_double[2][0] = (double)(-2);
state.h.ptr.pp_double[2][1] = (double)(0);
state.h.ptr.pp_double[2][2] = (double)(2);
}
ae_set_error_flag(statefieldsconsistencyflag, !testminlmunit_rkindvsstatecheck(rkind, &state, _state), __FILE__, __LINE__, "testminlmunit.ap:486");
}
minlmresults(&state, &x, &rep, _state);
ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:489");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
if( ckind==0 )
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x.ptr.p_double[0]-ae_log((double)(2), _state), _state),eps), __FILE__, __LINE__, "testminlmunit.ap:494");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x.ptr.p_double[1], _state),eps), __FILE__, __LINE__, "testminlmunit.ap:495");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x.ptr.p_double[2]-ae_log((double)(2), _state), _state),eps), __FILE__, __LINE__, "testminlmunit.ap:496");
ae_set_error_flag(errorflag, rep.terminationtype!=2, __FILE__, __LINE__, "testminlmunit.ap:497");
}
if( ckind==1 )
{
ae_set_error_flag(errorflag, rep.terminationtype!=5, __FILE__, __LINE__, "testminlmunit.ap:501");
ae_set_error_flag(errorflag, rep.iterationscount!=maxits, __FILE__, __LINE__, "testminlmunit.ap:502");
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Test for box constrained problems.
On failure sets error flag, leaves it unchanged on success.
*************************************************************************/
static void testminlmunit_testbc(ae_bool* errorflag, ae_state *_state)
{
ae_frame _frame_block;
minlmstate state;
minlmreport rep;
ae_vector bl;
ae_vector bu;
ae_int_t n;
ae_int_t m;
ae_vector x0;
ae_vector x;
ae_vector xe;
ae_vector x1;
ae_vector d;
ae_matrix c;
ae_int_t i;
ae_int_t j;
double v;
double h;
ae_int_t tmpkind;
hqrndstate rs;
double epsx;
double tolf;
double f0;
double f1;
ae_frame_make(_state, &_frame_block);
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&bl, 0, sizeof(bl));
memset(&bu, 0, sizeof(bu));
memset(&x0, 0, sizeof(x0));
memset(&x, 0, sizeof(x));
memset(&xe, 0, sizeof(xe));
memset(&x1, 0, sizeof(x1));
memset(&d, 0, sizeof(d));
memset(&c, 0, sizeof(c));
memset(&rs, 0, sizeof(rs));
_minlmstate_init(&state, _state, ae_true);
_minlmreport_init(&rep, _state, ae_true);
ae_vector_init(&bl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xe, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Reference box constrained problem:
*
* min sum((x[i]-xe[i])^4) subject to 0<=x[i]<=1
*
* NOTES:
* 1. we test only two optimization modes - V and FGH,
* because from algorithm internals we can assume that actual
* mode being used doesn't matter for bound constrained optimization
* process.
*/
for(tmpkind=0; tmpkind<=1; tmpkind++)
{
for(n=1; n<=5; n++)
{
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
ae_vector_set_length(&xe, n, _state);
ae_vector_set_length(&x, n, _state);
for(i=0; i<=n-1; i++)
{
bl.ptr.p_double[i] = (double)(0);
bu.ptr.p_double[i] = (double)(1);
xe.ptr.p_double[i] = 3*ae_randomreal(_state)-1;
x.ptr.p_double[i] = ae_randomreal(_state);
}
if( tmpkind==0 )
{
minlmcreatefgh(n, &x, &state, _state);
}
if( tmpkind==1 )
{
minlmcreatev(n, n, &x, 1.0E-5, &state, _state);
}
minlmsetcond(&state, 1.0E-6, 0, _state);
minlmsetbc(&state, &bl, &bu, _state);
while(minlmiteration(&state, _state))
{
if( state.needfi )
{
for(i=0; i<=n-1; i++)
{
state.fi.ptr.p_double[i] = ae_pow(state.x.ptr.p_double[i]-xe.ptr.p_double[i], (double)(2), _state);
}
}
if( (state.needf||state.needfg)||state.needfgh )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+ae_pow(state.x.ptr.p_double[i]-xe.ptr.p_double[i], (double)(4), _state);
}
}
if( state.needfg||state.needfgh )
{
for(i=0; i<=n-1; i++)
{
state.g.ptr.p_double[i] = 4*ae_pow(state.x.ptr.p_double[i]-xe.ptr.p_double[i], (double)(3), _state);
}
}
if( state.needfgh )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
state.h.ptr.pp_double[i][j] = (double)(0);
}
}
for(i=0; i<=n-1; i++)
{
state.h.ptr.pp_double[i][i] = 12*ae_pow(state.x.ptr.p_double[i]-xe.ptr.p_double[i], (double)(2), _state);
}
}
}
minlmresults(&state, &x, &rep, _state);
if( rep.terminationtype>0 )
{
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(x.ptr.p_double[i]-boundval(xe.ptr.p_double[i], bl.ptr.p_double[i], bu.ptr.p_double[i], _state), _state),5.0E-2), __FILE__, __LINE__, "testminlmunit.ap:594");
}
}
else
{
ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testminlmunit.ap:597");
}
}
}
/*
* Minimize
*
* [ [ ]2 ]
* SUM_i[ SUM_j[ power(x_j,3)*c_ij ] ]
* [ [ ] ]
*
* subject to non-negativity constraints on x_j
*/
epsx = 1.0E-9;
tolf = 1.0E-10;
for(tmpkind=0; tmpkind<=1; tmpkind++)
{
for(n=1; n<=20; n++)
{
m = n+hqrnduniformi(&rs, n, _state);
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
bl.ptr.p_double[i] = (double)(0);
bu.ptr.p_double[i] = _state->v_posinf;
x0.ptr.p_double[i] = 1+hqrnduniformr(&rs, _state);
}
ae_matrix_set_length(&c, m, n+1, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n; j++)
{
c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
if( tmpkind==0 )
{
minlmcreatev(n, m, &x0, 10*epsx, &state, _state);
}
if( tmpkind==1 )
{
minlmcreatevj(n, m, &x0, &state, _state);
}
minlmsetcond(&state, epsx, 0, _state);
minlmsetbc(&state, &bl, &bu, _state);
while(minlmiteration(&state, _state))
{
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_less(state.x.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:639");
ae_set_error_flag(errorflag, ae_fp_greater(state.x.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:640");
}
if( state.needfi )
{
testminlmunit_testfunc1(n, m, &c, &state.x, &v, ae_false, &state.fi, ae_true, &state.j, ae_false, _state);
continue;
}
if( state.needfij )
{
testminlmunit_testfunc1(n, m, &c, &state.x, &v, ae_false, &state.fi, ae_true, &state.j, ae_true, _state);
continue;
}
ae_assert(ae_false, "minlm test: integrity check failed", _state);
}
minlmresults(&state, &x, &rep, _state);
ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:655");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
testminlmunit_testfunc1(n, m, &c, &x, &f0, ae_true, &state.fi, ae_false, &state.j, ae_false, _state);
ae_vector_set_length(&x1, n, _state);
h = 0.001;
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_less(x.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:664");
ae_set_error_flag(errorflag, ae_fp_greater(x.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:665");
if( ae_fp_greater_eq(x.ptr.p_double[i]+h,bl.ptr.p_double[i]) )
{
for(j=0; j<=n-1; j++)
{
x1.ptr.p_double[j] = x.ptr.p_double[j];
}
x1.ptr.p_double[i] = x.ptr.p_double[i]+h;
testminlmunit_testfunc1(n, m, &c, &x1, &f1, ae_true, &state.fi, ae_false, &state.j, ae_false, _state);
ae_set_error_flag(errorflag, ae_fp_less(f1,f0*(1-tolf)), __FILE__, __LINE__, "testminlmunit.ap:674");
}
if( ae_fp_greater_eq(x.ptr.p_double[i]-h,bl.ptr.p_double[i]) )
{
for(j=0; j<=n-1; j++)
{
x1.ptr.p_double[j] = x.ptr.p_double[j];
}
x1.ptr.p_double[i] = x.ptr.p_double[i]-h;
testminlmunit_testfunc1(n, m, &c, &x1, &f1, ae_true, &state.fi, ae_false, &state.j, ae_false, _state);
ae_set_error_flag(errorflag, ae_fp_less(f1,f0*(1-tolf)), __FILE__, __LINE__, "testminlmunit.ap:684");
}
}
}
}
/*
* Minimize
*
* [ [ ]2 ]
* SUM_i[ SUM_j[ power(x_j,3)*c_ij ] ]
* [ [ ] ]
*
* subject to random box constraints on x_j
*/
epsx = 1.0E-9;
tolf = 1.0E-10;
for(tmpkind=0; tmpkind<=1; tmpkind++)
{
for(n=1; n<=20; n++)
{
m = n+hqrnduniformi(&rs, n, _state);
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
bl.ptr.p_double[i] = hqrndnormal(&rs, _state);
bu.ptr.p_double[i] = bl.ptr.p_double[i]+hqrnduniformr(&rs, _state);
x0.ptr.p_double[i] = 1+hqrnduniformr(&rs, _state);
}
ae_matrix_set_length(&c, m, n+1, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n; j++)
{
c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
if( tmpkind==0 )
{
minlmcreatev(n, m, &x0, 10*epsx, &state, _state);
}
if( tmpkind==1 )
{
minlmcreatevj(n, m, &x0, &state, _state);
}
minlmsetcond(&state, epsx, 0, _state);
minlmsetbc(&state, &bl, &bu, _state);
while(minlmiteration(&state, _state))
{
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_less(state.x.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:728");
ae_set_error_flag(errorflag, ae_fp_greater(state.x.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:729");
}
if( state.needfi )
{
testminlmunit_testfunc1(n, m, &c, &state.x, &v, ae_false, &state.fi, ae_true, &state.j, ae_false, _state);
continue;
}
if( state.needfij )
{
testminlmunit_testfunc1(n, m, &c, &state.x, &v, ae_false, &state.fi, ae_true, &state.j, ae_true, _state);
continue;
}
ae_assert(ae_false, "minlm test: integrity check failed", _state);
}
minlmresults(&state, &x, &rep, _state);
ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:744");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
testminlmunit_testfunc1(n, m, &c, &x, &f0, ae_true, &state.fi, ae_false, &state.j, ae_false, _state);
ae_vector_set_length(&x1, n, _state);
h = 0.001;
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_less(x.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:753");
ae_set_error_flag(errorflag, ae_fp_greater(x.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:754");
if( ae_fp_greater_eq(x.ptr.p_double[i]+h,bl.ptr.p_double[i])&&ae_fp_less_eq(x.ptr.p_double[i]+h,bu.ptr.p_double[i]) )
{
for(j=0; j<=n-1; j++)
{
x1.ptr.p_double[j] = x.ptr.p_double[j];
}
x1.ptr.p_double[i] = x.ptr.p_double[i]+h;
testminlmunit_testfunc1(n, m, &c, &x1, &f1, ae_true, &state.fi, ae_false, &state.j, ae_false, _state);
ae_set_error_flag(errorflag, ae_fp_less(f1,f0*(1-tolf)), __FILE__, __LINE__, "testminlmunit.ap:763");
}
if( ae_fp_greater_eq(x.ptr.p_double[i]-h,bl.ptr.p_double[i])&&ae_fp_less_eq(x.ptr.p_double[i]-h,bu.ptr.p_double[i]) )
{
for(j=0; j<=n-1; j++)
{
x1.ptr.p_double[j] = x.ptr.p_double[j];
}
x1.ptr.p_double[i] = x.ptr.p_double[i]-h;
testminlmunit_testfunc1(n, m, &c, &x1, &f1, ae_true, &state.fi, ae_false, &state.j, ae_false, _state);
ae_set_error_flag(errorflag, ae_fp_less(f1,f0*(1-tolf)), __FILE__, __LINE__, "testminlmunit.ap:773");
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Test for linearly constrained problems.
On failure sets error flag, leaves it unchanged on success.
*************************************************************************/
static void testminlmunit_testlc(ae_bool* errorflag, ae_state *_state)
{
ae_frame _frame_block;
minlmstate state;
minlmreport rep;
ae_vector bl;
ae_vector bu;
ae_int_t n;
ae_int_t m;
ae_int_t m1;
ae_int_t m2;
ae_vector x0;
ae_vector x;
ae_vector xe;
ae_vector x1;
ae_vector x12;
ae_vector d;
ae_matrix rawc;
ae_vector rawct;
ae_int_t rawccnt;
ae_matrix c;
ae_matrix c12;
ae_matrix z;
ae_int_t trialidx;
ae_int_t i;
ae_int_t j;
double v;
double h;
ae_int_t optkind;
hqrndstate rs;
double epsx;
double xtol;
double tolf;
double f0;
double f1;
ae_bool bflag;
ae_frame_make(_state, &_frame_block);
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&bl, 0, sizeof(bl));
memset(&bu, 0, sizeof(bu));
memset(&x0, 0, sizeof(x0));
memset(&x, 0, sizeof(x));
memset(&xe, 0, sizeof(xe));
memset(&x1, 0, sizeof(x1));
memset(&x12, 0, sizeof(x12));
memset(&d, 0, sizeof(d));
memset(&rawc, 0, sizeof(rawc));
memset(&rawct, 0, sizeof(rawct));
memset(&c, 0, sizeof(c));
memset(&c12, 0, sizeof(c12));
memset(&z, 0, sizeof(z));
memset(&rs, 0, sizeof(rs));
_minlmstate_init(&state, _state, ae_true);
_minlmreport_init(&rep, _state, ae_true);
ae_vector_init(&bl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xe, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x12, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&rawc, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rawct, 0, DT_INT, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c12, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Minimize
*
* [ [ ]2 ]
* SUM_i[ SUM_j[ (0.1*x_j+power(x_j,3))*c_ij ] ]
* [ [ ] ]
*
* subject to mix of box and linear inequality constraints on x_j
*
* We check correctness of solution by sampling a few random points
* around one returned by optimizer, and comparing function value
* with target. Sampling is performed with respect to inequality
* constraints.
*/
epsx = 1.0E-12;
xtol = 1.0E-8;
tolf = 1.0E-10;
for(optkind=0; optkind<=1; optkind++)
{
for(n=5; n<=20; n++)
{
/*
* Generate problem
*/
m = n+hqrnduniformi(&rs, n, _state);
ae_vector_set_length(&bl, n, _state);
ae_vector_set_length(&bu, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
bl.ptr.p_double[i] = hqrndnormal(&rs, _state);
bu.ptr.p_double[i] = bl.ptr.p_double[i]+hqrnduniformr(&rs, _state);
x0.ptr.p_double[i] = bl.ptr.p_double[i]+(bu.ptr.p_double[i]-bl.ptr.p_double[i])*hqrnduniformr(&rs, _state);
}
ae_matrix_set_length(&c, m, n+1, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n; j++)
{
c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
ae_assert(n>=5, "Assertion failed", _state);
rawccnt = 3;
ae_matrix_set_length(&rawc, rawccnt, n+1, _state);
ae_vector_set_length(&rawct, rawccnt, _state);
for(i=0; i<=rawccnt-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
rawc.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
v = v+x0.ptr.p_double[j]*rawc.ptr.pp_double[i][j];
}
rawc.ptr.pp_double[i][n] = v;
rawct.ptr.p_int[i] = 2*hqrnduniformi(&rs, 2, _state)-1;
}
/*
* Solve
*/
if( optkind==0 )
{
minlmcreatev(n, m, &x0, 10*epsx, &state, _state);
}
if( optkind==1 )
{
minlmcreatevj(n, m, &x0, &state, _state);
}
minlmsetcond(&state, epsx, 0, _state);
minlmsetbc(&state, &bl, &bu, _state);
minlmsetlc(&state, &rawc, &rawct, rawccnt, _state);
while(minlmiteration(&state, _state))
{
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_less(state.x.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:878");
ae_set_error_flag(errorflag, ae_fp_greater(state.x.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:879");
}
if( state.needfi )
{
testminlmunit_testfunc1(n, m, &c, &state.x, &v, ae_false, &state.fi, ae_true, &state.j, ae_false, _state);
continue;
}
if( state.needfij )
{
testminlmunit_testfunc1(n, m, &c, &state.x, &v, ae_false, &state.fi, ae_true, &state.j, ae_true, _state);
continue;
}
ae_assert(ae_false, "minlm test: integrity check failed", _state);
}
minlmresults(&state, &x, &rep, _state);
ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:894");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
/*
* Test feasibility w.r.t. box and linear inequality constraints
*/
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_less(x.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:903");
ae_set_error_flag(errorflag, ae_fp_greater(x.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:904");
}
for(i=0; i<=rawccnt-1; i++)
{
v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = v-rawc.ptr.pp_double[i][n];
if( rawct.ptr.p_int[i]>0 )
{
ae_set_error_flag(errorflag, ae_fp_less(v,-xtol), __FILE__, __LINE__, "testminlmunit.ap:911");
}
if( rawct.ptr.p_int[i]<0 )
{
ae_set_error_flag(errorflag, ae_fp_greater(v,xtol), __FILE__, __LINE__, "testminlmunit.ap:913");
}
}
/*
* Make several random trial steps and:
* 0) generate small random trial step
* 1) if step is infeasible, skip to next trial
* 2) compare function value in the trial point against one in other points
*/
testminlmunit_testfunc1(n, m, &c, &x, &f0, ae_true, &state.fi, ae_false, &state.j, ae_false, _state);
ae_vector_set_length(&x1, n, _state);
for(trialidx=0; trialidx<=10*n; trialidx++)
{
h = 0.001;
for(i=0; i<=n-1; i++)
{
do
{
x1.ptr.p_double[i] = x.ptr.p_double[i]+(hqrnduniformr(&rs, _state)*2-1)*h;
}
while(!(ae_fp_greater_eq(x1.ptr.p_double[i],bl.ptr.p_double[i])&&ae_fp_less_eq(x1.ptr.p_double[i],bu.ptr.p_double[i])));
}
bflag = ae_false;
for(i=0; i<=rawccnt-1; i++)
{
ae_assert(rawct.ptr.p_int[i]!=0, "Assertion failed", _state);
v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = v-rawc.ptr.pp_double[i][n];
bflag = bflag||(rawct.ptr.p_int[i]>0&&ae_fp_less(v,(double)(0)));
bflag = bflag||(rawct.ptr.p_int[i]<0&&ae_fp_greater(v,(double)(0)));
}
if( bflag )
{
continue;
}
testminlmunit_testfunc1(n, m, &c, &x1, &f1, ae_true, &state.fi, ae_false, &state.j, ae_false, _state);
ae_set_error_flag(errorflag, ae_fp_less(f1,f0*(1-tolf)), __FILE__, __LINE__, "testminlmunit.ap:950");
}
}
}
/*
* Minimize
*
* [ [ ]2 ]
* SUM_i[ SUM_j[ (0.1*x_j+power(x_j,3))*c_ij ] ]
* [ [ ] ]
*
* subject to linear EQUALITY constraints on x_j.
*
* We check correctness of solution by sampling a few random points
* around one returned by optimizer, and comparing function value
* with target. Sampling is performed with respect to equality
* constraints. In order to simplify algorithm we use orthogonal
* equality constraints.
*
* NOTE: we solve problem using VJ mode (analytic Jacobian) because
* roundoff errors from numerical differentiation sometimes
* prevent us from converging with good precision.
*/
epsx = 1.0E-12;
xtol = 1.0E-8;
tolf = 1.0E-10;
optkind = 1;
for(n=10; n<=20; n++)
{
/*
* Generate problem
*/
m = n+hqrnduniformi(&rs, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_matrix_set_length(&c, m, n+1, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n; j++)
{
c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
ae_assert(n>=5, "Assertion failed", _state);
rawccnt = 1+hqrnduniformi(&rs, 5, _state);
rmatrixrndorthogonal(n, &z, _state);
ae_matrix_set_length(&rawc, rawccnt, n+1, _state);
ae_vector_set_length(&rawct, rawccnt, _state);
for(i=0; i<=rawccnt-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
rawc.ptr.pp_double[i][j] = z.ptr.pp_double[i][j];
v = v+x0.ptr.p_double[j]*rawc.ptr.pp_double[i][j];
}
rawc.ptr.pp_double[i][n] = v;
rawct.ptr.p_int[i] = 0;
}
/*
* Solve
*/
if( optkind==0 )
{
minlmcreatev(n, m, &x0, 1.0E-12, &state, _state);
}
if( optkind==1 )
{
minlmcreatevj(n, m, &x0, &state, _state);
}
minlmsetcond(&state, epsx, 0, _state);
minlmsetlc(&state, &rawc, &rawct, rawccnt, _state);
while(minlmiteration(&state, _state))
{
if( state.needfi )
{
testminlmunit_testfunc1(n, m, &c, &state.x, &v, ae_false, &state.fi, ae_true, &state.j, ae_false, _state);
continue;
}
if( state.needfij )
{
testminlmunit_testfunc1(n, m, &c, &state.x, &v, ae_false, &state.fi, ae_true, &state.j, ae_true, _state);
continue;
}
ae_assert(ae_false, "minlm test: integrity check failed", _state);
}
minlmresults(&state, &x, &rep, _state);
ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:1031");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
/*
* Test feasibility w.r.t. linear equality constraints
*/
for(i=0; i<=rawccnt-1; i++)
{
v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1));
v = v-rawc.ptr.pp_double[i][n];
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v, _state),xtol), __FILE__, __LINE__, "testminlmunit.ap:1042");
}
/*
* Make several random trial steps and:
* 0) generate small random trial step
* 1) project it onto equality constrained subspace
* 2) compare function value in the trial point against one in other points
*/
testminlmunit_testfunc1(n, m, &c, &x, &f0, ae_true, &state.fi, ae_false, &state.j, ae_false, _state);
ae_vector_set_length(&x1, n, _state);
for(trialidx=0; trialidx<=10*n; trialidx++)
{
h = 0.001;
for(i=0; i<=n-1; i++)
{
x1.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
for(i=0; i<=rawccnt-1; i++)
{
v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1));
ae_v_subd(&x1.ptr.p_double[0], 1, &rawc.ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v);
}
v = ae_v_dotproduct(&x1.ptr.p_double[0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,n-1));
ae_assert(ae_fp_greater(v,(double)(0)), "Assertion failed", _state);
v = h/ae_sqrt(v, _state);
ae_v_muld(&x1.ptr.p_double[0], 1, ae_v_len(0,n-1), v);
ae_v_add(&x1.ptr.p_double[0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,n-1));
testminlmunit_testfunc1(n, m, &c, &x1, &f1, ae_true, &state.fi, ae_false, &state.j, ae_false, _state);
ae_set_error_flag(errorflag, ae_fp_less(f1,f0*(1-tolf)), __FILE__, __LINE__, "testminlmunit.ap:1072");
}
}
/*
* Minimize
*
* [ [ ]2 ] [ [ ]2 ]
* SUM_i[ SUM_j[ (0.1*x_j+power(x0_j,3))*c0_ij ] ] + SUM_i[ SUM_j[ (0.1*x_j+power(x1_j,3))*c1_ij ] ]
* [ [ ] ] [ [ ] ]
*
* for two sets of unknowns (x0_j and x1_j) and two sets of
* coefficients (c0_ij and c1_ij, M1*N and M2*N matrices) subject
* to equality constraint
*
* x0_j=x1_j for all j
*
* Such optimization problem arises when we fit same model to
* two distinct datasets and want to share SOME of coefficients
* between fits. If we share ALL coefficients, it is equal to
* fitting one model to combination of two datasets.
*
* Our test checks that such "combined" 2N-dimensional problem
* solved with general linear constraints which "glue" two datasets
* together returns same answer as N-dimensional problem on (M1+M2)-point
* dataset.
*
* NOTE: we solve problem using VJ mode (analytic Jacobian) because
* roundoff errors from numerical differentiation prevent us
* from converging with good precision.
*/
epsx = 1.0E-12;
for(n=5; n<=20; n++)
{
/*
* Generate problems
*/
m1 = n+hqrnduniformi(&rs, n, _state);
m2 = n+hqrnduniformi(&rs, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&x12, 2*n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = hqrndnormal(&rs, _state);
x12.ptr.p_double[2*i+0] = hqrndnormal(&rs, _state);
x12.ptr.p_double[2*i+1] = hqrndnormal(&rs, _state);
}
ae_matrix_set_length(&c, m1+m2, n+1, _state);
ae_matrix_set_length(&c12, m1+m2, 2*n+1, _state);
for(i=0; i<=m1+m2-1; i++)
{
for(j=0; j<=2*n; j++)
{
c12.ptr.pp_double[i][j] = (double)(0);
}
}
for(i=0; i<=m1+m2-1; i++)
{
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
if( iv_nan;
if( i==1 )
{
v = _state->v_posinf;
}
if( i==2 )
{
v = _state->v_neginf;
}
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
state.fi.ptr.p_double[ae_randominteger(m, _state)] = v;
}
else
{
state.j.ptr.pp_double[ae_randominteger(m, _state)][ae_randominteger(n, _state)] = v;
}
inc(&spoilcnt, _state);
}
continue;
}
if( state.needfi )
{
for(i=0; i<=n-2; i++)
{
state.fi.ptr.p_double[2*i+0] = s*(state.x.ptr.p_double[i+1]-ae_sqr(state.x.ptr.p_double[i], _state));
state.fi.ptr.p_double[2*i+1] = 1-state.x.ptr.p_double[i];
}
mx = (double)(0);
for(i=0; i<=n-1; i++)
{
mx = ae_maxreal(mx, ae_fabs(state.x.ptr.p_double[i]-1, _state), _state);
}
if( ae_fp_less(mx,1.0E-2) )
{
i = ae_randominteger(3, _state);
v = _state->v_nan;
if( i==1 )
{
v = _state->v_posinf;
}
if( i==2 )
{
v = _state->v_neginf;
}
state.fi.ptr.p_double[ae_randominteger(m, _state)] = v;
inc(&spoilcnt, _state);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minlmresults(&state, &x, &rep, _state);
ae_set_error_flag(errorflag, rep.terminationtype!=-8, __FILE__, __LINE__, "testminlmunit.ap:1513");
ae_set_error_flag(errorflag, spoilcnt!=1, __FILE__, __LINE__, "testminlmunit.ap:1514");
ae_frame_leave(_state);
}
/*************************************************************************
This function tests OptGuard
On failure sets error flag.
*************************************************************************/
static void testminlmunit_testoptguard(ae_bool* wereerrors,
ae_state *_state)
{
ae_frame _frame_block;
hqrndstate rs;
double v;
minlmstate state;
minlmreport rep;
optguardreport ogrep;
ae_int_t i;
ae_int_t j;
ae_int_t n;
ae_matrix a;
ae_matrix a1;
ae_vector s;
ae_vector x0;
ae_vector x1;
ae_vector bndl;
ae_vector bndu;
double diffstep;
ae_int_t defecttype;
ae_int_t funcidx;
ae_int_t varidx;
ae_int_t skind;
ae_matrix jactrue;
ae_matrix jacdefect;
ae_frame_make(_state, &_frame_block);
memset(&rs, 0, sizeof(rs));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&ogrep, 0, sizeof(ogrep));
memset(&a, 0, sizeof(a));
memset(&a1, 0, sizeof(a1));
memset(&s, 0, sizeof(s));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(&jactrue, 0, sizeof(jactrue));
memset(&jacdefect, 0, sizeof(jacdefect));
_hqrndstate_init(&rs, _state, ae_true);
_minlmstate_init(&state, _state, ae_true);
_minlmreport_init(&rep, _state, ae_true);
_optguardreport_init(&ogrep, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bndu, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&jactrue, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&jacdefect, 0, 0, DT_REAL, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Check that gradient verification is disabled by default:
* gradient checking for bad problem must return nothing
*/
n = 10;
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 1.0+0.1*i;
}
spdmatrixrndcond(n, 1.0E3, &a, _state);
spdmatrixrndcond(n, 1.0E3, &a1, _state);
minlmcreatevj(n, 1, &x0, &state, _state);
minlmsetcond(&state, 1.0E-9, 10, _state);
while(minlmiteration(&state, _state))
{
if( state.needfij )
{
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*state.x.ptr.p_double[i]*v;
}
for(i=0; i<=n-1; i++)
{
state.j.ptr.pp_double[0][i] = (double)(0);
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minlmresults(&state, &x1, &rep, _state);
minlmoptguardresults(&state, &ogrep, _state);
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:1575");
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminlmunit.ap:1576");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(wereerrors, ogrep.badgradxbase.cnt!=0, __FILE__, __LINE__, "testminlmunit.ap:1579");
ae_set_error_flag(wereerrors, ogrep.badgraduser.rows!=0, __FILE__, __LINE__, "testminlmunit.ap:1580");
ae_set_error_flag(wereerrors, ogrep.badgraduser.cols!=0, __FILE__, __LINE__, "testminlmunit.ap:1581");
ae_set_error_flag(wereerrors, ogrep.badgradnum.rows!=0, __FILE__, __LINE__, "testminlmunit.ap:1582");
ae_set_error_flag(wereerrors, ogrep.badgradnum.cols!=0, __FILE__, __LINE__, "testminlmunit.ap:1583");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(wereerrors, ogrep.badgradsuspected, __FILE__, __LINE__, "testminlmunit.ap:1586");
ae_set_error_flag(wereerrors, ogrep.badgradfidx!=-1, __FILE__, __LINE__, "testminlmunit.ap:1587");
ae_set_error_flag(wereerrors, ogrep.badgradvidx!=-1, __FILE__, __LINE__, "testminlmunit.ap:1588");
/*
* Test gradient checking functionality, try various
* defect types:
* * accidental zeroing of some gradient component
* * accidental addition of 1.0 to some component
* * accidental multiplication by 2.0
* Try distorting both target and constraints.
*/
diffstep = 0.001;
n = 10;
for(skind=0; skind<=1; skind++)
{
for(funcidx=0; funcidx<=1; funcidx++)
{
for(defecttype=-1; defecttype<=2; defecttype++)
{
varidx = hqrnduniformi(&rs, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&s, n, _state);
ae_vector_set_length(&bndl, n, _state);
ae_vector_set_length(&bndu, n, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = ae_pow((double)(10), skind*(30*hqrnduniformr(&rs, _state)-15), _state);
x0.ptr.p_double[i] = (1.0+0.1*i)*s.ptr.p_double[i];
j = hqrnduniformi(&rs, 3, _state);
bndl.ptr.p_double[i] = -100*s.ptr.p_double[i];
bndu.ptr.p_double[i] = 100*s.ptr.p_double[i];
if( j==1 )
{
bndl.ptr.p_double[i] = x0.ptr.p_double[i];
}
if( j==2 )
{
bndu.ptr.p_double[i] = x0.ptr.p_double[i];
}
}
spdmatrixrndcond(n, 1.0E3, &a, _state);
spdmatrixrndcond(n, 1.0E3, &a1, _state);
minlmcreatevj(n, 2, &x0, &state, _state);
minlmoptguardgradient(&state, diffstep, _state);
minlmsetcond(&state, 1.0E-9, 10, _state);
minlmsetscale(&state, &s, _state);
minlmsetbc(&state, &bndl, &bndu, _state);
while(minlmiteration(&state, _state))
{
if( state.needfi||state.needfij )
{
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(wereerrors, ae_fp_less(state.x.ptr.p_double[i],bndl.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:1637");
ae_set_error_flag(wereerrors, ae_fp_greater(state.x.ptr.p_double[i],bndu.ptr.p_double[i]), __FILE__, __LINE__, "testminlmunit.ap:1638");
}
state.fi.ptr.p_double[0] = (double)(0);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
state.fi.ptr.p_double[0] = state.fi.ptr.p_double[0]+0.5*(state.x.ptr.p_double[i]/s.ptr.p_double[i])*v;
if( state.needfij )
{
state.j.ptr.pp_double[0][i] = v;
}
}
state.fi.ptr.p_double[1] = (double)(0);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+state.x.ptr.p_double[j]/s.ptr.p_double[j]*a1.ptr.pp_double[i][j];
}
state.fi.ptr.p_double[1] = state.fi.ptr.p_double[1]+0.5*(state.x.ptr.p_double[i]/s.ptr.p_double[i])*v;
if( state.needfij )
{
state.j.ptr.pp_double[1][i] = v;
}
}
if( state.needfij )
{
if( defecttype==0 )
{
state.j.ptr.pp_double[funcidx][varidx] = (double)(0);
}
if( defecttype==1 )
{
state.j.ptr.pp_double[funcidx][varidx] = state.j.ptr.pp_double[funcidx][varidx]+1;
}
if( defecttype==2 )
{
state.j.ptr.pp_double[funcidx][varidx] = state.j.ptr.pp_double[funcidx][varidx]*2;
}
}
if( state.needfij )
{
for(i=0; i<=n-1; i++)
{
state.j.ptr.pp_double[0][i] = state.j.ptr.pp_double[0][i]/s.ptr.p_double[i];
state.j.ptr.pp_double[1][i] = state.j.ptr.pp_double[1][i]/s.ptr.p_double[i];
}
}
continue;
}
ae_assert(ae_false, "Assertion failed", _state);
}
minlmresults(&state, &x1, &rep, _state);
minlmoptguardresults(&state, &ogrep, _state);
/*
* Check that something is returned
*/
ae_set_error_flag(wereerrors, rep.terminationtype<=0, __FILE__, __LINE__, "testminlmunit.ap:1695");
ae_set_error_flag(wereerrors, !isfinitevector(&x1, n, _state), __FILE__, __LINE__, "testminlmunit.ap:1696");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
/*
* Compute reference values for true and spoiled Jacobian at X0
*/
ae_set_error_flag(wereerrors, !isfinitevector(&ogrep.badgradxbase, n, _state), __FILE__, __LINE__, "testminlmunit.ap:1703");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
ae_matrix_set_length(&jactrue, 2, n, _state);
ae_matrix_set_length(&jacdefect, 2, n, _state);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+ogrep.badgradxbase.ptr.p_double[j]/s.ptr.p_double[j]*a.ptr.pp_double[i][j];
}
jactrue.ptr.pp_double[0][i] = v;
jacdefect.ptr.pp_double[0][i] = v;
}
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+ogrep.badgradxbase.ptr.p_double[j]/s.ptr.p_double[j]*a1.ptr.pp_double[i][j];
}
jactrue.ptr.pp_double[1][i] = v;
jacdefect.ptr.pp_double[1][i] = v;
}
if( defecttype==0 )
{
jacdefect.ptr.pp_double[funcidx][varidx] = (double)(0);
}
if( defecttype==1 )
{
jacdefect.ptr.pp_double[funcidx][varidx] = jacdefect.ptr.pp_double[funcidx][varidx]+1;
}
if( defecttype==2 )
{
jacdefect.ptr.pp_double[funcidx][varidx] = jacdefect.ptr.pp_double[funcidx][varidx]*2;
}
for(i=0; i<=n-1; i++)
{
jactrue.ptr.pp_double[0][i] = jactrue.ptr.pp_double[0][i]/s.ptr.p_double[i];
jactrue.ptr.pp_double[1][i] = jactrue.ptr.pp_double[1][i]/s.ptr.p_double[i];
jacdefect.ptr.pp_double[0][i] = jacdefect.ptr.pp_double[0][i]/s.ptr.p_double[i];
jacdefect.ptr.pp_double[1][i] = jacdefect.ptr.pp_double[1][i]/s.ptr.p_double[i];
}
/*
* Check OptGuard report
*/
ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgraduser, 2, n, _state), __FILE__, __LINE__, "testminlmunit.ap:1741");
ae_set_error_flag(wereerrors, !apservisfinitematrix(&ogrep.badgradnum, 2, n, _state), __FILE__, __LINE__, "testminlmunit.ap:1742");
if( *wereerrors )
{
ae_frame_leave(_state);
return;
}
if( defecttype>=0 )
{
ae_set_error_flag(wereerrors, !ogrep.badgradsuspected, __FILE__, __LINE__, "testminlmunit.ap:1747");
ae_set_error_flag(wereerrors, ogrep.badgradfidx!=funcidx, __FILE__, __LINE__, "testminlmunit.ap:1748");
ae_set_error_flag(wereerrors, ogrep.badgradvidx!=varidx, __FILE__, __LINE__, "testminlmunit.ap:1749");
}
else
{
ae_set_error_flag(wereerrors, ogrep.badgradsuspected, __FILE__, __LINE__, "testminlmunit.ap:1753");
ae_set_error_flag(wereerrors, ogrep.badgradfidx!=-1, __FILE__, __LINE__, "testminlmunit.ap:1754");
ae_set_error_flag(wereerrors, ogrep.badgradvidx!=-1, __FILE__, __LINE__, "testminlmunit.ap:1755");
}
for(i=0; i<=1; i++)
{
for(j=0; j<=n-1; j++)
{
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jactrue.ptr.pp_double[i][j]-ogrep.badgradnum.ptr.pp_double[i][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testminlmunit.ap:1760");
ae_set_error_flag(wereerrors, ae_fp_greater(ae_fabs(jacdefect.ptr.pp_double[i][j]-ogrep.badgraduser.ptr.pp_double[i][j], _state),0.01/s.ptr.p_double[j]), __FILE__, __LINE__, "testminlmunit.ap:1761");
}
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Asserts that State fields are consistent with RKind.
Returns False otherwise.
RKind is an algorithm selector:
* -2 = V, AccType=1
* -1 = V, AccType=0
* 0 = FJ
* 1 = FGJ
* 2 = FGH
* 3 = VJ, AccType=0
* 4 = VJ, AccType=1
* 5 = VJ, AccType=2
*************************************************************************/
static ae_bool testminlmunit_rkindvsstatecheck(ae_int_t rkind,
minlmstate* state,
ae_state *_state)
{
ae_int_t nset;
ae_bool result;
nset = 0;
if( state->needfi )
{
nset = nset+1;
}
if( state->needf )
{
nset = nset+1;
}
if( state->needfg )
{
nset = nset+1;
}
if( state->needfij )
{
nset = nset+1;
}
if( state->needfgh )
{
nset = nset+1;
}
if( state->xupdated )
{
nset = nset+1;
}
if( nset!=1 )
{
result = ae_false;
return result;
}
if( rkind==-2 )
{
result = state->needfi||state->xupdated;
return result;
}
if( rkind==-1 )
{
result = state->needfi||state->xupdated;
return result;
}
if( rkind==0 )
{
result = (state->needf||state->needfij)||state->xupdated;
return result;
}
if( rkind==1 )
{
result = ((state->needf||state->needfij)||state->needfg)||state->xupdated;
return result;
}
if( rkind==2 )
{
result = ((state->needf||state->needfg)||state->needfgh)||state->xupdated;
return result;
}
if( rkind==3 )
{
result = (state->needfi||state->needfij)||state->xupdated;
return result;
}
if( rkind==4 )
{
result = (state->needfi||state->needfij)||state->xupdated;
return result;
}
if( rkind==5 )
{
result = (state->needfi||state->needfij)||state->xupdated;
return result;
}
result = ae_false;
return result;
}
/*************************************************************************
Calculates FI/F/G/H for problem min(||Ax-b||)
*************************************************************************/
static void testminlmunit_axmb(minlmstate* state,
/* Real */ ae_matrix* a,
/* Real */ ae_vector* b,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
if( (state->needf||state->needfg)||state->needfgh )
{
state->f = (double)(0);
}
if( state->needfg||state->needfgh )
{
for(i=0; i<=n-1; i++)
{
state->g.ptr.p_double[i] = (double)(0);
}
}
if( state->needfgh )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
state->h.ptr.pp_double[i][j] = (double)(0);
}
}
}
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&a->ptr.pp_double[i][0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,n-1));
if( (state->needf||state->needfg)||state->needfgh )
{
state->f = state->f+ae_sqr(v-b->ptr.p_double[i], _state);
}
if( state->needfg||state->needfgh )
{
for(j=0; j<=n-1; j++)
{
state->g.ptr.p_double[j] = state->g.ptr.p_double[j]+2*(v-b->ptr.p_double[i])*a->ptr.pp_double[i][j];
}
}
if( state->needfgh )
{
for(j=0; j<=n-1; j++)
{
for(k=0; k<=n-1; k++)
{
state->h.ptr.pp_double[j][k] = state->h.ptr.pp_double[j][k]+2*a->ptr.pp_double[i][j]*a->ptr.pp_double[i][k];
}
}
}
if( state->needfi )
{
state->fi.ptr.p_double[i] = v-b->ptr.p_double[i];
}
if( state->needfij )
{
state->fi.ptr.p_double[i] = v-b->ptr.p_double[i];
ae_v_move(&state->j.ptr.pp_double[i][0], 1, &a->ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
}
}
}
/*************************************************************************
This function tries to reproduce previously fixed bugs; in case of bug
being present sets Err to True; leaves it unchanged otherwise.
*************************************************************************/
static void testminlmunit_tryreproducefixedbugs(ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
minlmstate s;
minlmreport rep;
ae_vector bl;
ae_vector bu;
ae_vector x;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&bl, 0, sizeof(bl));
memset(&bu, 0, sizeof(bu));
memset(&x, 0, sizeof(x));
_minlmstate_init(&s, _state, ae_true);
_minlmreport_init(&rep, _state, ae_true);
ae_vector_init(&bl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
/*
* Reproduce bug reported by ISS:
* when solving bound constrained problem with numerical differentiation
* and starting from infeasible point, we won't stop at the feasible point
*/
ae_vector_set_length(&x, 2, _state);
ae_vector_set_length(&bl, 2, _state);
ae_vector_set_length(&bu, 2, _state);
x.ptr.p_double[0] = 2.0;
bl.ptr.p_double[0] = -1.0;
bu.ptr.p_double[0] = 1.0;
x.ptr.p_double[1] = 2.0;
bl.ptr.p_double[1] = -1.0;
bu.ptr.p_double[1] = 1.0;
minlmcreatev(2, 2, &x, 0.001, &s, _state);
minlmsetbc(&s, &bl, &bu, _state);
while(minlmiteration(&s, _state))
{
if( s.needfi )
{
s.fi.ptr.p_double[0] = ae_sqr(s.x.ptr.p_double[0], _state);
s.fi.ptr.p_double[1] = ae_sqr(s.x.ptr.p_double[1], _state);
}
}
minlmresults(&s, &x, &rep, _state);
ae_set_error_flag(err, ((ae_fp_less(x.ptr.p_double[0],bl.ptr.p_double[0])||ae_fp_greater(x.ptr.p_double[0],bu.ptr.p_double[0]))||ae_fp_less(x.ptr.p_double[1],bl.ptr.p_double[1]))||ae_fp_greater(x.ptr.p_double[1],bu.ptr.p_double[1]), __FILE__, __LINE__, "testminlmunit.ap:1923");
ae_frame_leave(_state);
}
/*************************************************************************
Test function 1:
F(N, M, C, X) = SUM( f_i^2 )
f_i = SUM( (power(x_j,3)+alpha*x_j)*c_ij )
*************************************************************************/
static void testminlmunit_testfunc1(ae_int_t n,
ae_int_t m,
/* Real */ ae_matrix* c,
/* Real */ ae_vector* x,
double* f,
ae_bool needf,
/* Real */ ae_vector* fi,
ae_bool needfi,
/* Real */ ae_matrix* jac,
ae_bool needjac,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
double v;
double alpha;
alpha = 0.01;
if( needf )
{
*f = (double)(0);
}
for(i=0; i<=m-1; i++)
{
v = c->ptr.pp_double[i][n];
for(j=0; j<=n-1; j++)
{
v = v+(alpha*x->ptr.p_double[j]+ae_pow(x->ptr.p_double[j], (double)(3), _state))*c->ptr.pp_double[i][j];
if( needjac )
{
jac->ptr.pp_double[i][j] = (alpha+3*ae_pow(x->ptr.p_double[j], (double)(2), _state))*c->ptr.pp_double[i][j];
}
}
if( needfi )
{
fi->ptr.p_double[i] = v;
}
if( needf )
{
*f = *f+v*v;
}
}
}
static void testevdunit_rmatrixfillsparsea(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double sparcity,
double diagmag,
ae_state *_state);
static void testevdunit_cmatrixfillsparsea(/* Complex */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double sparcity,
double diagmag,
ae_state *_state);
static void testevdunit_rmatrixsymmetricsplit(/* Real */ ae_matrix* a,
ae_int_t n,
/* Real */ ae_matrix* al,
/* Real */ ae_matrix* au,
ae_state *_state);
static void testevdunit_cmatrixhermitiansplit(/* Complex */ ae_matrix* a,
ae_int_t n,
/* Complex */ ae_matrix* al,
/* Complex */ ae_matrix* au,
ae_state *_state);
static void testevdunit_unset2d(/* Real */ ae_matrix* a,
ae_state *_state);
static void testevdunit_cunset2d(/* Complex */ ae_matrix* a,
ae_state *_state);
static void testevdunit_unset1d(/* Real */ ae_vector* a,
ae_state *_state);
static double testevdunit_tdtestproduct(/* Real */ ae_vector* d,
/* Real */ ae_vector* e,
ae_int_t n,
/* Real */ ae_matrix* z,
/* Real */ ae_vector* lambdav,
ae_state *_state);
static double testevdunit_testproduct(/* Real */ ae_matrix* a,
ae_int_t n,
/* Real */ ae_matrix* z,
/* Real */ ae_vector* lambdav,
ae_state *_state);
static double testevdunit_testort(/* Real */ ae_matrix* z,
ae_int_t n,
ae_state *_state);
static double testevdunit_testcproduct(/* Complex */ ae_matrix* a,
ae_int_t n,
/* Complex */ ae_matrix* z,
/* Real */ ae_vector* lambdav,
ae_state *_state);
static double testevdunit_testcort(/* Complex */ ae_matrix* z,
ae_int_t n,
ae_state *_state);
static void testevdunit_testsevdproblem(/* Real */ ae_matrix* a,
/* Real */ ae_matrix* al,
/* Real */ ae_matrix* au,
ae_int_t n,
double threshold,
ae_bool* serrors,
ae_int_t* failc,
ae_int_t* runs,
ae_state *_state);
static void testevdunit_testhevdproblem(/* Complex */ ae_matrix* a,
/* Complex */ ae_matrix* al,
/* Complex */ ae_matrix* au,
ae_int_t n,
double threshold,
ae_bool* herrors,
ae_int_t* failc,
ae_int_t* runs,
ae_state *_state);
static void testevdunit_testsevdbiproblem(/* Real */ ae_matrix* afull,
/* Real */ ae_matrix* al,
/* Real */ ae_matrix* au,
ae_int_t n,
ae_bool distvals,
double threshold,
ae_bool* serrors,
ae_int_t* failc,
ae_int_t* runs,
ae_state *_state);
static void testevdunit_testhevdbiproblem(/* Complex */ ae_matrix* afull,
/* Complex */ ae_matrix* al,
/* Complex */ ae_matrix* au,
ae_int_t n,
ae_bool distvals,
double threshold,
ae_bool* herrors,
ae_int_t* failc,
ae_int_t* runs,
ae_state *_state);
static void testevdunit_testtdevdproblem(/* Real */ ae_vector* d,
/* Real */ ae_vector* e,
ae_int_t n,
double threshold,
ae_bool* tderrors,
ae_state *_state);
static void testevdunit_testtdevdbiproblem(/* Real */ ae_vector* d,
/* Real */ ae_vector* e,
ae_int_t n,
ae_bool distvals,
double threshold,
ae_bool* serrors,
ae_int_t* failc,
ae_int_t* runs,
ae_state *_state);
static void testevdunit_testnsevdproblem(/* Real */ ae_matrix* a,
ae_int_t n,
double threshold,
ae_bool* nserrors,
ae_state *_state);
static void testevdunit_testevdset(ae_int_t n,
double threshold,
double bithreshold,
ae_int_t* failc,
ae_int_t* runs,
ae_bool* nserrors,
ae_bool* serrors,
ae_bool* herrors,
ae_bool* tderrors,
ae_bool* sbierrors,
ae_bool* hbierrors,
ae_bool* tdbierrors,
ae_state *_state);
static void testevdunit_testsisymm(ae_bool* errorflag, ae_state *_state);
/*************************************************************************
Testing symmetric EVD subroutine
*************************************************************************/
ae_bool testevd(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_matrix ra;
ae_int_t n;
ae_int_t j;
ae_int_t failc;
ae_int_t runs;
double failthreshold;
double threshold;
double bithreshold;
ae_bool waserrors;
ae_bool nserrors;
ae_bool serrors;
ae_bool herrors;
ae_bool tderrors;
ae_bool sbierrors;
ae_bool hbierrors;
ae_bool tdbierrors;
ae_bool sisymmerrors;
ae_bool wfailed;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&ra, 0, sizeof(ra));
ae_matrix_init(&ra, 0, 0, DT_REAL, _state, ae_true);
failthreshold = 0.005;
threshold = 1.0E-8;
bithreshold = 1.0E-6;
nserrors = ae_false;
serrors = ae_false;
herrors = ae_false;
tderrors = ae_false;
sbierrors = ae_false;
hbierrors = ae_false;
tdbierrors = ae_false;
sisymmerrors = ae_false;
failc = 0;
runs = 0;
/*
* Test subspace iteration solver
*/
testevdunit_testsisymm(&sisymmerrors, _state);
/*
* Test dense solvers
*/
for(n=1; n<=ablasblocksize(&ra, _state); n++)
{
testevdunit_testevdset(n, threshold, bithreshold, &failc, &runs, &nserrors, &serrors, &herrors, &tderrors, &sbierrors, &hbierrors, &tdbierrors, _state);
}
for(j=2; j<=3; j++)
{
for(n=j*ablasblocksize(&ra, _state)-1; n<=j*ablasblocksize(&ra, _state)+1; n++)
{
testevdunit_testevdset(n, threshold, bithreshold, &failc, &runs, &nserrors, &serrors, &herrors, &tderrors, &sbierrors, &hbierrors, &tdbierrors, _state);
}
}
/*
* report
*/
wfailed = ae_fp_greater((double)failc/(double)runs,failthreshold);
waserrors = (((((((nserrors||serrors)||herrors)||tderrors)||sbierrors)||hbierrors)||tdbierrors)||wfailed)||sisymmerrors;
if( !silent )
{
printf("TESTING EVD UNIT\n");
printf("DENSE DIRECT SOLVERS:\n");
printf("* NS ");
if( !nserrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* S ");
if( !serrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* H ");
if( !herrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* TD ");
if( !tderrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* SBI ");
if( !sbierrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* HBI ");
if( !hbierrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* TDBI ");
if( !tdbierrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* FAILURE THRESHOLD ");
if( !wfailed )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("ITERATIVE SOLVERS:\n");
printf("* SUBSPACE ITERATION (S) ");
if( !sisymmerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Sparse fill
Sparcity - sparcity level, in [0,1] (0=dense matrix).
DiagMAg - magnitude of dense diagonal entries; zero value means that diagonal
is sparse too, non-zero value means that diagonal is dense
*************************************************************************/
static void testevdunit_rmatrixfillsparsea(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double sparcity,
double diagmag,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_greater_eq(ae_randomreal(_state),sparcity) )
{
a->ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
else
{
a->ptr.pp_double[i][j] = (double)(0);
}
}
}
if( ae_fp_greater(diagmag,(double)(0)) )
{
for(i=0; i<=ae_minint(m, n, _state)-1; i++)
{
a->ptr.pp_double[i][i] = diagmag*(2*ae_randomreal(_state)-1);
}
}
}
/*************************************************************************
Sparse fill
Sparcity - sparcity level, in [0,1] (0=dense matrix).
DiagMAg - magnitude of dense diagonal entries; zero value means that diagonal
is sparse too, non-zero value means that diagonal is dense
*************************************************************************/
static void testevdunit_cmatrixfillsparsea(/* Complex */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
double sparcity,
double diagmag,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_greater_eq(ae_randomreal(_state),sparcity) )
{
a->ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
a->ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
else
{
a->ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
}
if( ae_fp_greater(diagmag,(double)(0)) )
{
for(i=0; i<=ae_minint(m, n, _state)-1; i++)
{
a->ptr.pp_complex[i][i].x = diagmag*(2*ae_randomreal(_state)-1);
a->ptr.pp_complex[i][i].y = diagmag*(2*ae_randomreal(_state)-1);
}
}
}
/*************************************************************************
Copies A to AL (lower half) and AU (upper half), filling unused parts by
random garbage.
*************************************************************************/
static void testevdunit_rmatrixsymmetricsplit(/* Real */ ae_matrix* a,
ae_int_t n,
/* Real */ ae_matrix* al,
/* Real */ ae_matrix* au,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
for(i=0; i<=n-1; i++)
{
for(j=i+1; j<=n-1; j++)
{
al->ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
al->ptr.pp_double[j][i] = a->ptr.pp_double[i][j];
au->ptr.pp_double[i][j] = a->ptr.pp_double[i][j];
au->ptr.pp_double[j][i] = 2*ae_randomreal(_state)-1;
}
al->ptr.pp_double[i][i] = a->ptr.pp_double[i][i];
au->ptr.pp_double[i][i] = a->ptr.pp_double[i][i];
}
}
/*************************************************************************
Copies A to AL (lower half) and AU (upper half), filling unused parts by
random garbage.
*************************************************************************/
static void testevdunit_cmatrixhermitiansplit(/* Complex */ ae_matrix* a,
ae_int_t n,
/* Complex */ ae_matrix* al,
/* Complex */ ae_matrix* au,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
for(i=0; i<=n-1; i++)
{
for(j=i+1; j<=n-1; j++)
{
al->ptr.pp_complex[i][j] = ae_complex_from_d(2*ae_randomreal(_state)-1);
al->ptr.pp_complex[j][i] = ae_c_conj(a->ptr.pp_complex[i][j], _state);
au->ptr.pp_complex[i][j] = a->ptr.pp_complex[i][j];
au->ptr.pp_complex[j][i] = ae_complex_from_d(2*ae_randomreal(_state)-1);
}
al->ptr.pp_complex[i][i] = a->ptr.pp_complex[i][i];
au->ptr.pp_complex[i][i] = a->ptr.pp_complex[i][i];
}
}
/*************************************************************************
Unsets 2D array.
*************************************************************************/
static void testevdunit_unset2d(/* Real */ ae_matrix* a,
ae_state *_state)
{
ae_matrix_clear(a);
if( a->rows*a->cols>0 )
{
ae_matrix_set_length(a, 1, 1, _state);
}
}
/*************************************************************************
Unsets 2D array.
*************************************************************************/
static void testevdunit_cunset2d(/* Complex */ ae_matrix* a,
ae_state *_state)
{
ae_matrix_set_length(a, 0+1, 0+1, _state);
a->ptr.pp_complex[0][0] = ae_complex_from_d(2*ae_randomreal(_state)-1);
}
/*************************************************************************
Unsets 1D array.
*************************************************************************/
static void testevdunit_unset1d(/* Real */ ae_vector* a,
ae_state *_state)
{
ae_vector_clear(a);
if( a->cnt>0 )
{
ae_vector_set_length(a, 1, _state);
}
}
/*************************************************************************
Tests Z*Lambda*Z' against tridiag(D,E).
Returns relative error.
*************************************************************************/
static double testevdunit_tdtestproduct(/* Real */ ae_vector* d,
/* Real */ ae_vector* e,
ae_int_t n,
/* Real */ ae_matrix* z,
/* Real */ ae_vector* lambdav,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
double mx;
double result;
result = (double)(0);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
/*
* Calculate V = A[i,j], A = Z*Lambda*Z'
*/
v = (double)(0);
for(k=0; k<=n-1; k++)
{
v = v+z->ptr.pp_double[i][k]*lambdav->ptr.p_double[k]*z->ptr.pp_double[j][k];
}
/*
* Compare
*/
if( ae_iabs(i-j, _state)==0 )
{
result = ae_maxreal(result, ae_fabs(v-d->ptr.p_double[i], _state), _state);
}
if( ae_iabs(i-j, _state)==1 )
{
result = ae_maxreal(result, ae_fabs(v-e->ptr.p_double[ae_minint(i, j, _state)], _state), _state);
}
if( ae_iabs(i-j, _state)>1 )
{
result = ae_maxreal(result, ae_fabs(v, _state), _state);
}
}
}
mx = (double)(0);
for(i=0; i<=n-1; i++)
{
mx = ae_maxreal(mx, ae_fabs(d->ptr.p_double[i], _state), _state);
}
for(i=0; i<=n-2; i++)
{
mx = ae_maxreal(mx, ae_fabs(e->ptr.p_double[i], _state), _state);
}
if( ae_fp_eq(mx,(double)(0)) )
{
mx = (double)(1);
}
result = result/mx;
return result;
}
/*************************************************************************
Tests Z*Lambda*Z' against A
Returns relative error.
*************************************************************************/
static double testevdunit_testproduct(/* Real */ ae_matrix* a,
ae_int_t n,
/* Real */ ae_matrix* z,
/* Real */ ae_vector* lambdav,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
double mx;
double result;
result = (double)(0);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
/*
* Calculate V = A[i,j], A = Z*Lambda*Z'
*/
v = (double)(0);
for(k=0; k<=n-1; k++)
{
v = v+z->ptr.pp_double[i][k]*lambdav->ptr.p_double[k]*z->ptr.pp_double[j][k];
}
/*
* Compare
*/
result = ae_maxreal(result, ae_fabs(v-a->ptr.pp_double[i][j], _state), _state);
}
}
mx = (double)(0);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
mx = ae_maxreal(mx, ae_fabs(a->ptr.pp_double[i][j], _state), _state);
}
}
if( ae_fp_eq(mx,(double)(0)) )
{
mx = (double)(1);
}
result = result/mx;
return result;
}
/*************************************************************************
Tests Z*Z' against diag(1...1)
Returns absolute error.
*************************************************************************/
static double testevdunit_testort(/* Real */ ae_matrix* z,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
double v;
double result;
result = (double)(0);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&z->ptr.pp_double[0][i], z->stride, &z->ptr.pp_double[0][j], z->stride, ae_v_len(0,n-1));
if( i==j )
{
v = v-1;
}
result = ae_maxreal(result, ae_fabs(v, _state), _state);
}
}
return result;
}
/*************************************************************************
Tests Z*Lambda*Z' against A
Returns relative error.
*************************************************************************/
static double testevdunit_testcproduct(/* Complex */ ae_matrix* a,
ae_int_t n,
/* Complex */ ae_matrix* z,
/* Real */ ae_vector* lambdav,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_complex v;
double mx;
double result;
result = (double)(0);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
/*
* Calculate V = A[i,j], A = Z*Lambda*Z'
*/
v = ae_complex_from_i(0);
for(k=0; k<=n-1; k++)
{
v = ae_c_add(v,ae_c_mul(ae_c_mul_d(z->ptr.pp_complex[i][k],lambdav->ptr.p_double[k]),ae_c_conj(z->ptr.pp_complex[j][k], _state)));
}
/*
* Compare
*/
result = ae_maxreal(result, ae_c_abs(ae_c_sub(v,a->ptr.pp_complex[i][j]), _state), _state);
}
}
mx = (double)(0);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
mx = ae_maxreal(mx, ae_c_abs(a->ptr.pp_complex[i][j], _state), _state);
}
}
if( ae_fp_eq(mx,(double)(0)) )
{
mx = (double)(1);
}
result = result/mx;
return result;
}
/*************************************************************************
Tests Z*Z' against diag(1...1)
Returns absolute error.
*************************************************************************/
static double testevdunit_testcort(/* Complex */ ae_matrix* z,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_complex v;
double result;
result = (double)(0);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_cdotproduct(&z->ptr.pp_complex[0][i], z->stride, "N", &z->ptr.pp_complex[0][j], z->stride, "Conj", ae_v_len(0,n-1));
if( i==j )
{
v = ae_c_sub_d(v,1);
}
result = ae_maxreal(result, ae_c_abs(v, _state), _state);
}
}
return result;
}
/*************************************************************************
Tests SEVD problem
*************************************************************************/
static void testevdunit_testsevdproblem(/* Real */ ae_matrix* a,
/* Real */ ae_matrix* al,
/* Real */ ae_matrix* au,
ae_int_t n,
double threshold,
ae_bool* serrors,
ae_int_t* failc,
ae_int_t* runs,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector lambdav;
ae_vector lambdaref;
ae_matrix z;
ae_int_t i;
ae_frame_make(_state, &_frame_block);
memset(&lambdav, 0, sizeof(lambdav));
memset(&lambdaref, 0, sizeof(lambdaref));
memset(&z, 0, sizeof(z));
ae_vector_init(&lambdav, 0, DT_REAL, _state, ae_true);
ae_vector_init(&lambdaref, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true);
/*
* Test simple EVD: values and full vectors, lower A
*/
testevdunit_unset1d(&lambdaref, _state);
testevdunit_unset2d(&z, _state);
*runs = *runs+1;
if( !smatrixevd(al, n, 1, ae_false, &lambdaref, &z, _state) )
{
*failc = *failc+1;
ae_frame_leave(_state);
return;
}
*serrors = *serrors||ae_fp_greater(testevdunit_testproduct(a, n, &z, &lambdaref, _state),threshold);
*serrors = *serrors||ae_fp_greater(testevdunit_testort(&z, n, _state),threshold);
for(i=0; i<=n-2; i++)
{
if( ae_fp_less(lambdaref.ptr.p_double[i+1],lambdaref.ptr.p_double[i]) )
{
*serrors = ae_true;
ae_frame_leave(_state);
return;
}
}
/*
* Test simple EVD: values and full vectors, upper A
*/
testevdunit_unset1d(&lambdav, _state);
testevdunit_unset2d(&z, _state);
*runs = *runs+1;
if( !smatrixevd(au, n, 1, ae_true, &lambdav, &z, _state) )
{
*failc = *failc+1;
ae_frame_leave(_state);
return;
}
*serrors = *serrors||ae_fp_greater(testevdunit_testproduct(a, n, &z, &lambdav, _state),threshold);
*serrors = *serrors||ae_fp_greater(testevdunit_testort(&z, n, _state),threshold);
for(i=0; i<=n-2; i++)
{
if( ae_fp_less(lambdav.ptr.p_double[i+1],lambdav.ptr.p_double[i]) )
{
*serrors = ae_true;
ae_frame_leave(_state);
return;
}
}
/*
* Test simple EVD: values only, lower A
*/
testevdunit_unset1d(&lambdav, _state);
testevdunit_unset2d(&z, _state);
*runs = *runs+1;
if( !smatrixevd(al, n, 0, ae_false, &lambdav, &z, _state) )
{
*failc = *failc+1;
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
*serrors = *serrors||ae_fp_greater(ae_fabs(lambdav.ptr.p_double[i]-lambdaref.ptr.p_double[i], _state),threshold);
}
/*
* Test simple EVD: values only, upper A
*/
testevdunit_unset1d(&lambdav, _state);
testevdunit_unset2d(&z, _state);
*runs = *runs+1;
if( !smatrixevd(au, n, 0, ae_true, &lambdav, &z, _state) )
{
*failc = *failc+1;
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
*serrors = *serrors||ae_fp_greater(ae_fabs(lambdav.ptr.p_double[i]-lambdaref.ptr.p_double[i], _state),threshold);
}
ae_frame_leave(_state);
}
/*************************************************************************
Tests SEVD problem
*************************************************************************/
static void testevdunit_testhevdproblem(/* Complex */ ae_matrix* a,
/* Complex */ ae_matrix* al,
/* Complex */ ae_matrix* au,
ae_int_t n,
double threshold,
ae_bool* herrors,
ae_int_t* failc,
ae_int_t* runs,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector lambdav;
ae_vector lambdaref;
ae_matrix z;
ae_int_t i;
ae_frame_make(_state, &_frame_block);
memset(&lambdav, 0, sizeof(lambdav));
memset(&lambdaref, 0, sizeof(lambdaref));
memset(&z, 0, sizeof(z));
ae_vector_init(&lambdav, 0, DT_REAL, _state, ae_true);
ae_vector_init(&lambdaref, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&z, 0, 0, DT_COMPLEX, _state, ae_true);
/*
* Test simple EVD: values and full vectors, lower A
*/
testevdunit_unset1d(&lambdaref, _state);
testevdunit_cunset2d(&z, _state);
*runs = *runs+1;
if( !hmatrixevd(al, n, 1, ae_false, &lambdaref, &z, _state) )
{
*failc = *failc+1;
ae_frame_leave(_state);
return;
}
*herrors = *herrors||ae_fp_greater(testevdunit_testcproduct(a, n, &z, &lambdaref, _state),threshold);
*herrors = *herrors||ae_fp_greater(testevdunit_testcort(&z, n, _state),threshold);
for(i=0; i<=n-2; i++)
{
if( ae_fp_less(lambdaref.ptr.p_double[i+1],lambdaref.ptr.p_double[i]) )
{
*herrors = ae_true;
ae_frame_leave(_state);
return;
}
}
/*
* Test simple EVD: values and full vectors, upper A
*/
testevdunit_unset1d(&lambdav, _state);
testevdunit_cunset2d(&z, _state);
*runs = *runs+1;
if( !hmatrixevd(au, n, 1, ae_true, &lambdav, &z, _state) )
{
*failc = *failc+1;
ae_frame_leave(_state);
return;
}
*herrors = *herrors||ae_fp_greater(testevdunit_testcproduct(a, n, &z, &lambdav, _state),threshold);
*herrors = *herrors||ae_fp_greater(testevdunit_testcort(&z, n, _state),threshold);
for(i=0; i<=n-2; i++)
{
if( ae_fp_less(lambdav.ptr.p_double[i+1],lambdav.ptr.p_double[i]) )
{
*herrors = ae_true;
ae_frame_leave(_state);
return;
}
}
/*
* Test simple EVD: values only, lower A
*/
testevdunit_unset1d(&lambdav, _state);
testevdunit_cunset2d(&z, _state);
*runs = *runs+1;
if( !hmatrixevd(al, n, 0, ae_false, &lambdav, &z, _state) )
{
*failc = *failc+1;
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
*herrors = *herrors||ae_fp_greater(ae_fabs(lambdav.ptr.p_double[i]-lambdaref.ptr.p_double[i], _state),threshold);
}
/*
* Test simple EVD: values only, upper A
*/
testevdunit_unset1d(&lambdav, _state);
testevdunit_cunset2d(&z, _state);
*runs = *runs+1;
if( !hmatrixevd(au, n, 0, ae_true, &lambdav, &z, _state) )
{
*failc = *failc+1;
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
*herrors = *herrors||ae_fp_greater(ae_fabs(lambdav.ptr.p_double[i]-lambdaref.ptr.p_double[i], _state),threshold);
}
ae_frame_leave(_state);
}
/*************************************************************************
Tests EVD problem
DistVals - is True, when eigenvalues are distinct. Is False, when we
are solving sparse task with lots of zero eigenvalues.
In such cases some tests related to the eigenvectors are
not performed.
*************************************************************************/
static void testevdunit_testsevdbiproblem(/* Real */ ae_matrix* afull,
/* Real */ ae_matrix* al,
/* Real */ ae_matrix* au,
ae_int_t n,
ae_bool distvals,
double threshold,
ae_bool* serrors,
ae_int_t* failc,
ae_int_t* runs,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector lambdav;
ae_vector lambdaref;
ae_matrix z;
ae_matrix zref;
ae_matrix a1;
ae_matrix a2;
ae_matrix ar;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t m;
ae_int_t i1;
ae_int_t i2;
double v;
double a;
double b;
ae_frame_make(_state, &_frame_block);
memset(&lambdav, 0, sizeof(lambdav));
memset(&lambdaref, 0, sizeof(lambdaref));
memset(&z, 0, sizeof(z));
memset(&zref, 0, sizeof(zref));
memset(&a1, 0, sizeof(a1));
memset(&a2, 0, sizeof(a2));
memset(&ar, 0, sizeof(ar));
ae_vector_init(&lambdav, 0, DT_REAL, _state, ae_true);
ae_vector_init(&lambdaref, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&zref, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ar, 0, 0, DT_REAL, _state, ae_true);
ae_vector_set_length(&lambdaref, n-1+1, _state);
ae_matrix_set_length(&zref, n-1+1, n-1+1, _state);
ae_matrix_set_length(&a1, n-1+1, n-1+1, _state);
ae_matrix_set_length(&a2, n-1+1, n-1+1, _state);
/*
* Reference EVD
*/
*runs = *runs+1;
if( !smatrixevd(afull, n, 1, ae_true, &lambdaref, &zref, _state) )
{
*failc = *failc+1;
ae_frame_leave(_state);
return;
}
/*
* Select random interval boundaries.
* If there are non-distinct eigenvalues at the boundaries,
* we move indexes further until values splits. It is done to
* avoid situations where we can't get definite answer.
*/
i1 = ae_randominteger(n, _state);
i2 = i1+ae_randominteger(n-i1, _state);
while(i1>0)
{
if( ae_fp_greater(ae_fabs(lambdaref.ptr.p_double[i1-1]-lambdaref.ptr.p_double[i1], _state),10*threshold) )
{
break;
}
i1 = i1-1;
}
while(i20 )
{
a = 0.5*(lambdaref.ptr.p_double[i1]+lambdaref.ptr.p_double[i1-1]);
}
else
{
a = lambdaref.ptr.p_double[0]-1;
}
if( i20)
{
if( ae_fp_greater(ae_fabs(lambdaref.ptr.p_double[i1-1]-lambdaref.ptr.p_double[i1], _state),10*threshold) )
{
break;
}
i1 = i1-1;
}
while(i20 )
{
a = 0.5*(lambdaref.ptr.p_double[i1]+lambdaref.ptr.p_double[i1-1]);
}
else
{
a = lambdaref.ptr.p_double[0]-1;
}
if( i21 )
{
ae_vector_set_length(&ee, n-2+1, _state);
}
/*
* Test simple EVD: values and full vectors
*/
for(i=0; i<=n-1; i++)
{
lambdav.ptr.p_double[i] = d->ptr.p_double[i];
}
for(i=0; i<=n-2; i++)
{
ee.ptr.p_double[i] = e->ptr.p_double[i];
}
testevdunit_unset2d(&z, _state);
wsucc = smatrixtdevd(&lambdav, &ee, n, 2, &z, _state);
if( !wsucc )
{
ae_set_error_flag(tderrors, ae_true, __FILE__, __LINE__, "testevdunit.ap:1113");
ae_frame_leave(_state);
return;
}
ae_set_error_flag(tderrors, ae_fp_greater(testevdunit_tdtestproduct(d, e, n, &z, &lambdav, _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1116");
ae_set_error_flag(tderrors, ae_fp_greater(testevdunit_testort(&z, n, _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1117");
for(i=0; i<=n-2; i++)
{
if( ae_fp_less(lambdav.ptr.p_double[i+1],lambdav.ptr.p_double[i]) )
{
ae_set_error_flag(tderrors, ae_true, __FILE__, __LINE__, "testevdunit.ap:1121");
ae_frame_leave(_state);
return;
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
zref.ptr.pp_double[i][j] = z.ptr.pp_double[i][j];
}
}
/*
* Test values only variant
*/
for(i=0; i<=n-1; i++)
{
lambda2.ptr.p_double[i] = d->ptr.p_double[i];
}
for(i=0; i<=n-2; i++)
{
ee.ptr.p_double[i] = e->ptr.p_double[i];
}
testevdunit_unset2d(&z, _state);
wsucc = smatrixtdevd(&lambda2, &ee, n, 0, &z, _state);
if( !wsucc )
{
ae_set_error_flag(tderrors, ae_true, __FILE__, __LINE__, "testevdunit.ap:1139");
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(tderrors, ae_fp_greater(ae_fabs(lambda2.ptr.p_double[i]-lambdav.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1143");
}
/*
* Test multiplication variant
*/
for(i=0; i<=n-1; i++)
{
lambda2.ptr.p_double[i] = d->ptr.p_double[i];
}
for(i=0; i<=n-2; i++)
{
ee.ptr.p_double[i] = e->ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a1.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
a2.ptr.pp_double[i][j] = a1.ptr.pp_double[i][j];
}
}
wsucc = smatrixtdevd(&lambda2, &ee, n, 1, &a1, _state);
if( !wsucc )
{
ae_set_error_flag(tderrors, ae_true, __FILE__, __LINE__, "testevdunit.ap:1161");
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(tderrors, ae_fp_greater(ae_fabs(lambda2.ptr.p_double[i]-lambdav.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1165");
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&a2.ptr.pp_double[i][0], 1, &zref.ptr.pp_double[0][j], zref.stride, ae_v_len(0,n-1));
/*
* next line is a bit complicated because
* depending on algorithm used we can get either
* z or -z as eigenvector. so we compare result
* with both A*ZRef and -A*ZRef
*/
ae_set_error_flag(tderrors, ae_fp_greater(ae_fabs(v-a1.ptr.pp_double[i][j], _state),threshold)&&ae_fp_greater(ae_fabs(v+a1.ptr.pp_double[i][j], _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1177");
}
}
/*
* Test first row variant.
*
* NOTE: this test is special because ZNeeded=3 is ALGLIB-specific feature
* which is NOT supported by Intel MKL. Thus, MKL-capable version of
* ALGLIB will use different algorithms for ZNeeded=3 and for ZNeeded<3.
*
* In most cases it is OK, but when problem happened to be degenerate
* (two close eigenvalues), Z computed by ALGLIB may be different from
* Z computed by MKL (up to arbitrary rotation), which will lead to
* failure of the test, because ZNeeded=2 is used as reference value
* for ZNeeded=3.
*
* That's why this test is performed only for well-separated matrices,
* and with custom threshold.
*/
requiredseparation = 1.0E-6;
specialthreshold = 1.0E-6;
worstseparation = ae_maxrealnumber;
for(i=0; i<=n-2; i++)
{
worstseparation = ae_minreal(worstseparation, ae_fabs(lambdav.ptr.p_double[i+1]-lambdav.ptr.p_double[i], _state), _state);
}
if( ae_fp_greater(worstseparation,requiredseparation) )
{
for(i=0; i<=n-1; i++)
{
lambda2.ptr.p_double[i] = d->ptr.p_double[i];
}
for(i=0; i<=n-2; i++)
{
ee.ptr.p_double[i] = e->ptr.p_double[i];
}
testevdunit_unset2d(&z, _state);
wsucc = smatrixtdevd(&lambda2, &ee, n, 3, &z, _state);
if( !wsucc )
{
ae_set_error_flag(tderrors, ae_true, __FILE__, __LINE__, "testevdunit.ap:1211");
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(tderrors, ae_fp_greater(ae_fabs(lambda2.ptr.p_double[i]-lambdav.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1216");
/*
* next line is a bit complicated because
* depending on algorithm used we can get either
* z or -z as eigenvector. so we compare result
* with both z and -z
*/
ae_set_error_flag(tderrors, ae_fp_greater(ae_fabs(z.ptr.pp_double[0][i]-zref.ptr.pp_double[0][i], _state),specialthreshold)&&ae_fp_greater(ae_fabs(z.ptr.pp_double[0][i]+zref.ptr.pp_double[0][i], _state),specialthreshold), __FILE__, __LINE__, "testevdunit.ap:1224");
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Tests EVD problem
DistVals - is True, when eigenvalues are distinct. Is False, when we
are solving sparse task with lots of zero eigenvalues.
In such cases some tests related to the eigenvectors are
not performed.
*************************************************************************/
static void testevdunit_testtdevdbiproblem(/* Real */ ae_vector* d,
/* Real */ ae_vector* e,
ae_int_t n,
ae_bool distvals,
double threshold,
ae_bool* serrors,
ae_int_t* failc,
ae_int_t* runs,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector lambdav;
ae_vector lambdaref;
ae_matrix z;
ae_matrix zref;
ae_matrix a1;
ae_matrix a2;
ae_matrix ar;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t m;
ae_int_t i1;
ae_int_t i2;
double v;
double a;
double b;
ae_frame_make(_state, &_frame_block);
memset(&lambdav, 0, sizeof(lambdav));
memset(&lambdaref, 0, sizeof(lambdaref));
memset(&z, 0, sizeof(z));
memset(&zref, 0, sizeof(zref));
memset(&a1, 0, sizeof(a1));
memset(&a2, 0, sizeof(a2));
memset(&ar, 0, sizeof(ar));
ae_vector_init(&lambdav, 0, DT_REAL, _state, ae_true);
ae_vector_init(&lambdaref, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&zref, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a1, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ar, 0, 0, DT_REAL, _state, ae_true);
ae_vector_set_length(&lambdaref, n-1+1, _state);
ae_matrix_set_length(&zref, n-1+1, n-1+1, _state);
ae_matrix_set_length(&a1, n-1+1, n-1+1, _state);
ae_matrix_set_length(&a2, n-1+1, n-1+1, _state);
/*
* Reference EVD
*/
ae_vector_set_length(&lambdaref, n, _state);
ae_v_move(&lambdaref.ptr.p_double[0], 1, &d->ptr.p_double[0], 1, ae_v_len(0,n-1));
*runs = *runs+1;
if( !smatrixtdevd(&lambdaref, e, n, 2, &zref, _state) )
{
*failc = *failc+1;
ae_frame_leave(_state);
return;
}
/*
* Select random interval boundaries.
* If there are non-distinct eigenvalues at the boundaries,
* we move indexes further until values splits. It is done to
* avoid situations where we can't get definite answer.
*/
i1 = ae_randominteger(n, _state);
i2 = i1+ae_randominteger(n-i1, _state);
while(i1>0)
{
if( ae_fp_greater(ae_fabs(lambdaref.ptr.p_double[i1-1]-lambdaref.ptr.p_double[i1], _state),10*threshold) )
{
break;
}
i1 = i1-1;
}
while(i20 )
{
a = 0.5*(lambdaref.ptr.p_double[i1]+lambdaref.ptr.p_double[i1-1]);
}
else
{
a = lambdaref.ptr.p_double[0]-1;
}
if( i2ptr.p_double[i];
}
*runs = *runs+1;
if( !smatrixtdevdr(&lambdav, e, n, 0, a, b, &m, &z, _state) )
{
*failc = *failc+1;
ae_frame_leave(_state);
return;
}
if( m!=i2-i1+1 )
{
*failc = *failc+1;
ae_frame_leave(_state);
return;
}
for(k=0; k<=m-1; k++)
{
*serrors = *serrors||ae_fp_greater(ae_fabs(lambdav.ptr.p_double[k]-lambdaref.ptr.p_double[i1+k], _state),threshold);
}
/*
* Test indexes, no vectors
*/
ae_vector_set_length(&lambdav, n-1+1, _state);
for(i=0; i<=n-1; i++)
{
lambdav.ptr.p_double[i] = d->ptr.p_double[i];
}
*runs = *runs+1;
if( !smatrixtdevdi(&lambdav, e, n, 0, i1, i2, &z, _state) )
{
*failc = *failc+1;
ae_frame_leave(_state);
return;
}
m = i2-i1+1;
for(k=0; k<=m-1; k++)
{
*serrors = *serrors||ae_fp_greater(ae_fabs(lambdav.ptr.p_double[k]-lambdaref.ptr.p_double[i1+k], _state),threshold);
}
/*
* Test interval, transform vectors
*/
ae_vector_set_length(&lambdav, n-1+1, _state);
for(i=0; i<=n-1; i++)
{
lambdav.ptr.p_double[i] = d->ptr.p_double[i];
}
ae_matrix_set_length(&a1, n-1+1, n-1+1, _state);
ae_matrix_set_length(&a2, n-1+1, n-1+1, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a1.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
a2.ptr.pp_double[i][j] = a1.ptr.pp_double[i][j];
}
}
*runs = *runs+1;
if( !smatrixtdevdr(&lambdav, e, n, 1, a, b, &m, &a1, _state) )
{
*failc = *failc+1;
ae_frame_leave(_state);
return;
}
if( m!=i2-i1+1 )
{
*failc = *failc+1;
ae_frame_leave(_state);
return;
}
for(k=0; k<=m-1; k++)
{
*serrors = *serrors||ae_fp_greater(ae_fabs(lambdav.ptr.p_double[k]-lambdaref.ptr.p_double[i1+k], _state),threshold);
}
if( distvals )
{
ae_matrix_set_length(&ar, n-1+1, m-1+1, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
v = ae_v_dotproduct(&a2.ptr.pp_double[i][0], 1, &zref.ptr.pp_double[0][i1+j], zref.stride, ae_v_len(0,n-1));
ar.ptr.pp_double[i][j] = v;
}
}
for(j=0; j<=m-1; j++)
{
v = ae_v_dotproduct(&a1.ptr.pp_double[0][j], a1.stride, &ar.ptr.pp_double[0][j], ar.stride, ae_v_len(0,n-1));
if( ae_fp_less(v,(double)(0)) )
{
ae_v_muld(&ar.ptr.pp_double[0][j], ar.stride, ae_v_len(0,n-1), -1);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
*serrors = *serrors||ae_fp_greater(ae_fabs(a1.ptr.pp_double[i][j]-ar.ptr.pp_double[i][j], _state),threshold);
}
}
}
/*
* Test indexes, transform vectors
*/
ae_vector_set_length(&lambdav, n-1+1, _state);
for(i=0; i<=n-1; i++)
{
lambdav.ptr.p_double[i] = d->ptr.p_double[i];
}
ae_matrix_set_length(&a1, n-1+1, n-1+1, _state);
ae_matrix_set_length(&a2, n-1+1, n-1+1, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a1.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
a2.ptr.pp_double[i][j] = a1.ptr.pp_double[i][j];
}
}
*runs = *runs+1;
if( !smatrixtdevdi(&lambdav, e, n, 1, i1, i2, &a1, _state) )
{
*failc = *failc+1;
ae_frame_leave(_state);
return;
}
m = i2-i1+1;
for(k=0; k<=m-1; k++)
{
*serrors = *serrors||ae_fp_greater(ae_fabs(lambdav.ptr.p_double[k]-lambdaref.ptr.p_double[i1+k], _state),threshold);
}
if( distvals )
{
ae_matrix_set_length(&ar, n-1+1, m-1+1, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
v = ae_v_dotproduct(&a2.ptr.pp_double[i][0], 1, &zref.ptr.pp_double[0][i1+j], zref.stride, ae_v_len(0,n-1));
ar.ptr.pp_double[i][j] = v;
}
}
for(j=0; j<=m-1; j++)
{
v = ae_v_dotproduct(&a1.ptr.pp_double[0][j], a1.stride, &ar.ptr.pp_double[0][j], ar.stride, ae_v_len(0,n-1));
if( ae_fp_less(v,(double)(0)) )
{
ae_v_muld(&ar.ptr.pp_double[0][j], ar.stride, ae_v_len(0,n-1), -1);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
*serrors = *serrors||ae_fp_greater(ae_fabs(a1.ptr.pp_double[i][j]-ar.ptr.pp_double[i][j], _state),threshold);
}
}
}
/*
* Test interval, do not transform vectors
*/
ae_vector_set_length(&lambdav, n-1+1, _state);
for(i=0; i<=n-1; i++)
{
lambdav.ptr.p_double[i] = d->ptr.p_double[i];
}
ae_matrix_set_length(&z, 0+1, 0+1, _state);
*runs = *runs+1;
if( !smatrixtdevdr(&lambdav, e, n, 2, a, b, &m, &z, _state) )
{
*failc = *failc+1;
ae_frame_leave(_state);
return;
}
if( m!=i2-i1+1 )
{
*failc = *failc+1;
ae_frame_leave(_state);
return;
}
for(k=0; k<=m-1; k++)
{
*serrors = *serrors||ae_fp_greater(ae_fabs(lambdav.ptr.p_double[k]-lambdaref.ptr.p_double[i1+k], _state),threshold);
}
if( distvals )
{
for(j=0; j<=m-1; j++)
{
v = ae_v_dotproduct(&z.ptr.pp_double[0][j], z.stride, &zref.ptr.pp_double[0][i1+j], zref.stride, ae_v_len(0,n-1));
if( ae_fp_less(v,(double)(0)) )
{
ae_v_muld(&z.ptr.pp_double[0][j], z.stride, ae_v_len(0,n-1), -1);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
*serrors = *serrors||ae_fp_greater(ae_fabs(z.ptr.pp_double[i][j]-zref.ptr.pp_double[i][i1+j], _state),threshold);
}
}
}
/*
* Test indexes, do not transform vectors
*/
ae_vector_set_length(&lambdav, n-1+1, _state);
for(i=0; i<=n-1; i++)
{
lambdav.ptr.p_double[i] = d->ptr.p_double[i];
}
ae_matrix_set_length(&z, 0+1, 0+1, _state);
*runs = *runs+1;
if( !smatrixtdevdi(&lambdav, e, n, 2, i1, i2, &z, _state) )
{
*failc = *failc+1;
ae_frame_leave(_state);
return;
}
m = i2-i1+1;
for(k=0; k<=m-1; k++)
{
*serrors = *serrors||ae_fp_greater(ae_fabs(lambdav.ptr.p_double[k]-lambdaref.ptr.p_double[i1+k], _state),threshold);
}
if( distvals )
{
for(j=0; j<=m-1; j++)
{
v = ae_v_dotproduct(&z.ptr.pp_double[0][j], z.stride, &zref.ptr.pp_double[0][i1+j], zref.stride, ae_v_len(0,n-1));
if( ae_fp_less(v,(double)(0)) )
{
ae_v_muld(&z.ptr.pp_double[0][j], z.stride, ae_v_len(0,n-1), -1);
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
*serrors = *serrors||ae_fp_greater(ae_fabs(z.ptr.pp_double[i][j]-zref.ptr.pp_double[i][i1+j], _state),threshold);
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Non-symmetric problem
*************************************************************************/
static void testevdunit_testnsevdproblem(/* Real */ ae_matrix* a,
ae_int_t n,
double threshold,
ae_bool* nserrors,
ae_state *_state)
{
ae_frame _frame_block;
double mx;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t vjob;
ae_bool needl;
ae_bool needr;
ae_vector wr0;
ae_vector wi0;
ae_vector wr1;
ae_vector wi1;
ae_vector wr0s;
ae_vector wi0s;
ae_vector wr1s;
ae_vector wi1s;
ae_matrix vl;
ae_matrix vr;
ae_vector vec1r;
ae_vector vec1i;
ae_vector vec2r;
ae_vector vec2i;
ae_vector vec3r;
ae_vector vec3i;
double curwr;
double curwi;
double vt;
double tmp;
double vnorm;
ae_frame_make(_state, &_frame_block);
memset(&wr0, 0, sizeof(wr0));
memset(&wi0, 0, sizeof(wi0));
memset(&wr1, 0, sizeof(wr1));
memset(&wi1, 0, sizeof(wi1));
memset(&wr0s, 0, sizeof(wr0s));
memset(&wi0s, 0, sizeof(wi0s));
memset(&wr1s, 0, sizeof(wr1s));
memset(&wi1s, 0, sizeof(wi1s));
memset(&vl, 0, sizeof(vl));
memset(&vr, 0, sizeof(vr));
memset(&vec1r, 0, sizeof(vec1r));
memset(&vec1i, 0, sizeof(vec1i));
memset(&vec2r, 0, sizeof(vec2r));
memset(&vec2i, 0, sizeof(vec2i));
memset(&vec3r, 0, sizeof(vec3r));
memset(&vec3i, 0, sizeof(vec3i));
ae_vector_init(&wr0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&wi0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&wr1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&wi1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&wr0s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&wi0s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&wr1s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&wi1s, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&vl, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&vr, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&vec1r, 0, DT_REAL, _state, ae_true);
ae_vector_init(&vec1i, 0, DT_REAL, _state, ae_true);
ae_vector_init(&vec2r, 0, DT_REAL, _state, ae_true);
ae_vector_init(&vec2i, 0, DT_REAL, _state, ae_true);
ae_vector_init(&vec3r, 0, DT_REAL, _state, ae_true);
ae_vector_init(&vec3i, 0, DT_REAL, _state, ae_true);
ae_vector_set_length(&vec1r, n-1+1, _state);
ae_vector_set_length(&vec2r, n-1+1, _state);
ae_vector_set_length(&vec3r, n-1+1, _state);
ae_vector_set_length(&vec1i, n-1+1, _state);
ae_vector_set_length(&vec2i, n-1+1, _state);
ae_vector_set_length(&vec3i, n-1+1, _state);
ae_vector_set_length(&wr0s, n-1+1, _state);
ae_vector_set_length(&wr1s, n-1+1, _state);
ae_vector_set_length(&wi0s, n-1+1, _state);
ae_vector_set_length(&wi1s, n-1+1, _state);
mx = (double)(0);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_greater(ae_fabs(a->ptr.pp_double[i][j], _state),mx) )
{
mx = ae_fabs(a->ptr.pp_double[i][j], _state);
}
}
}
if( ae_fp_eq(mx,(double)(0)) )
{
mx = (double)(1);
}
/*
* Load values-only
*/
if( !rmatrixevd(a, n, 0, &wr0, &wi0, &vl, &vr, _state) )
{
ae_set_error_flag(nserrors, ae_true, __FILE__, __LINE__, "testevdunit.ap:1554");
ae_frame_leave(_state);
return;
}
/*
* Test different jobs
*/
for(vjob=1; vjob<=3; vjob++)
{
needr = vjob==1||vjob==3;
needl = vjob==2||vjob==3;
if( !rmatrixevd(a, n, vjob, &wr1, &wi1, &vl, &vr, _state) )
{
ae_set_error_flag(nserrors, ae_true, __FILE__, __LINE__, "testevdunit.ap:1567");
ae_frame_leave(_state);
return;
}
/*
* Test values:
* 1. sort by real part
* 2. test
*/
ae_v_move(&wr0s.ptr.p_double[0], 1, &wr0.ptr.p_double[0], 1, ae_v_len(0,n-1));
ae_v_move(&wi0s.ptr.p_double[0], 1, &wi0.ptr.p_double[0], 1, ae_v_len(0,n-1));
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-2-i; j++)
{
if( ae_fp_greater(wr0s.ptr.p_double[j],wr0s.ptr.p_double[j+1]) )
{
tmp = wr0s.ptr.p_double[j];
wr0s.ptr.p_double[j] = wr0s.ptr.p_double[j+1];
wr0s.ptr.p_double[j+1] = tmp;
tmp = wi0s.ptr.p_double[j];
wi0s.ptr.p_double[j] = wi0s.ptr.p_double[j+1];
wi0s.ptr.p_double[j+1] = tmp;
}
}
}
ae_v_move(&wr1s.ptr.p_double[0], 1, &wr1.ptr.p_double[0], 1, ae_v_len(0,n-1));
ae_v_move(&wi1s.ptr.p_double[0], 1, &wi1.ptr.p_double[0], 1, ae_v_len(0,n-1));
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-2-i; j++)
{
if( ae_fp_greater(wr1s.ptr.p_double[j],wr1s.ptr.p_double[j+1]) )
{
tmp = wr1s.ptr.p_double[j];
wr1s.ptr.p_double[j] = wr1s.ptr.p_double[j+1];
wr1s.ptr.p_double[j+1] = tmp;
tmp = wi1s.ptr.p_double[j];
wi1s.ptr.p_double[j] = wi1s.ptr.p_double[j+1];
wi1s.ptr.p_double[j+1] = tmp;
}
}
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(nserrors, ae_fp_greater(ae_fabs(wr0s.ptr.p_double[i]-wr1s.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1604");
ae_set_error_flag(nserrors, ae_fp_greater(ae_fabs(wi0s.ptr.p_double[i]-wi1s.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1605");
}
/*
* Test right vectors
*/
if( needr )
{
k = 0;
while(k<=n-1)
{
curwr = (double)(0);
curwi = (double)(0);
if( ae_fp_eq(wi1.ptr.p_double[k],(double)(0)) )
{
ae_v_move(&vec1r.ptr.p_double[0], 1, &vr.ptr.pp_double[0][k], vr.stride, ae_v_len(0,n-1));
for(i=0; i<=n-1; i++)
{
vec1i.ptr.p_double[i] = (double)(0);
}
curwr = wr1.ptr.p_double[k];
curwi = (double)(0);
}
if( ae_fp_greater(wi1.ptr.p_double[k],(double)(0)) )
{
ae_v_move(&vec1r.ptr.p_double[0], 1, &vr.ptr.pp_double[0][k], vr.stride, ae_v_len(0,n-1));
ae_v_move(&vec1i.ptr.p_double[0], 1, &vr.ptr.pp_double[0][k+1], vr.stride, ae_v_len(0,n-1));
curwr = wr1.ptr.p_double[k];
curwi = wi1.ptr.p_double[k];
}
if( ae_fp_less(wi1.ptr.p_double[k],(double)(0)) )
{
ae_v_move(&vec1r.ptr.p_double[0], 1, &vr.ptr.pp_double[0][k-1], vr.stride, ae_v_len(0,n-1));
ae_v_moveneg(&vec1i.ptr.p_double[0], 1, &vr.ptr.pp_double[0][k], vr.stride, ae_v_len(0,n-1));
curwr = wr1.ptr.p_double[k];
curwi = wi1.ptr.p_double[k];
}
vnorm = 0.0;
for(i=0; i<=n-1; i++)
{
vt = ae_v_dotproduct(&a->ptr.pp_double[i][0], 1, &vec1r.ptr.p_double[0], 1, ae_v_len(0,n-1));
vec2r.ptr.p_double[i] = vt;
vt = ae_v_dotproduct(&a->ptr.pp_double[i][0], 1, &vec1i.ptr.p_double[0], 1, ae_v_len(0,n-1));
vec2i.ptr.p_double[i] = vt;
vnorm = vnorm+ae_sqr(vec1r.ptr.p_double[i], _state)+ae_sqr(vec1i.ptr.p_double[i], _state);
}
vnorm = ae_sqrt(vnorm, _state);
ae_v_moved(&vec3r.ptr.p_double[0], 1, &vec1r.ptr.p_double[0], 1, ae_v_len(0,n-1), curwr);
ae_v_subd(&vec3r.ptr.p_double[0], 1, &vec1i.ptr.p_double[0], 1, ae_v_len(0,n-1), curwi);
ae_v_moved(&vec3i.ptr.p_double[0], 1, &vec1r.ptr.p_double[0], 1, ae_v_len(0,n-1), curwi);
ae_v_addd(&vec3i.ptr.p_double[0], 1, &vec1i.ptr.p_double[0], 1, ae_v_len(0,n-1), curwr);
ae_set_error_flag(nserrors, ae_fp_less(vnorm,1.0E-3)||!ae_isfinite(vnorm, _state), __FILE__, __LINE__, "testevdunit.ap:1654");
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(nserrors, ae_fp_greater(ae_fabs(vec2r.ptr.p_double[i]-vec3r.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1657");
ae_set_error_flag(nserrors, ae_fp_greater(ae_fabs(vec2i.ptr.p_double[i]-vec3i.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1658");
}
k = k+1;
}
}
/*
* Test left vectors
*/
curwr = (double)(0);
curwi = (double)(0);
if( needl )
{
k = 0;
while(k<=n-1)
{
if( ae_fp_eq(wi1.ptr.p_double[k],(double)(0)) )
{
ae_v_move(&vec1r.ptr.p_double[0], 1, &vl.ptr.pp_double[0][k], vl.stride, ae_v_len(0,n-1));
for(i=0; i<=n-1; i++)
{
vec1i.ptr.p_double[i] = (double)(0);
}
curwr = wr1.ptr.p_double[k];
curwi = (double)(0);
}
if( ae_fp_greater(wi1.ptr.p_double[k],(double)(0)) )
{
ae_v_move(&vec1r.ptr.p_double[0], 1, &vl.ptr.pp_double[0][k], vl.stride, ae_v_len(0,n-1));
ae_v_move(&vec1i.ptr.p_double[0], 1, &vl.ptr.pp_double[0][k+1], vl.stride, ae_v_len(0,n-1));
curwr = wr1.ptr.p_double[k];
curwi = wi1.ptr.p_double[k];
}
if( ae_fp_less(wi1.ptr.p_double[k],(double)(0)) )
{
ae_v_move(&vec1r.ptr.p_double[0], 1, &vl.ptr.pp_double[0][k-1], vl.stride, ae_v_len(0,n-1));
ae_v_moveneg(&vec1i.ptr.p_double[0], 1, &vl.ptr.pp_double[0][k], vl.stride, ae_v_len(0,n-1));
curwr = wr1.ptr.p_double[k];
curwi = wi1.ptr.p_double[k];
}
vnorm = 0.0;
for(j=0; j<=n-1; j++)
{
vt = ae_v_dotproduct(&vec1r.ptr.p_double[0], 1, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,n-1));
vec2r.ptr.p_double[j] = vt;
vt = ae_v_dotproduct(&vec1i.ptr.p_double[0], 1, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,n-1));
vec2i.ptr.p_double[j] = -vt;
vnorm = vnorm+ae_sqr(vec1r.ptr.p_double[j], _state)+ae_sqr(vec1i.ptr.p_double[j], _state);
}
vnorm = ae_sqrt(vnorm, _state);
ae_v_moved(&vec3r.ptr.p_double[0], 1, &vec1r.ptr.p_double[0], 1, ae_v_len(0,n-1), curwr);
ae_v_addd(&vec3r.ptr.p_double[0], 1, &vec1i.ptr.p_double[0], 1, ae_v_len(0,n-1), curwi);
ae_v_moved(&vec3i.ptr.p_double[0], 1, &vec1r.ptr.p_double[0], 1, ae_v_len(0,n-1), curwi);
ae_v_addd(&vec3i.ptr.p_double[0], 1, &vec1i.ptr.p_double[0], 1, ae_v_len(0,n-1), -curwr);
ae_set_error_flag(nserrors, ae_fp_less(vnorm,1.0E-3)||!ae_isfinite(vnorm, _state), __FILE__, __LINE__, "testevdunit.ap:1710");
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(nserrors, ae_fp_greater(ae_fabs(vec2r.ptr.p_double[i]-vec3r.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1713");
ae_set_error_flag(nserrors, ae_fp_greater(ae_fabs(vec2i.ptr.p_double[i]-vec3i.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testevdunit.ap:1714");
}
k = k+1;
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Testing EVD subroutines for one N
NOTES:
* BIThreshold is a threshold for bisection-and-inverse-iteration subroutines.
special threshold is needed because these subroutines may have much more
larger error than QR-based algorithms.
*************************************************************************/
static void testevdunit_testevdset(ae_int_t n,
double threshold,
double bithreshold,
ae_int_t* failc,
ae_int_t* runs,
ae_bool* nserrors,
ae_bool* serrors,
ae_bool* herrors,
ae_bool* tderrors,
ae_bool* sbierrors,
ae_bool* hbierrors,
ae_bool* tdbierrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix ra;
ae_matrix ral;
ae_matrix rau;
ae_matrix ca;
ae_matrix cal;
ae_matrix cau;
ae_vector d;
ae_vector e;
ae_int_t i;
ae_int_t j;
ae_int_t mkind;
ae_frame_make(_state, &_frame_block);
memset(&ra, 0, sizeof(ra));
memset(&ral, 0, sizeof(ral));
memset(&rau, 0, sizeof(rau));
memset(&ca, 0, sizeof(ca));
memset(&cal, 0, sizeof(cal));
memset(&cau, 0, sizeof(cau));
memset(&d, 0, sizeof(d));
memset(&e, 0, sizeof(e));
ae_matrix_init(&ra, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ral, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&rau, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ca, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&cal, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&cau, 0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&e, 0, DT_REAL, _state, ae_true);
/*
* Test symmetric problems
*/
ae_matrix_set_length(&ra, n, n, _state);
ae_matrix_set_length(&ral, n, n, _state);
ae_matrix_set_length(&rau, n, n, _state);
ae_matrix_set_length(&ca, n, n, _state);
ae_matrix_set_length(&cal, n, n, _state);
ae_matrix_set_length(&cau, n, n, _state);
/*
* Zero matrices
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
ra.ptr.pp_double[i][j] = (double)(0);
ca.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
testevdunit_rmatrixsymmetricsplit(&ra, n, &ral, &rau, _state);
testevdunit_cmatrixhermitiansplit(&ca, n, &cal, &cau, _state);
testevdunit_testsevdproblem(&ra, &ral, &rau, n, threshold, serrors, failc, runs, _state);
testevdunit_testhevdproblem(&ca, &cal, &cau, n, threshold, herrors, failc, runs, _state);
testevdunit_testsevdbiproblem(&ra, &ral, &rau, n, ae_false, bithreshold, sbierrors, failc, runs, _state);
testevdunit_testhevdbiproblem(&ca, &cal, &cau, n, ae_false, bithreshold, hbierrors, failc, runs, _state);
/*
* Random matrix
*/
for(i=0; i<=n-1; i++)
{
for(j=i+1; j<=n-1; j++)
{
ra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
ca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
ca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
ra.ptr.pp_double[j][i] = ra.ptr.pp_double[i][j];
ca.ptr.pp_complex[j][i] = ae_c_conj(ca.ptr.pp_complex[i][j], _state);
}
ra.ptr.pp_double[i][i] = 2*ae_randomreal(_state)-1;
ca.ptr.pp_complex[i][i] = ae_complex_from_d(2*ae_randomreal(_state)-1);
}
testevdunit_rmatrixsymmetricsplit(&ra, n, &ral, &rau, _state);
testevdunit_cmatrixhermitiansplit(&ca, n, &cal, &cau, _state);
testevdunit_testsevdproblem(&ra, &ral, &rau, n, threshold, serrors, failc, runs, _state);
testevdunit_testhevdproblem(&ca, &cal, &cau, n, threshold, herrors, failc, runs, _state);
/*
* Random diagonally dominant matrix with distinct eigenvalues
*/
for(i=0; i<=n-1; i++)
{
for(j=i+1; j<=n-1; j++)
{
ra.ptr.pp_double[i][j] = 0.1*(2*ae_randomreal(_state)-1)/n;
ca.ptr.pp_complex[i][j].x = 0.1*(2*ae_randomreal(_state)-1)/n;
ca.ptr.pp_complex[i][j].y = 0.1*(2*ae_randomreal(_state)-1)/n;
ra.ptr.pp_double[j][i] = ra.ptr.pp_double[i][j];
ca.ptr.pp_complex[j][i] = ae_c_conj(ca.ptr.pp_complex[i][j], _state);
}
ra.ptr.pp_double[i][i] = 0.1*(2*ae_randomreal(_state)-1)+i;
ca.ptr.pp_complex[i][i] = ae_complex_from_d(0.1*(2*ae_randomreal(_state)-1)+i);
}
testevdunit_rmatrixsymmetricsplit(&ra, n, &ral, &rau, _state);
testevdunit_cmatrixhermitiansplit(&ca, n, &cal, &cau, _state);
testevdunit_testsevdproblem(&ra, &ral, &rau, n, threshold, serrors, failc, runs, _state);
testevdunit_testhevdproblem(&ca, &cal, &cau, n, threshold, herrors, failc, runs, _state);
testevdunit_testsevdbiproblem(&ra, &ral, &rau, n, ae_true, bithreshold, sbierrors, failc, runs, _state);
testevdunit_testhevdbiproblem(&ca, &cal, &cau, n, ae_true, bithreshold, hbierrors, failc, runs, _state);
/*
* Sparse matrices
*/
testevdunit_rmatrixfillsparsea(&ra, n, n, 0.995, (double)(0), _state);
testevdunit_cmatrixfillsparsea(&ca, n, n, 0.995, (double)(0), _state);
for(i=0; i<=n-1; i++)
{
for(j=i+1; j<=n-1; j++)
{
ra.ptr.pp_double[j][i] = ra.ptr.pp_double[i][j];
ca.ptr.pp_complex[j][i] = ae_c_conj(ca.ptr.pp_complex[i][j], _state);
}
ca.ptr.pp_complex[i][i].y = (double)(0);
}
testevdunit_rmatrixsymmetricsplit(&ra, n, &ral, &rau, _state);
testevdunit_cmatrixhermitiansplit(&ca, n, &cal, &cau, _state);
testevdunit_testsevdproblem(&ra, &ral, &rau, n, threshold, serrors, failc, runs, _state);
testevdunit_testhevdproblem(&ca, &cal, &cau, n, threshold, herrors, failc, runs, _state);
testevdunit_testsevdbiproblem(&ra, &ral, &rau, n, ae_false, bithreshold, sbierrors, failc, runs, _state);
testevdunit_testhevdbiproblem(&ca, &cal, &cau, n, ae_false, bithreshold, hbierrors, failc, runs, _state);
/*
* testing tridiagonal problems
*/
for(mkind=0; mkind<=7; mkind++)
{
ae_vector_set_length(&d, n, _state);
if( n>1 )
{
ae_vector_set_length(&e, n-1, _state);
}
if( mkind==0 )
{
/*
* Zero matrix
*/
for(i=0; i<=n-1; i++)
{
d.ptr.p_double[i] = (double)(0);
}
for(i=0; i<=n-2; i++)
{
e.ptr.p_double[i] = (double)(0);
}
}
if( mkind==1 )
{
/*
* Diagonal matrix
*/
for(i=0; i<=n-1; i++)
{
d.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=n-2; i++)
{
e.ptr.p_double[i] = (double)(0);
}
}
if( mkind==2 )
{
/*
* Off-diagonal matrix
*/
for(i=0; i<=n-1; i++)
{
d.ptr.p_double[i] = (double)(0);
}
for(i=0; i<=n-2; i++)
{
e.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
}
if( mkind==3 )
{
/*
* Dense matrix with blocks
*/
for(i=0; i<=n-1; i++)
{
d.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=n-2; i++)
{
e.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
j = 1;
i = 2;
while(j<=n-2)
{
e.ptr.p_double[j] = (double)(0);
j = j+i;
i = i+1;
}
}
if( mkind==4 )
{
/*
* dense matrix
*/
for(i=0; i<=n-1; i++)
{
d.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=n-2; i++)
{
e.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
}
if( mkind==5 )
{
/*
* Diagonal matrix with distinct eigenvalues
*/
for(i=0; i<=n-1; i++)
{
d.ptr.p_double[i] = 0.1*(2*ae_randomreal(_state)-1)+i;
}
for(i=0; i<=n-2; i++)
{
e.ptr.p_double[i] = (double)(0);
}
}
if( mkind==6 )
{
/*
* Off-diagonal matrix with distinct eigenvalues
*/
for(i=0; i<=n-1; i++)
{
d.ptr.p_double[i] = (double)(0);
}
for(i=0; i<=n-2; i++)
{
e.ptr.p_double[i] = 0.1*(2*ae_randomreal(_state)-1)+i+1;
}
}
if( mkind==7 )
{
/*
* dense matrix with distinct eigenvalues
*/
for(i=0; i<=n-1; i++)
{
d.ptr.p_double[i] = 0.1*(2*ae_randomreal(_state)-1)+i+1;
}
for(i=0; i<=n-2; i++)
{
e.ptr.p_double[i] = 0.1*(2*ae_randomreal(_state)-1);
}
}
testevdunit_testtdevdproblem(&d, &e, n, threshold, tderrors, _state);
testevdunit_testtdevdbiproblem(&d, &e, n, (mkind==5||mkind==6)||mkind==7, bithreshold, tdbierrors, failc, runs, _state);
}
/*
* Test non-symmetric problems
*/
/*
* Test non-symmetric problems: zero, random, sparse matrices.
*/
ae_matrix_set_length(&ra, n, n, _state);
ae_matrix_set_length(&ca, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
ra.ptr.pp_double[i][j] = (double)(0);
ca.ptr.pp_complex[i][j] = ae_complex_from_i(0);
}
}
testevdunit_testnsevdproblem(&ra, n, threshold, nserrors, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
ra.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
ca.ptr.pp_complex[i][j].x = 2*ae_randomreal(_state)-1;
ca.ptr.pp_complex[i][j].y = 2*ae_randomreal(_state)-1;
}
}
testevdunit_testnsevdproblem(&ra, n, threshold, nserrors, _state);
ae_frame_leave(_state);
}
/*************************************************************************
Testing symmetric mode of subspace iteration solver.
On failure sets error flag, on success flag is not changed.
*************************************************************************/
static void testevdunit_testsisymm(ae_bool* errorflag, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t m;
ae_int_t smode;
ae_int_t i;
ae_int_t j;
ae_int_t k;
hqrndstate rs;
double sgn;
ae_vector diaga;
double decaya;
ae_bool isupper;
ae_matrix qa;
ae_matrix densea;
ae_matrix halfa;
ae_matrix ra;
ae_matrix rb;
ae_matrix tmp2;
sparsematrix halfsa;
ae_int_t sformat;
double v;
double mx;
eigsubspacestate s;
eigsubspacereport rep;
ae_vector sw;
ae_matrix sz;
ae_vector u;
double tollambda;
double tolvector;
ae_int_t itscount;
ae_int_t callcount;
ae_int_t requestsize;
ae_int_t requesttype;
ae_int_t pass;
ae_int_t cnta;
ae_int_t cntb;
ae_int_t cntc;
double nu;
double eps;
ae_frame_make(_state, &_frame_block);
memset(&rs, 0, sizeof(rs));
memset(&diaga, 0, sizeof(diaga));
memset(&qa, 0, sizeof(qa));
memset(&densea, 0, sizeof(densea));
memset(&halfa, 0, sizeof(halfa));
memset(&ra, 0, sizeof(ra));
memset(&rb, 0, sizeof(rb));
memset(&tmp2, 0, sizeof(tmp2));
memset(&halfsa, 0, sizeof(halfsa));
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&sw, 0, sizeof(sw));
memset(&sz, 0, sizeof(sz));
memset(&u, 0, sizeof(u));
_hqrndstate_init(&rs, _state, ae_true);
ae_vector_init(&diaga, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&qa, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&densea, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&halfa, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ra, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&rb, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&tmp2, 0, 0, DT_REAL, _state, ae_true);
_sparsematrix_init(&halfsa, _state, ae_true);
_eigsubspacestate_init(&s, _state, ae_true);
_eigsubspacereport_init(&rep, _state, ae_true);
ae_vector_init(&sw, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&sz, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&u, 0, DT_REAL, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Problem with weakly separated eigenvalues (but not too weak),
* either with alternating sign - or all positive. EPS-based
* stopping condition is used because we can not tell how many
* iterations is required to solve it.
*/
tollambda = 1.0E-9;
tolvector = 1.0E-4;
for(n=1; n<=25; n++)
{
for(m=1; m<=n; m++)
{
for(smode=0; smode<=2; smode++)
{
/*
* Generate eigenproblem
*/
sgn = (double)(2*hqrnduniformi(&rs, 2, _state)-1);
decaya = 1.05;
ae_vector_set_length(&diaga, n, _state);
diaga.ptr.p_double[0] = ae_pow((double)(10), 2*hqrnduniformr(&rs, _state)-1, _state);
for(i=1; i<=n-1; i++)
{
diaga.ptr.p_double[i] = diaga.ptr.p_double[i-1]*sgn/(decaya*(1+0.01*hqrnduniformr(&rs, _state)));
}
rmatrixrndorthogonal(n, &qa, _state);
ae_matrix_set_length(&densea, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = (double)(0);
for(k=0; k<=n-1; k++)
{
v = v+qa.ptr.pp_double[k][i]*diaga.ptr.p_double[k]*qa.ptr.pp_double[k][j];
}
densea.ptr.pp_double[i][j] = v;
}
}
isupper = ae_fp_greater(hqrnduniformr(&rs, _state),0.5);
ae_matrix_set_length(&halfa, n, n, _state);
sparsecreate(n, n, 0, &halfsa, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
halfa.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state);
if( j>=i&&isupper )
{
halfa.ptr.pp_double[i][j] = densea.ptr.pp_double[i][j];
sparseset(&halfsa, i, j, densea.ptr.pp_double[i][j], _state);
}
if( j<=i&&!isupper )
{
halfa.ptr.pp_double[i][j] = densea.ptr.pp_double[i][j];
sparseset(&halfsa, i, j, densea.ptr.pp_double[i][j], _state);
}
}
}
sformat = hqrnduniformi(&rs, 2, _state);
if( sformat==0 )
{
sparseconverttocrs(&halfsa, _state);
}
if( sformat==1 )
{
sparseconverttosks(&halfsa, _state);
}
/*
* Solve with eigensolver operating in dense mode
*/
eigsubspacecreate(n, m, &s, _state);
eigsubspacesetcond(&s, tollambda/100, 0, _state);
if( smode==0 )
{
/*
* Dense mode
*/
eigsubspacesolvedenses(&s, &halfa, isupper, &sw, &sz, &rep, _state);
}
else
{
if( smode==1 )
{
/*
* Sparse mode
*/
eigsubspacesolvesparses(&s, &halfsa, isupper, &sw, &sz, &rep, _state);
}
else
{
if( smode==2 )
{
/*
* Out-of-core mode, symmetric version
*/
eigsubspaceoocstart(&s, 0, _state);
while(eigsubspaceooccontinue(&s, _state))
{
eigsubspaceoocgetrequestinfo(&s, &requesttype, &requestsize, _state);
ae_assert(requesttype==0, "EVDI: integrity check failed in unit test", _state);
ae_assert(requestsize>0, "EVDI: integrity check failed in unit test", _state);
eigsubspaceoocgetrequestdata(&s, &ra, _state);
rmatrixsetlengthatleast(&rb, n, requestsize, _state);
rmatrixgemm(n, requestsize, n, 1.0, &densea, 0, 0, 0, &ra, 0, 0, 0, 0.0, &rb, 0, 0, _state);
eigsubspaceoocsendresult(&s, &rb, _state);
}
eigsubspaceoocstop(&s, &sw, &sz, &rep, _state);
}
else
{
ae_assert(ae_false, "unittest: integrity check failed", _state);
}
}
}
/*
* Compare against reference values
*/
for(i=0; i<=m-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(sw.ptr.p_double[i]-diaga.ptr.p_double[i], _state),tollambda), __FILE__, __LINE__, "testevdunit.ap:2126");
v = ae_v_dotproduct(&qa.ptr.pp_double[i][0], 1, &sz.ptr.pp_double[0][i], sz.stride, ae_v_len(0,n-1));
mx = (double)(0);
for(j=0; j<=n-1; j++)
{
mx = ae_maxreal(mx, ae_fabs(sz.ptr.pp_double[j][i]*ae_sign(v, _state)-qa.ptr.pp_double[i][j], _state), _state);
}
ae_set_error_flag(errorflag, ae_fp_greater(mx,tolvector), __FILE__, __LINE__, "testevdunit.ap:2131");
}
}
}
}
/*
* Problem with highly separated eigenvalues (either with alternating
* sign - or all positive). Only a few iterations is performed, we
* want to check convergence properties on such problems.
*/
tollambda = 1.0E-9;
tolvector = 1.0E-4;
itscount = 5;
for(n=1; n<=25; n++)
{
for(m=1; m<=n; m++)
{
for(smode=0; smode<=2; smode++)
{
/*
* Generate eigenproblem
*/
sgn = (double)(2*hqrnduniformi(&rs, 2, _state)-1);
decaya = 1.05;
ae_vector_set_length(&diaga, n, _state);
diaga.ptr.p_double[0] = ae_pow((double)(10), 2*hqrnduniformr(&rs, _state)-1, _state);
for(i=1; i<=n-1; i++)
{
diaga.ptr.p_double[i] = diaga.ptr.p_double[i-1]*sgn/(decaya*(1+0.01*hqrnduniformr(&rs, _state)));
}
for(i=m; i<=n-1; i++)
{
diaga.ptr.p_double[i] = diaga.ptr.p_double[i]/(100+10*hqrnduniformr(&rs, _state));
}
rmatrixrndorthogonal(n, &qa, _state);
ae_matrix_set_length(&densea, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = (double)(0);
for(k=0; k<=n-1; k++)
{
v = v+qa.ptr.pp_double[k][i]*diaga.ptr.p_double[k]*qa.ptr.pp_double[k][j];
}
densea.ptr.pp_double[i][j] = v;
}
}
isupper = ae_fp_greater(hqrnduniformr(&rs, _state),0.5);
ae_matrix_set_length(&halfa, n, n, _state);
sparsecreate(n, n, 0, &halfsa, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
halfa.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state);
if( j>=i&&isupper )
{
halfa.ptr.pp_double[i][j] = densea.ptr.pp_double[i][j];
sparseset(&halfsa, i, j, densea.ptr.pp_double[i][j], _state);
}
if( j<=i&&!isupper )
{
halfa.ptr.pp_double[i][j] = densea.ptr.pp_double[i][j];
sparseset(&halfsa, i, j, densea.ptr.pp_double[i][j], _state);
}
}
}
sformat = hqrnduniformi(&rs, 2, _state);
if( sformat==0 )
{
sparseconverttocrs(&halfsa, _state);
}
if( sformat==1 )
{
sparseconverttosks(&halfsa, _state);
}
/*
* Solve with eigensolver operating in dense mode
*/
eigsubspacecreate(n, m, &s, _state);
eigsubspacesetcond(&s, (double)(0), itscount, _state);
if( smode==0 )
{
/*
* Dense mode
*/
eigsubspacesolvedenses(&s, &halfa, isupper, &sw, &sz, &rep, _state);
}
else
{
if( smode==1 )
{
/*
* Sparse mode
*/
eigsubspacesolvesparses(&s, &halfsa, isupper, &sw, &sz, &rep, _state);
}
else
{
if( smode==2 )
{
/*
* Out-of-core mode, symmetric version
*
* NOTE: we check that solver performs no more than ItsCount+2 calls
*/
callcount = 0;
eigsubspaceoocstart(&s, 0, _state);
while(eigsubspaceooccontinue(&s, _state))
{
eigsubspaceoocgetrequestinfo(&s, &requesttype, &requestsize, _state);
ae_assert(requesttype==0, "EVDI: integrity check failed in unit test", _state);
ae_assert(requestsize>0, "EVDI: integrity check failed in unit test", _state);
eigsubspaceoocgetrequestdata(&s, &ra, _state);
rmatrixsetlengthatleast(&rb, n, requestsize, _state);
rmatrixgemm(n, requestsize, n, 1.0, &densea, 0, 0, 0, &ra, 0, 0, 0, 0.0, &rb, 0, 0, _state);
eigsubspaceoocsendresult(&s, &rb, _state);
callcount = callcount+1;
}
eigsubspaceoocstop(&s, &sw, &sz, &rep, _state);
ae_set_error_flag(errorflag, callcount>itscount+2, __FILE__, __LINE__, "testevdunit.ap:2238");
}
else
{
ae_assert(ae_false, "unittest: integrity check failed", _state);
}
}
}
/*
* Compare against reference values
*/
ae_set_error_flag(errorflag, rep.iterationscount>itscount, __FILE__, __LINE__, "testevdunit.ap:2246");
for(i=0; i<=m-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(sw.ptr.p_double[i]-diaga.ptr.p_double[i], _state),tollambda), __FILE__, __LINE__, "testevdunit.ap:2249");
v = ae_v_dotproduct(&qa.ptr.pp_double[i][0], 1, &sz.ptr.pp_double[0][i], sz.stride, ae_v_len(0,n-1));
mx = (double)(0);
for(j=0; j<=n-1; j++)
{
mx = ae_maxreal(mx, ae_fabs(sz.ptr.pp_double[j][i]*ae_sign(v, _state)-qa.ptr.pp_double[i][j], _state), _state);
}
ae_set_error_flag(errorflag, ae_fp_greater(mx,tolvector), __FILE__, __LINE__, "testevdunit.ap:2254");
}
}
}
}
/*
* Problem with numerically zero matrix. We check ability to stop
* and to return orthogonal vectors.
*/
tollambda = 1.0E-9;
itscount = 5;
for(n=1; n<=25; n++)
{
for(m=1; m<=n; m++)
{
/*
* Generate eigenproblem
*/
ae_matrix_set_length(&densea, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
densea.ptr.pp_double[i][j] = (double)(0);
}
}
/*
* Solve with eigensolver operating in dense mode,
* iteration count based stopping condition.
*/
eigsubspacecreate(n, m, &s, _state);
eigsubspacesetcond(&s, (double)(0), itscount, _state);
eigsubspacesolvedenses(&s, &densea, ae_true, &sw, &sz, &rep, _state);
ae_set_error_flag(errorflag, rep.iterationscount>itscount, __FILE__, __LINE__, "testevdunit.ap:2283");
for(i=0; i<=m-1; i++)
{
for(j=i; j<=m-1; j++)
{
v = ae_v_dotproduct(&sz.ptr.pp_double[0][i], sz.stride, &sz.ptr.pp_double[0][j], sz.stride, ae_v_len(0,n-1));
if( j==i )
{
v = v-1;
}
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v, _state),1.0E3*ae_machineepsilon), __FILE__, __LINE__, "testevdunit.ap:2291");
}
ae_set_error_flag(errorflag, ae_fp_neq(sw.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testevdunit.ap:2293");
}
/*
* Solve with eigensolver operating in dense mode,
* eps-based stopping condition.
*/
eigsubspacecreate(n, m, &s, _state);
eigsubspacesetcond(&s, tollambda, 0, _state);
eigsubspacesolvedenses(&s, &densea, ae_true, &sw, &sz, &rep, _state);
for(i=0; i<=m-1; i++)
{
for(j=i; j<=m-1; j++)
{
v = ae_v_dotproduct(&sz.ptr.pp_double[0][i], sz.stride, &sz.ptr.pp_double[0][j], sz.stride, ae_v_len(0,n-1));
if( j==i )
{
v = v-1;
}
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v, _state),1.0E3*ae_machineepsilon), __FILE__, __LINE__, "testevdunit.ap:2310");
}
ae_set_error_flag(errorflag, ae_fp_neq(sw.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testevdunit.ap:2312");
}
}
}
/*
* Test warm start functionality:
* * for many randomly generated problems...
* * ...solve original problem with EPS-based criterion
* * ...then apply small rank-1 correction to the matrix
* * ...and solve again, with warm start
* * ...and solve again, with explicit cold start
* * do so many times and calculate total iteration counts
*
* Iteration counts for warm starts should be significantly lower,
* whilst solution found should be within tolerances.
*/
cnta = 0;
cntb = 0;
cntc = 0;
eps = 1.0E-3;
nu = 0.001;
for(pass=1; pass<=50; pass++)
{
/*
* Generate eigenproblem and rank-1 update
*/
n = 50+hqrnduniformi(&rs, 20, _state);
m = 1+hqrnduniformi(&rs, 5, _state);
ae_matrix_set_length(&ra, n, n, _state);
ae_matrix_set_length(&tmp2, n, n, _state);
ae_vector_set_length(&u, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
tmp2.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
rmatrixgemm(n, n, n, 1.0, &tmp2, 0, 0, 0, &tmp2, 0, 0, 1, 0.0, &ra, 0, 0, _state);
/*
* Solve with eigensolver operating in cold-start mode,
* iteration count based stopping condition.
*/
eigsubspacecreate(n, m, &s, _state);
eigsubspacesetcond(&s, eps, 0, _state);
eigsubspacesolvedenses(&s, &ra, ae_true, &sw, &sz, &rep, _state);
cnta = cnta+rep.iterationscount;
/*
* Solve with eigensolver operating in warm-start mode,
* iteration count based stopping condition.
*/
for(i=0; i<=n-1; i++)
{
u.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
rmatrixger(n, n, &ra, 0, 0, nu, &u, 0, &u, 0, _state);
eigsubspacesetwarmstart(&s, ae_true, _state);
eigsubspacesolvedenses(&s, &ra, ae_true, &sw, &sz, &rep, _state);
cntb = cntb+rep.iterationscount;
/*
* Solve with eigensolver operating in explicit cold-start mode,
* iteration count based stopping condition.
*/
for(i=0; i<=n-1; i++)
{
u.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
rmatrixger(n, n, &ra, 0, 0, nu, &u, 0, &u, 0, _state);
eigsubspacesetwarmstart(&s, ae_false, _state);
eigsubspacesolvedenses(&s, &ra, ae_true, &sw, &sz, &rep, _state);
cntc = cntc+rep.iterationscount;
}
ae_set_error_flag(errorflag, ae_fp_greater((double)(cntb),0.66*cnta), __FILE__, __LINE__, "testevdunit.ap:2387");
ae_set_error_flag(errorflag, ae_fp_less((double)(cntc),0.66*cnta), __FILE__, __LINE__, "testevdunit.ap:2388");
ae_frame_leave(_state);
}
static void testbasestatunit_testranking(ae_bool* err, ae_state *_state);
ae_bool testbasestat(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_bool waserrors;
ae_bool s1errors;
ae_bool covcorrerrors;
ae_bool rankerrors;
double threshold;
ae_int_t i;
ae_int_t j;
ae_int_t n;
ae_int_t kx;
ae_int_t ky;
ae_int_t ctype;
ae_int_t cidxx;
ae_int_t cidxy;
ae_vector x;
ae_vector y;
ae_matrix mx;
ae_matrix my;
ae_matrix cc;
ae_matrix cp;
ae_matrix cs;
double mean;
double variance;
double skewness;
double kurtosis;
double adev;
double median;
double pv;
double v;
double tmean;
double tvariance;
double tskewness;
double tkurtosis;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&mx, 0, sizeof(mx));
memset(&my, 0, sizeof(my));
memset(&cc, 0, sizeof(cc));
memset(&cp, 0, sizeof(cp));
memset(&cs, 0, sizeof(cs));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&mx, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&my, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&cc, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&cp, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&cs, 0, 0, DT_REAL, _state, ae_true);
/*
* Primary settings
*/
waserrors = ae_false;
s1errors = ae_false;
covcorrerrors = ae_false;
rankerrors = ae_false;
threshold = 1000*ae_machineepsilon;
/*
* Ranking
*/
testbasestatunit_testranking(&rankerrors, _state);
/*
* * prepare X and Y - two test samples
* * test 1-sample coefficients
* * test for SampleMean, SampleVariance,
* SampleSkewness, SampleKurtosis.
*/
n = 10;
ae_vector_set_length(&x, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = ae_sqr((double)(i), _state);
}
samplemoments(&x, n, &mean, &variance, &skewness, &kurtosis, _state);
s1errors = s1errors||ae_fp_greater(ae_fabs(mean-28.5, _state),0.001);
s1errors = s1errors||ae_fp_greater(ae_fabs(variance-801.1667, _state),0.001);
s1errors = s1errors||ae_fp_greater(ae_fabs(skewness-0.5751, _state),0.001);
s1errors = s1errors||ae_fp_greater(ae_fabs(kurtosis+1.2666, _state),0.001);
tmean = samplemean(&x, n, _state);
tvariance = samplevariance(&x, n, _state);
tskewness = sampleskewness(&x, n, _state);
tkurtosis = samplekurtosis(&x, n, _state);
s1errors = s1errors||ae_fp_greater(ae_fabs(mean-tmean, _state),1.0E-15);
s1errors = s1errors||ae_fp_greater(ae_fabs(variance-tvariance, _state),1.0E-15);
s1errors = s1errors||ae_fp_greater(ae_fabs(skewness-tskewness, _state),1.0E-15);
s1errors = s1errors||ae_fp_greater(ae_fabs(kurtosis-tkurtosis, _state),1.0E-15);
sampleadev(&x, n, &adev, _state);
s1errors = s1errors||ae_fp_greater(ae_fabs(adev-23.2000, _state),0.001);
samplemedian(&x, n, &median, _state);
s1errors = s1errors||ae_fp_greater(ae_fabs(median-0.5*(16+25), _state),0.001);
for(i=0; i<=n-1; i++)
{
samplepercentile(&x, n, (double)i/(double)(n-1), &pv, _state);
s1errors = s1errors||ae_fp_greater(ae_fabs(pv-x.ptr.p_double[i], _state),0.001);
}
samplepercentile(&x, n, 0.5, &pv, _state);
s1errors = s1errors||ae_fp_greater(ae_fabs(pv-0.5*(16+25), _state),0.001);
/*
* test covariance/correlation:
* * 2-sample coefficients
*
* We generate random matrices MX and MY
*/
n = 10;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = ae_sqr((double)(i), _state);
y.ptr.p_double[i] = (double)(i);
}
covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(pearsoncorr2(&x, &y, n, _state)-0.9627, _state),0.0001);
covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(spearmancorr2(&x, &y, n, _state)-1.0000, _state),0.0001);
covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(cov2(&x, &y, n, _state)-82.5000, _state),0.0001);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = ae_sqr(i-0.5*n, _state);
y.ptr.p_double[i] = (double)(i);
}
covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(pearsoncorr2(&x, &y, n, _state)+0.3676, _state),0.0001);
covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(spearmancorr2(&x, &y, n, _state)+0.2761, _state),0.0001);
covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(cov2(&x, &y, n, _state)+9.1667, _state),0.0001);
/*
* test covariance/correlation:
* * matrix covariance/correlation
* * matrix cross-covariance/cross-correlation
*
* We generate random matrices MX and MY which contain KX (KY)
* columns, all except one are random, one of them is constant.
* We test that function (a) do not crash on constant column,
* and (b) return variances/correlations that are exactly zero
* for this column.
*
* CType control variable controls type of constant: 0 - no constant
* column, 1 - zero column, 2 - nonzero column with value whose
* binary representation contains many non-zero bits. Using such
* type of constant column we are able to ensure than even in the
* presense of roundoff error functions correctly detect constant
* columns.
*/
for(n=0; n<=10; n++)
{
if( n>0 )
{
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
}
for(ctype=0; ctype<=2; ctype++)
{
for(kx=1; kx<=10; kx++)
{
for(ky=1; ky<=10; ky++)
{
/*
* Fill matrices, add constant column (when CType=1 or =2)
*/
cidxx = -1;
cidxy = -1;
if( n>0 )
{
ae_matrix_set_length(&mx, n, kx, _state);
ae_matrix_set_length(&my, n, ky, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=kx-1; j++)
{
mx.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
for(j=0; j<=ky-1; j++)
{
my.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
if( ctype==1 )
{
cidxx = ae_randominteger(kx, _state);
cidxy = ae_randominteger(ky, _state);
for(i=0; i<=n-1; i++)
{
mx.ptr.pp_double[i][cidxx] = 0.0;
my.ptr.pp_double[i][cidxy] = 0.0;
}
}
if( ctype==2 )
{
cidxx = ae_randominteger(kx, _state);
cidxy = ae_randominteger(ky, _state);
v = ae_sqrt((double)(ae_randominteger(kx, _state)+1)/(double)kx, _state);
for(i=0; i<=n-1; i++)
{
mx.ptr.pp_double[i][cidxx] = v;
my.ptr.pp_double[i][cidxy] = v;
}
}
}
/*
* test covariance/correlation matrix using
* 2-sample functions as reference point.
*
* We also test that coefficients for constant variables
* are exactly zero.
*/
covm(&mx, n, kx, &cc, _state);
pearsoncorrm(&mx, n, kx, &cp, _state);
spearmancorrm(&mx, n, kx, &cs, _state);
for(i=0; i<=kx-1; i++)
{
for(j=0; j<=kx-1; j++)
{
if( n>0 )
{
ae_v_move(&x.ptr.p_double[0], 1, &mx.ptr.pp_double[0][i], mx.stride, ae_v_len(0,n-1));
ae_v_move(&y.ptr.p_double[0], 1, &mx.ptr.pp_double[0][j], mx.stride, ae_v_len(0,n-1));
}
covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(cov2(&x, &y, n, _state)-cc.ptr.pp_double[i][j], _state),threshold);
covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(pearsoncorr2(&x, &y, n, _state)-cp.ptr.pp_double[i][j], _state),threshold);
covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(spearmancorr2(&x, &y, n, _state)-cs.ptr.pp_double[i][j], _state),threshold);
}
}
if( ctype!=0&&n>0 )
{
for(i=0; i<=kx-1; i++)
{
covcorrerrors = covcorrerrors||ae_fp_neq(cc.ptr.pp_double[i][cidxx],(double)(0));
covcorrerrors = covcorrerrors||ae_fp_neq(cc.ptr.pp_double[cidxx][i],(double)(0));
covcorrerrors = covcorrerrors||ae_fp_neq(cp.ptr.pp_double[i][cidxx],(double)(0));
covcorrerrors = covcorrerrors||ae_fp_neq(cp.ptr.pp_double[cidxx][i],(double)(0));
covcorrerrors = covcorrerrors||ae_fp_neq(cs.ptr.pp_double[i][cidxx],(double)(0));
covcorrerrors = covcorrerrors||ae_fp_neq(cs.ptr.pp_double[cidxx][i],(double)(0));
}
}
/*
* test cross-covariance/cross-correlation matrix using
* 2-sample functions as reference point.
*
* We also test that coefficients for constant variables
* are exactly zero.
*/
covm2(&mx, &my, n, kx, ky, &cc, _state);
pearsoncorrm2(&mx, &my, n, kx, ky, &cp, _state);
spearmancorrm2(&mx, &my, n, kx, ky, &cs, _state);
for(i=0; i<=kx-1; i++)
{
for(j=0; j<=ky-1; j++)
{
if( n>0 )
{
ae_v_move(&x.ptr.p_double[0], 1, &mx.ptr.pp_double[0][i], mx.stride, ae_v_len(0,n-1));
ae_v_move(&y.ptr.p_double[0], 1, &my.ptr.pp_double[0][j], my.stride, ae_v_len(0,n-1));
}
covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(cov2(&x, &y, n, _state)-cc.ptr.pp_double[i][j], _state),threshold);
covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(pearsoncorr2(&x, &y, n, _state)-cp.ptr.pp_double[i][j], _state),threshold);
covcorrerrors = covcorrerrors||ae_fp_greater(ae_fabs(spearmancorr2(&x, &y, n, _state)-cs.ptr.pp_double[i][j], _state),threshold);
}
}
if( ctype!=0&&n>0 )
{
for(i=0; i<=kx-1; i++)
{
covcorrerrors = covcorrerrors||ae_fp_neq(cc.ptr.pp_double[i][cidxy],(double)(0));
covcorrerrors = covcorrerrors||ae_fp_neq(cp.ptr.pp_double[i][cidxy],(double)(0));
covcorrerrors = covcorrerrors||ae_fp_neq(cs.ptr.pp_double[i][cidxy],(double)(0));
}
for(j=0; j<=ky-1; j++)
{
covcorrerrors = covcorrerrors||ae_fp_neq(cc.ptr.pp_double[cidxx][j],(double)(0));
covcorrerrors = covcorrerrors||ae_fp_neq(cp.ptr.pp_double[cidxx][j],(double)(0));
covcorrerrors = covcorrerrors||ae_fp_neq(cs.ptr.pp_double[cidxx][j],(double)(0));
}
}
}
}
}
}
/*
* Final report
*/
waserrors = (s1errors||covcorrerrors)||rankerrors;
if( !silent )
{
printf("DESC.STAT TEST\n");
printf("TOTAL RESULTS: ");
if( !waserrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* 1-SAMPLE FUNCTIONALITY: ");
if( !s1errors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* CORRELATION/COVARIATION: ");
if( !covcorrerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* RANKING: ");
if( !rankerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST SUMMARY: FAILED\n");
}
else
{
printf("TEST SUMMARY: PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function tests ranking functionality. In case of failure it sets
Err parameter to True; this parameter is left unchanged otherwise.
*************************************************************************/
static void testbasestatunit_testranking(ae_bool* err, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t testk;
ae_int_t npoints;
ae_int_t nfeatures;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_matrix xy0;
ae_matrix xy1;
ae_matrix xy2;
double v;
ae_frame_make(_state, &_frame_block);
memset(&xy0, 0, sizeof(xy0));
memset(&xy1, 0, sizeof(xy1));
memset(&xy2, 0, sizeof(xy2));
ae_matrix_init(&xy0, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy1, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true);
/*
* Test 1 - large array, unique ranks, each row is obtained as follows:
* * we generate X[i=0..N-1] = I
* * we add random noise: X[i] := X[i] + 0.2*randomreal()-0.1
* * we perform random permutation
*
* Such dataset has following properties:
* * all data are unique within their rows
* * rank(X[i]) = round(X[i])
*
* We perform several tests with different NPoints/NFeatures.
*/
for(testk=0; testk<=2; testk++)
{
/*
* Select problem size
*/
if( testk==0 )
{
npoints = 200;
nfeatures = 1000;
}
else
{
if( testk==1 )
{
npoints = 1000;
nfeatures = 200;
}
else
{
npoints = ae_round(ae_sqrt(smpactivationlevel(_state), _state), _state);
nfeatures = ae_round(ae_sqrt(smpactivationlevel(_state), _state), _state);
}
}
/*
* Generate XY0, XY1, XY2
*/
ae_matrix_set_length(&xy0, npoints, nfeatures, _state);
ae_matrix_set_length(&xy1, npoints, nfeatures, _state);
ae_matrix_set_length(&xy2, npoints, nfeatures, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nfeatures-1; j++)
{
xy0.ptr.pp_double[i][j] = j+0.2*ae_randomreal(_state)-0.1;
}
for(j=0; j<=nfeatures-2; j++)
{
k = ae_randominteger(nfeatures-j, _state);
if( k!=0 )
{
v = xy0.ptr.pp_double[i][j];
xy0.ptr.pp_double[i][j] = xy0.ptr.pp_double[i][j+k];
xy0.ptr.pp_double[i][j+k] = v;
}
}
for(j=0; j<=nfeatures-1; j++)
{
xy1.ptr.pp_double[i][j] = xy0.ptr.pp_double[i][j];
xy2.ptr.pp_double[i][j] = xy0.ptr.pp_double[i][j];
}
}
/*
* Test uncentered ranks
*/
rankdata(&xy0, npoints, nfeatures, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nfeatures-1; j++)
{
if( ae_fp_neq(xy0.ptr.pp_double[i][j],(double)(ae_round(xy2.ptr.pp_double[i][j], _state))) )
{
*err = ae_true;
}
}
}
/*
* Test centered ranks:
* they must be equal to uncentered ranks minus (NFeatures-1)/2
*/
rankdatacentered(&xy1, npoints, nfeatures, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nfeatures-1; j++)
{
if( ae_fp_neq(xy1.ptr.pp_double[i][j],ae_round(xy2.ptr.pp_double[i][j], _state)-(double)(nfeatures-1)/(double)2) )
{
*err = ae_true;
}
}
}
}
/*
* Test correct handling of tied ranks
*/
npoints = 3;
nfeatures = 4;
ae_matrix_set_length(&xy0, npoints, nfeatures, _state);
ae_matrix_set_length(&xy1, npoints, nfeatures, _state);
xy0.ptr.pp_double[0][0] = 2.25;
xy0.ptr.pp_double[0][1] = 3.75;
xy0.ptr.pp_double[0][2] = 3.25;
xy0.ptr.pp_double[0][3] = 2.25;
xy0.ptr.pp_double[1][0] = (double)(2);
xy0.ptr.pp_double[1][1] = (double)(2);
xy0.ptr.pp_double[1][2] = (double)(2);
xy0.ptr.pp_double[1][3] = (double)(7);
xy0.ptr.pp_double[2][0] = (double)(9);
xy0.ptr.pp_double[2][1] = (double)(9);
xy0.ptr.pp_double[2][2] = (double)(9);
xy0.ptr.pp_double[2][3] = (double)(9);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nfeatures-1; j++)
{
xy1.ptr.pp_double[i][j] = xy0.ptr.pp_double[i][j];
}
}
rankdata(&xy0, npoints, nfeatures, _state);
if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[0][0]-0.5, _state),10*ae_machineepsilon) )
{
*err = ae_true;
}
if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[0][1]-3.0, _state),10*ae_machineepsilon) )
{
*err = ae_true;
}
if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[0][2]-2.0, _state),10*ae_machineepsilon) )
{
*err = ae_true;
}
if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[0][3]-0.5, _state),10*ae_machineepsilon) )
{
*err = ae_true;
}
if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[1][0]-1.0, _state),10*ae_machineepsilon) )
{
*err = ae_true;
}
if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[1][1]-1.0, _state),10*ae_machineepsilon) )
{
*err = ae_true;
}
if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[1][2]-1.0, _state),10*ae_machineepsilon) )
{
*err = ae_true;
}
if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[1][3]-3.0, _state),10*ae_machineepsilon) )
{
*err = ae_true;
}
if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[2][0]-1.5, _state),10*ae_machineepsilon) )
{
*err = ae_true;
}
if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[2][1]-1.5, _state),10*ae_machineepsilon) )
{
*err = ae_true;
}
if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[2][2]-1.5, _state),10*ae_machineepsilon) )
{
*err = ae_true;
}
if( ae_fp_greater(ae_fabs(xy0.ptr.pp_double[2][3]-1.5, _state),10*ae_machineepsilon) )
{
*err = ae_true;
}
rankdatacentered(&xy1, npoints, nfeatures, _state);
if( ae_fp_greater(ae_fabs(xy1.ptr.pp_double[0][0]+1.0, _state),10*ae_machineepsilon) )
{
*err = ae_true;
}
if( ae_fp_greater(ae_fabs(xy1.ptr.pp_double[0][1]-1.5, _state),10*ae_machineepsilon) )
{
*err = ae_true;
}
if( ae_fp_greater(ae_fabs(xy1.ptr.pp_double[0][2]-0.5, _state),10*ae_machineepsilon) )
{
*err = ae_true;
}
if( ae_fp_greater(ae_fabs(xy1.ptr.pp_double[0][3]+1.0, _state),10*ae_machineepsilon) )
{
*err = ae_true;
}
if( ae_fp_greater(ae_fabs(xy1.ptr.pp_double[1][0]+0.5, _state),10*ae_machineepsilon) )
{
*err = ae_true;
}
if( ae_fp_greater(ae_fabs(xy1.ptr.pp_double[1][1]+0.5, _state),10*ae_machineepsilon) )
{
*err = ae_true;
}
if( ae_fp_greater(ae_fabs(xy1.ptr.pp_double[1][2]+0.5, _state),10*ae_machineepsilon) )
{
*err = ae_true;
}
if( ae_fp_greater(ae_fabs(xy1.ptr.pp_double[1][3]-1.5, _state),10*ae_machineepsilon) )
{
*err = ae_true;
}
if( ae_fp_neq(xy1.ptr.pp_double[2][0],(double)(0)) )
{
*err = ae_true;
}
if( ae_fp_neq(xy1.ptr.pp_double[2][1],(double)(0)) )
{
*err = ae_true;
}
if( ae_fp_neq(xy1.ptr.pp_double[2][2],(double)(0)) )
{
*err = ae_true;
}
if( ae_fp_neq(xy1.ptr.pp_double[2][3],(double)(0)) )
{
*err = ae_true;
}
ae_frame_leave(_state);
}
static void testpcaunit_calculatemv(/* Real */ ae_vector* x,
ae_int_t n,
double* mean,
double* means,
double* stddev,
double* stddevs,
ae_state *_state);
ae_bool testpca(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t maxn;
ae_int_t maxm;
double threshold;
ae_int_t m;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t info;
ae_vector means;
ae_vector s;
ae_vector s2;
ae_vector t2;
ae_vector t3;
ae_matrix v;
ae_matrix v2;
ae_matrix x;
double t;
double h;
sparsematrix xsparse;
double tmean;
double tmeans;
double tstddev;
double tstddevs;
double tmean2;
double tmeans2;
double tstddev2;
double tstddevs2;
hqrndstate rs;
ae_int_t requested;
double tolreduced;
double varcomplete;
double varreduced;
ae_int_t pass;
ae_bool pcaconverrors;
ae_bool pcaorterrors;
ae_bool pcavarerrors;
ae_bool pcaopterrors;
ae_bool pcadensesubspaceerrors;
ae_bool pcasparsesubspaceerrors;
ae_bool waserrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&means, 0, sizeof(means));
memset(&s, 0, sizeof(s));
memset(&s2, 0, sizeof(s2));
memset(&t2, 0, sizeof(t2));
memset(&t3, 0, sizeof(t3));
memset(&v, 0, sizeof(v));
memset(&v2, 0, sizeof(v2));
memset(&x, 0, sizeof(x));
memset(&xsparse, 0, sizeof(xsparse));
memset(&rs, 0, sizeof(rs));
ae_vector_init(&means, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&t2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&t3, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&v2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&x, 0, 0, DT_REAL, _state, ae_true);
_sparsematrix_init(&xsparse, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Primary settings
*/
maxm = 10;
maxn = 100;
threshold = 1.0E5*ae_machineepsilon;
waserrors = ae_false;
pcaconverrors = ae_false;
pcaorterrors = ae_false;
pcavarerrors = ae_false;
pcaopterrors = ae_false;
pcadensesubspaceerrors = ae_false;
pcasparsesubspaceerrors = ae_false;
/*
* Test 1: N random points in M-dimensional space, full PCA.
*/
for(m=1; m<=maxm; m++)
{
for(n=1; n<=maxn; n++)
{
/*
* Generate task
*/
ae_matrix_set_length(&x, n-1+1, m-1+1, _state);
ae_vector_set_length(&means, m-1+1, _state);
for(j=0; j<=m-1; j++)
{
means.ptr.p_double[j] = 1.5*ae_randomreal(_state)-0.75;
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_double[i][j] = means.ptr.p_double[j]+(2*ae_randomreal(_state)-1);
}
}
/*
* Solve
*/
pcabuildbasis(&x, n, m, &info, &s, &v, _state);
if( info!=1 )
{
pcaconverrors = ae_true;
continue;
}
/*
* Orthogonality test
*/
for(i=0; i<=m-1; i++)
{
for(j=0; j<=m-1; j++)
{
t = ae_v_dotproduct(&v.ptr.pp_double[0][i], v.stride, &v.ptr.pp_double[0][j], v.stride, ae_v_len(0,m-1));
if( i==j )
{
t = t-1;
}
pcaorterrors = pcaorterrors||ae_fp_greater(ae_fabs(t, _state),threshold);
}
}
/*
* Variance test
*/
ae_vector_set_length(&t2, n-1+1, _state);
for(k=0; k<=m-1; k++)
{
for(i=0; i<=n-1; i++)
{
t = ae_v_dotproduct(&x.ptr.pp_double[i][0], 1, &v.ptr.pp_double[0][k], v.stride, ae_v_len(0,m-1));
t2.ptr.p_double[i] = t;
}
testpcaunit_calculatemv(&t2, n, &tmean, &tmeans, &tstddev, &tstddevs, _state);
if( n!=1 )
{
t = ae_sqr(tstddev, _state)*n/(n-1);
}
else
{
t = (double)(0);
}
pcavarerrors = pcavarerrors||ae_fp_greater(ae_fabs(t-s.ptr.p_double[k], _state),threshold);
}
for(k=0; k<=m-2; k++)
{
pcavarerrors = pcavarerrors||ae_fp_less(s.ptr.p_double[k],s.ptr.p_double[k+1]);
}
/*
* Optimality: different perturbations in V[..,0] can't
* increase variance of projection - can only decrease.
*/
ae_vector_set_length(&t2, n-1+1, _state);
ae_vector_set_length(&t3, n-1+1, _state);
for(i=0; i<=n-1; i++)
{
t = ae_v_dotproduct(&x.ptr.pp_double[i][0], 1, &v.ptr.pp_double[0][0], v.stride, ae_v_len(0,m-1));
t2.ptr.p_double[i] = t;
}
testpcaunit_calculatemv(&t2, n, &tmean, &tmeans, &tstddev, &tstddevs, _state);
for(k=0; k<=2*m-1; k++)
{
h = 0.001;
if( k%2!=0 )
{
h = -h;
}
ae_v_move(&t3.ptr.p_double[0], 1, &t2.ptr.p_double[0], 1, ae_v_len(0,n-1));
ae_v_addd(&t3.ptr.p_double[0], 1, &x.ptr.pp_double[0][k/2], x.stride, ae_v_len(0,n-1), h);
t = (double)(0);
for(j=0; j<=m-1; j++)
{
if( j!=k/2 )
{
t = t+ae_sqr(v.ptr.pp_double[j][0], _state);
}
else
{
t = t+ae_sqr(v.ptr.pp_double[j][0]+h, _state);
}
}
t = 1/ae_sqrt(t, _state);
ae_v_muld(&t3.ptr.p_double[0], 1, ae_v_len(0,n-1), t);
testpcaunit_calculatemv(&t3, n, &tmean2, &tmeans2, &tstddev2, &tstddevs2, _state);
pcaopterrors = pcaopterrors||ae_fp_greater(tstddev2,tstddev+threshold);
}
}
}
/*
* Special test for N=0
*/
for(m=1; m<=maxm; m++)
{
/*
* Solve
*/
pcabuildbasis(&x, 0, m, &info, &s, &v, _state);
if( info!=1 )
{
pcaconverrors = ae_true;
continue;
}
/*
* Orthogonality test
*/
for(i=0; i<=m-1; i++)
{
for(j=0; j<=m-1; j++)
{
t = ae_v_dotproduct(&v.ptr.pp_double[0][i], v.stride, &v.ptr.pp_double[0][j], v.stride, ae_v_len(0,m-1));
if( i==j )
{
t = t-1;
}
pcaorterrors = pcaorterrors||ae_fp_greater(ae_fabs(t, _state),threshold);
}
}
}
/*
* Test dense reduced subspace PCA on randomly generated matrix. Because
* matrix is random, it may have bad spectral properties, so large
* number of iterations is performed.
*
* Following properties are tested:
* * principal vectors are orthogonal
* * variance values are computed correctly
* * variance values are decreasing
* * variance by inexact reduced PCA deviates from variance explained
* by top REQUESTED vectors of complete PCA by at most TolReduced.
*/
tolreduced = 1.0E-3;
for(m=1; m<=maxm; m++)
{
for(n=1; n<=maxn; n++)
{
/*
* Generate task
*/
requested = 1+hqrnduniformi(&rs, m, _state);
ae_vector_set_length(&means, m, _state);
for(j=0; j<=m-1; j++)
{
means.ptr.p_double[j] = 100*hqrndnormal(&rs, _state);
}
ae_matrix_set_length(&x, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_double[i][j] = hqrndnormal(&rs, _state)+means.ptr.p_double[j];
}
}
/*
* Solve
*/
pcatruncatedsubspace(&x, n, m, requested, 1.0E-9, 0, &s, &v, _state);
/*
* Orthogonality test
*/
for(i=0; i<=requested-1; i++)
{
for(j=0; j<=requested-1; j++)
{
t = ae_v_dotproduct(&v.ptr.pp_double[0][i], v.stride, &v.ptr.pp_double[0][j], v.stride, ae_v_len(0,m-1));
if( i==j )
{
t = t-1;
}
ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_greater(ae_fabs(t, _state),threshold), __FILE__, __LINE__, "testpcaunit.ap:217");
}
}
/*
* Variance test
*/
ae_vector_set_length(&t2, n, _state);
for(k=0; k<=requested-1; k++)
{
for(i=0; i<=n-1; i++)
{
t = ae_v_dotproduct(&x.ptr.pp_double[i][0], 1, &v.ptr.pp_double[0][k], v.stride, ae_v_len(0,m-1));
t2.ptr.p_double[i] = t;
}
testpcaunit_calculatemv(&t2, n, &tmean, &tmeans, &tstddev, &tstddevs, _state);
if( n!=1 )
{
t = ae_sqr(tstddev, _state)*n/(n-1);
}
else
{
t = (double)(0);
}
ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_greater(ae_fabs(t-s.ptr.p_double[k], _state),threshold), __FILE__, __LINE__, "testpcaunit.ap:236");
}
for(k=0; k<=requested-2; k++)
{
ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_less(ae_fabs(s.ptr.p_double[k], _state),ae_fabs(s.ptr.p_double[k+1], _state)), __FILE__, __LINE__, "testpcaunit.ap:239");
}
for(k=0; k<=requested-1; k++)
{
ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_less_eq(s.ptr.p_double[k],(double)(0))&&ae_fp_greater(ae_fabs(s.ptr.p_double[k], _state),1000*ae_machineepsilon*ae_fabs(s.ptr.p_double[0], _state)), __FILE__, __LINE__, "testpcaunit.ap:241");
}
/*
* Compare variance explained by top REQUESTED vectors from
* full PCA and variance explained by reduced PCA.
*/
pcabuildbasis(&x, n, m, &info, &s2, &v2, _state);
ae_assert(info>0, "PCA error: solver nonconvergence", _state);
varcomplete = 0.0;
varreduced = 0.0;
for(k=0; k<=requested-1; k++)
{
varreduced = varreduced+s.ptr.p_double[k];
varcomplete = varcomplete+s2.ptr.p_double[k];
}
ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_less((varreduced-varcomplete)/varcomplete,-tolreduced), __FILE__, __LINE__, "testpcaunit.ap:256");
ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_greater((varreduced-varcomplete)/varcomplete,1.0E5*ae_machineepsilon), __FILE__, __LINE__, "testpcaunit.ap:257");
}
}
/*
* Test dense subspace reduced PCA on specially designed problem with good
* spectral properties. Only limited number of iterations is performed,
* and we expect fast convergence.
*/
for(pass=0; pass<=3; pass++)
{
/*
* Generate task
*/
m = -1;
requested = -1;
if( pass==0 )
{
m = 50+hqrnduniformi(&rs, 50, _state);
requested = 1+hqrnduniformi(&rs, 10, _state);
}
if( pass==1 )
{
m = 100+hqrnduniformi(&rs, 50, _state);
requested = 1+hqrnduniformi(&rs, 10, _state);
}
if( pass==2 )
{
m = 100+hqrnduniformi(&rs, 50, _state);
requested = 25+hqrnduniformi(&rs, 10, _state);
}
if( pass==3 )
{
m = 200+hqrnduniformi(&rs, 200, _state);
requested = 1+hqrnduniformi(&rs, 10, _state);
}
ae_assert(m>0&&requested>0, "PCA test: integrity failure", _state);
n = 2*m;
tolreduced = 1.0E-3;
ae_matrix_set_length(&x, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_double[i][j] = (double)(0);
}
}
x.ptr.pp_double[0][0] = 1.0;
for(i=1; i<=m-1; i++)
{
x.ptr.pp_double[i][i] = x.ptr.pp_double[i-1][i-1]*(1/1.05);
}
rmatrixrndorthogonalfromtheleft(&x, n, m, _state);
rmatrixrndorthogonalfromtheright(&x, n, m, _state);
/*
* Solve
*/
if( ae_fp_greater(hqrnduniformr(&rs, _state),0.5) )
{
pcatruncatedsubspace(&x, n, m, requested, 0.0, 20, &s, &v, _state);
}
else
{
pcatruncatedsubspace(&x, n, m, requested, 0.0, 0, &s, &v, _state);
}
/*
* Orthogonality test
*/
for(i=0; i<=requested-1; i++)
{
for(j=0; j<=requested-1; j++)
{
t = ae_v_dotproduct(&v.ptr.pp_double[0][i], v.stride, &v.ptr.pp_double[0][j], v.stride, ae_v_len(0,m-1));
if( i==j )
{
t = t-1;
}
ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_greater(ae_fabs(t, _state),threshold), __FILE__, __LINE__, "testpcaunit.ap:323");
}
}
/*
* Variance test
*/
ae_vector_set_length(&t2, n, _state);
for(k=0; k<=requested-1; k++)
{
for(i=0; i<=n-1; i++)
{
t = ae_v_dotproduct(&x.ptr.pp_double[i][0], 1, &v.ptr.pp_double[0][k], v.stride, ae_v_len(0,m-1));
t2.ptr.p_double[i] = t;
}
testpcaunit_calculatemv(&t2, n, &tmean, &tmeans, &tstddev, &tstddevs, _state);
if( n!=1 )
{
t = ae_sqr(tstddev, _state)*n/(n-1);
}
else
{
t = (double)(0);
}
ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_greater(ae_fabs(t-s.ptr.p_double[k], _state),threshold), __FILE__, __LINE__, "testpcaunit.ap:342");
}
for(k=0; k<=requested-2; k++)
{
ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_less(s.ptr.p_double[k],s.ptr.p_double[k+1]), __FILE__, __LINE__, "testpcaunit.ap:345");
}
/*
* Compare variance explained by top REQUESTED vectors from
* full PCA and variance explained by reduced PCA.
*/
pcabuildbasis(&x, n, m, &info, &s2, &v2, _state);
ae_assert(info>0, "PCA error: solver nonconvergence", _state);
varcomplete = 0.0;
varreduced = 0.0;
for(k=0; k<=requested-1; k++)
{
varreduced = varreduced+s.ptr.p_double[k];
varcomplete = varcomplete+s2.ptr.p_double[k];
}
ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_less((varreduced-varcomplete)/varcomplete,-tolreduced), __FILE__, __LINE__, "testpcaunit.ap:360");
ae_set_error_flag(&pcadensesubspaceerrors, ae_fp_greater((varreduced-varcomplete)/varcomplete,1.0E5*ae_machineepsilon), __FILE__, __LINE__, "testpcaunit.ap:361");
}
/*
* Test sparse reduced subspace PCA on randomly generated matrix with
* two non-zero elements at each row. Because matrix is random, it may
* have bad spectral properties, so large number of iterations is performed.
*
* Following properties are tested:
* * principal vectors are orthogonal
* * variance values are computed correctly
* * variance values are decreasing
* * variance by inexact reduced PCA deviates from variance explained
* by top REQUESTED vectors of complete PCA by at most TolReduced.
*/
tolreduced = 1.0E-3;
for(m=1; m<=maxm; m++)
{
for(n=1; n<=maxn; n++)
{
/*
* Generate task
*/
requested = 1+hqrnduniformi(&rs, m, _state);
ae_vector_set_length(&means, m, _state);
for(j=0; j<=m-1; j++)
{
means.ptr.p_double[j] = 100*hqrndnormal(&rs, _state);
}
sparsecreate(n, m, 0, &xsparse, _state);
for(i=0; i<=n-1; i++)
{
j = hqrnduniformi(&rs, m, _state);
sparseset(&xsparse, i, j, hqrndnormal(&rs, _state)+means.ptr.p_double[j], _state);
j = hqrnduniformi(&rs, m, _state);
sparseset(&xsparse, i, j, hqrndnormal(&rs, _state)+means.ptr.p_double[j], _state);
}
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
sparseconverttocrs(&xsparse, _state);
}
ae_matrix_set_length(&x, n, m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_double[i][j] = sparseget(&xsparse, i, j, _state);
}
}
/*
* Solve
*/
pcatruncatedsubspacesparse(&xsparse, n, m, requested, 1.0E-9, 0, &s, &v, _state);
/*
* Orthogonality test
*/
for(i=0; i<=requested-1; i++)
{
for(j=0; j<=requested-1; j++)
{
t = ae_v_dotproduct(&v.ptr.pp_double[0][i], v.stride, &v.ptr.pp_double[0][j], v.stride, ae_v_len(0,m-1));
if( i==j )
{
t = t-1;
}
ae_set_error_flag(&pcasparsesubspaceerrors, ae_fp_greater(ae_fabs(t, _state),threshold), __FILE__, __LINE__, "testpcaunit.ap:417");
}
}
/*
* Variance test
*/
ae_vector_set_length(&t2, n, _state);
for(k=0; k<=requested-1; k++)
{
for(i=0; i<=n-1; i++)
{
t = ae_v_dotproduct(&x.ptr.pp_double[i][0], 1, &v.ptr.pp_double[0][k], v.stride, ae_v_len(0,m-1));
t2.ptr.p_double[i] = t;
}
testpcaunit_calculatemv(&t2, n, &tmean, &tmeans, &tstddev, &tstddevs, _state);
if( n!=1 )
{
t = ae_sqr(tstddev, _state)*n/(n-1);
}
else
{
t = (double)(0);
}
ae_set_error_flag(&pcasparsesubspaceerrors, ae_fp_greater(ae_fabs(t-s.ptr.p_double[k], _state),threshold*rmaxabs3(t, s.ptr.p_double[k], 1.0, _state)), __FILE__, __LINE__, "testpcaunit.ap:436");
}
for(k=0; k<=requested-2; k++)
{
ae_set_error_flag(&pcasparsesubspaceerrors, ae_fp_less(ae_fabs(s.ptr.p_double[k], _state),ae_fabs(s.ptr.p_double[k+1], _state)), __FILE__, __LINE__, "testpcaunit.ap:439");
}
for(k=0; k<=requested-1; k++)
{
ae_set_error_flag(&pcasparsesubspaceerrors, ae_fp_less_eq(s.ptr.p_double[k],(double)(0))&&ae_fp_greater(ae_fabs(s.ptr.p_double[k], _state),1000*ae_machineepsilon*ae_maxreal(ae_fabs(s.ptr.p_double[0], _state), (double)(1), _state)), __FILE__, __LINE__, "testpcaunit.ap:441");
}
/*
* Compare variance explained by top REQUESTED vectors from
* full PCA and variance explained by reduced PCA.
*/
pcabuildbasis(&x, n, m, &info, &s2, &v2, _state);
ae_assert(info>0, "PCA error: solver nonconvergence", _state);
varcomplete = 0.0;
varreduced = 0.0;
for(k=0; k<=requested-1; k++)
{
varreduced = varreduced+s.ptr.p_double[k];
varcomplete = varcomplete+s2.ptr.p_double[k];
}
ae_set_error_flag(&pcasparsesubspaceerrors, ae_fp_less((varreduced-varcomplete)/ae_maxreal(varcomplete, (double)(1), _state),-tolreduced), __FILE__, __LINE__, "testpcaunit.ap:456");
ae_set_error_flag(&pcasparsesubspaceerrors, ae_fp_greater((varreduced-varcomplete)/ae_maxreal(varcomplete, (double)(1), _state),1.0E5*ae_machineepsilon), __FILE__, __LINE__, "testpcaunit.ap:457");
}
}
/*
* Final report
*/
waserrors = ((((pcaconverrors||pcaorterrors)||pcavarerrors)||pcaopterrors)||pcadensesubspaceerrors)||pcasparsesubspaceerrors;
if( !silent )
{
printf("PCA TEST\n");
printf("COMPLETE PCA:\n");
printf("* CONVERGENCE ");
if( !pcaconverrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* ORTOGONALITY ");
if( !pcaorterrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* VARIANCE REPORT ");
if( !pcavarerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* OPTIMALITY ");
if( !pcaopterrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("SUBSPACE PCA:\n");
printf("* DENSE SUBSPACE PCA ");
if( !pcadensesubspaceerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* SPARSE SUBSPACE PCA ");
if( !pcasparsesubspaceerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST SUMMARY: FAILED\n");
}
else
{
printf("TEST SUMMARY: PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Moments estimates and their errors
*************************************************************************/
static void testpcaunit_calculatemv(/* Real */ ae_vector* x,
ae_int_t n,
double* mean,
double* means,
double* stddev,
double* stddevs,
ae_state *_state)
{
ae_int_t i;
double v1;
double v2;
double variance;
*mean = 0;
*means = 0;
*stddev = 0;
*stddevs = 0;
*mean = (double)(0);
*means = (double)(1);
*stddev = (double)(0);
*stddevs = (double)(1);
variance = (double)(0);
if( n<=1 )
{
return;
}
/*
* Mean
*/
for(i=0; i<=n-1; i++)
{
*mean = *mean+x->ptr.p_double[i];
}
*mean = *mean/n;
/*
* Variance (using corrected two-pass algorithm)
*/
if( n!=1 )
{
v1 = (double)(0);
for(i=0; i<=n-1; i++)
{
v1 = v1+ae_sqr(x->ptr.p_double[i]-(*mean), _state);
}
v2 = (double)(0);
for(i=0; i<=n-1; i++)
{
v2 = v2+(x->ptr.p_double[i]-(*mean));
}
v2 = ae_sqr(v2, _state)/n;
variance = (v1-v2)/n;
if( ae_fp_less(variance,(double)(0)) )
{
variance = (double)(0);
}
*stddev = ae_sqrt(variance, _state);
}
/*
* Errors
*/
*means = *stddev/ae_sqrt((double)(n), _state);
*stddevs = *stddev*ae_sqrt((double)(2), _state)/ae_sqrt((double)(n-1), _state);
}
static void testbdssunit_unset1di(/* Integer */ ae_vector* a,
ae_state *_state);
/*************************************************************************
Testing BDSS operations
*************************************************************************/
ae_bool testbdss(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_int_t pass;
ae_int_t passcount;
ae_int_t maxn;
ae_int_t maxnq;
ae_vector a;
ae_vector a0;
ae_vector at;
ae_matrix p;
ae_vector thresholds;
ae_int_t ni;
ae_vector c;
ae_vector p1;
ae_vector p2;
ae_vector ties;
ae_vector pt1;
ae_vector pt2;
ae_int_t tiecount;
ae_int_t c1;
ae_int_t c0;
ae_int_t nc;
ae_vector tmp;
ae_vector sortrbuf;
ae_vector sortrbuf2;
ae_vector sortibuf;
double pal;
double pbl;
double par;
double pbr;
double cve;
double cvr;
ae_int_t info;
double threshold;
ae_vector tiebuf;
ae_vector cntbuf;
double rms;
double cvrms;
ae_bool waserrors;
ae_bool tieserrors;
ae_bool split2errors;
ae_bool optimalsplitkerrors;
ae_bool splitkerrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&a0, 0, sizeof(a0));
memset(&at, 0, sizeof(at));
memset(&p, 0, sizeof(p));
memset(&thresholds, 0, sizeof(thresholds));
memset(&c, 0, sizeof(c));
memset(&p1, 0, sizeof(p1));
memset(&p2, 0, sizeof(p2));
memset(&ties, 0, sizeof(ties));
memset(&pt1, 0, sizeof(pt1));
memset(&pt2, 0, sizeof(pt2));
memset(&tmp, 0, sizeof(tmp));
memset(&sortrbuf, 0, sizeof(sortrbuf));
memset(&sortrbuf2, 0, sizeof(sortrbuf2));
memset(&sortibuf, 0, sizeof(sortibuf));
memset(&tiebuf, 0, sizeof(tiebuf));
memset(&cntbuf, 0, sizeof(cntbuf));
ae_vector_init(&a, 0, DT_REAL, _state, ae_true);
ae_vector_init(&a0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&at, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&p, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&thresholds, 0, DT_REAL, _state, ae_true);
ae_vector_init(&c, 0, DT_INT, _state, ae_true);
ae_vector_init(&p1, 0, DT_INT, _state, ae_true);
ae_vector_init(&p2, 0, DT_INT, _state, ae_true);
ae_vector_init(&ties, 0, DT_INT, _state, ae_true);
ae_vector_init(&pt1, 0, DT_INT, _state, ae_true);
ae_vector_init(&pt2, 0, DT_INT, _state, ae_true);
ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
ae_vector_init(&sortrbuf, 0, DT_REAL, _state, ae_true);
ae_vector_init(&sortrbuf2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&sortibuf, 0, DT_INT, _state, ae_true);
ae_vector_init(&tiebuf, 0, DT_INT, _state, ae_true);
ae_vector_init(&cntbuf, 0, DT_INT, _state, ae_true);
waserrors = ae_false;
tieserrors = ae_false;
split2errors = ae_false;
splitkerrors = ae_false;
optimalsplitkerrors = ae_false;
maxn = 100;
maxnq = 49;
passcount = 10;
/*
* Test ties
*/
for(n=1; n<=maxn; n++)
{
for(pass=1; pass<=passcount; pass++)
{
/*
* untied data, test DSTie
*/
testbdssunit_unset1di(&p1, _state);
testbdssunit_unset1di(&p2, _state);
testbdssunit_unset1di(&pt1, _state);
testbdssunit_unset1di(&pt2, _state);
ae_vector_set_length(&a, n-1+1, _state);
ae_vector_set_length(&a0, n-1+1, _state);
ae_vector_set_length(&at, n-1+1, _state);
ae_vector_set_length(&tmp, n-1+1, _state);
a.ptr.p_double[0] = 2*ae_randomreal(_state)-1;
tmp.ptr.p_double[0] = ae_randomreal(_state);
for(i=1; i<=n-1; i++)
{
/*
* A is randomly permuted
*/
a.ptr.p_double[i] = a.ptr.p_double[i-1]+0.1*ae_randomreal(_state)+0.1;
tmp.ptr.p_double[i] = ae_randomreal(_state);
}
tagsortfastr(&tmp, &a, &sortrbuf, &sortrbuf2, n, _state);
for(i=0; i<=n-1; i++)
{
a0.ptr.p_double[i] = a.ptr.p_double[i];
at.ptr.p_double[i] = a.ptr.p_double[i];
}
dstie(&a0, n, &ties, &tiecount, &p1, &p2, _state);
tagsort(&at, n, &pt1, &pt2, _state);
for(i=0; i<=n-1; i++)
{
tieserrors = tieserrors||p1.ptr.p_int[i]!=pt1.ptr.p_int[i];
tieserrors = tieserrors||p2.ptr.p_int[i]!=pt2.ptr.p_int[i];
}
tieserrors = tieserrors||tiecount!=n;
if( tiecount==n )
{
for(i=0; i<=n; i++)
{
tieserrors = tieserrors||ties.ptr.p_int[i]!=i;
}
}
/*
* tied data, test DSTie
*/
testbdssunit_unset1di(&p1, _state);
testbdssunit_unset1di(&p2, _state);
testbdssunit_unset1di(&pt1, _state);
testbdssunit_unset1di(&pt2, _state);
ae_vector_set_length(&a, n-1+1, _state);
ae_vector_set_length(&a0, n-1+1, _state);
ae_vector_set_length(&at, n-1+1, _state);
c1 = 0;
c0 = 0;
for(i=0; i<=n-1; i++)
{
a.ptr.p_double[i] = (double)(ae_randominteger(2, _state));
if( ae_fp_eq(a.ptr.p_double[i],(double)(0)) )
{
c0 = c0+1;
}
else
{
c1 = c1+1;
}
a0.ptr.p_double[i] = a.ptr.p_double[i];
at.ptr.p_double[i] = a.ptr.p_double[i];
}
dstie(&a0, n, &ties, &tiecount, &p1, &p2, _state);
tagsort(&at, n, &pt1, &pt2, _state);
for(i=0; i<=n-1; i++)
{
tieserrors = tieserrors||p1.ptr.p_int[i]!=pt1.ptr.p_int[i];
tieserrors = tieserrors||p2.ptr.p_int[i]!=pt2.ptr.p_int[i];
}
if( c0==0||c1==0 )
{
tieserrors = tieserrors||tiecount!=1;
if( tiecount==1 )
{
tieserrors = tieserrors||ties.ptr.p_int[0]!=0;
tieserrors = tieserrors||ties.ptr.p_int[1]!=n;
}
}
else
{
tieserrors = tieserrors||tiecount!=2;
if( tiecount==2 )
{
tieserrors = tieserrors||ties.ptr.p_int[0]!=0;
tieserrors = tieserrors||ties.ptr.p_int[1]!=c0;
tieserrors = tieserrors||ties.ptr.p_int[2]!=n;
}
}
}
}
/*
* split-2
*/
/*
* General tests for different N's
*/
for(n=1; n<=maxn; n++)
{
ae_vector_set_length(&a, n-1+1, _state);
ae_vector_set_length(&c, n-1+1, _state);
/*
* one-tie test
*/
if( n%2==0 )
{
for(i=0; i<=n-1; i++)
{
a.ptr.p_double[i] = (double)(n);
c.ptr.p_int[i] = i%2;
}
dsoptimalsplit2(&a, &c, n, &info, &threshold, &pal, &pbl, &par, &pbr, &cve, _state);
if( info!=-3 )
{
split2errors = ae_true;
continue;
}
}
/*
* two-tie test
*/
/*
* test #1
*/
if( n>1 )
{
for(i=0; i<=n-1; i++)
{
a.ptr.p_double[i] = (double)(i/((n+1)/2));
c.ptr.p_int[i] = i/((n+1)/2);
}
dsoptimalsplit2(&a, &c, n, &info, &threshold, &pal, &pbl, &par, &pbr, &cve, _state);
if( info!=1 )
{
split2errors = ae_true;
continue;
}
split2errors = split2errors||ae_fp_greater(ae_fabs(threshold-0.5, _state),100*ae_machineepsilon);
split2errors = split2errors||ae_fp_greater(ae_fabs(pal-1, _state),100*ae_machineepsilon);
split2errors = split2errors||ae_fp_greater(ae_fabs(pbl-0, _state),100*ae_machineepsilon);
split2errors = split2errors||ae_fp_greater(ae_fabs(par-0, _state),100*ae_machineepsilon);
split2errors = split2errors||ae_fp_greater(ae_fabs(pbr-1, _state),100*ae_machineepsilon);
}
}
/*
* Special "CREDIT"-test (transparency coefficient)
*/
n = 110;
ae_vector_set_length(&a, n-1+1, _state);
ae_vector_set_length(&c, n-1+1, _state);
a.ptr.p_double[0] = 0.000;
c.ptr.p_int[0] = 0;
a.ptr.p_double[1] = 0.000;
c.ptr.p_int[1] = 0;
a.ptr.p_double[2] = 0.000;
c.ptr.p_int[2] = 0;
a.ptr.p_double[3] = 0.000;
c.ptr.p_int[3] = 0;
a.ptr.p_double[4] = 0.000;
c.ptr.p_int[4] = 0;
a.ptr.p_double[5] = 0.000;
c.ptr.p_int[5] = 0;
a.ptr.p_double[6] = 0.000;
c.ptr.p_int[6] = 0;
a.ptr.p_double[7] = 0.000;
c.ptr.p_int[7] = 1;
a.ptr.p_double[8] = 0.000;
c.ptr.p_int[8] = 0;
a.ptr.p_double[9] = 0.000;
c.ptr.p_int[9] = 1;
a.ptr.p_double[10] = 0.000;
c.ptr.p_int[10] = 0;
a.ptr.p_double[11] = 0.000;
c.ptr.p_int[11] = 0;
a.ptr.p_double[12] = 0.000;
c.ptr.p_int[12] = 0;
a.ptr.p_double[13] = 0.000;
c.ptr.p_int[13] = 0;
a.ptr.p_double[14] = 0.000;
c.ptr.p_int[14] = 0;
a.ptr.p_double[15] = 0.000;
c.ptr.p_int[15] = 0;
a.ptr.p_double[16] = 0.000;
c.ptr.p_int[16] = 0;
a.ptr.p_double[17] = 0.000;
c.ptr.p_int[17] = 0;
a.ptr.p_double[18] = 0.000;
c.ptr.p_int[18] = 0;
a.ptr.p_double[19] = 0.000;
c.ptr.p_int[19] = 0;
a.ptr.p_double[20] = 0.000;
c.ptr.p_int[20] = 0;
a.ptr.p_double[21] = 0.000;
c.ptr.p_int[21] = 0;
a.ptr.p_double[22] = 0.000;
c.ptr.p_int[22] = 1;
a.ptr.p_double[23] = 0.000;
c.ptr.p_int[23] = 0;
a.ptr.p_double[24] = 0.000;
c.ptr.p_int[24] = 0;
a.ptr.p_double[25] = 0.000;
c.ptr.p_int[25] = 0;
a.ptr.p_double[26] = 0.000;
c.ptr.p_int[26] = 0;
a.ptr.p_double[27] = 0.000;
c.ptr.p_int[27] = 1;
a.ptr.p_double[28] = 0.000;
c.ptr.p_int[28] = 0;
a.ptr.p_double[29] = 0.000;
c.ptr.p_int[29] = 1;
a.ptr.p_double[30] = 0.000;
c.ptr.p_int[30] = 0;
a.ptr.p_double[31] = 0.000;
c.ptr.p_int[31] = 1;
a.ptr.p_double[32] = 0.000;
c.ptr.p_int[32] = 0;
a.ptr.p_double[33] = 0.000;
c.ptr.p_int[33] = 1;
a.ptr.p_double[34] = 0.000;
c.ptr.p_int[34] = 0;
a.ptr.p_double[35] = 0.030;
c.ptr.p_int[35] = 0;
a.ptr.p_double[36] = 0.030;
c.ptr.p_int[36] = 0;
a.ptr.p_double[37] = 0.050;
c.ptr.p_int[37] = 0;
a.ptr.p_double[38] = 0.070;
c.ptr.p_int[38] = 1;
a.ptr.p_double[39] = 0.110;
c.ptr.p_int[39] = 0;
a.ptr.p_double[40] = 0.110;
c.ptr.p_int[40] = 1;
a.ptr.p_double[41] = 0.120;
c.ptr.p_int[41] = 0;
a.ptr.p_double[42] = 0.130;
c.ptr.p_int[42] = 0;
a.ptr.p_double[43] = 0.140;
c.ptr.p_int[43] = 0;
a.ptr.p_double[44] = 0.140;
c.ptr.p_int[44] = 0;
a.ptr.p_double[45] = 0.140;
c.ptr.p_int[45] = 0;
a.ptr.p_double[46] = 0.150;
c.ptr.p_int[46] = 0;
a.ptr.p_double[47] = 0.150;
c.ptr.p_int[47] = 0;
a.ptr.p_double[48] = 0.170;
c.ptr.p_int[48] = 0;
a.ptr.p_double[49] = 0.190;
c.ptr.p_int[49] = 1;
a.ptr.p_double[50] = 0.200;
c.ptr.p_int[50] = 0;
a.ptr.p_double[51] = 0.200;
c.ptr.p_int[51] = 0;
a.ptr.p_double[52] = 0.250;
c.ptr.p_int[52] = 0;
a.ptr.p_double[53] = 0.250;
c.ptr.p_int[53] = 0;
a.ptr.p_double[54] = 0.260;
c.ptr.p_int[54] = 0;
a.ptr.p_double[55] = 0.270;
c.ptr.p_int[55] = 0;
a.ptr.p_double[56] = 0.280;
c.ptr.p_int[56] = 0;
a.ptr.p_double[57] = 0.310;
c.ptr.p_int[57] = 0;
a.ptr.p_double[58] = 0.310;
c.ptr.p_int[58] = 0;
a.ptr.p_double[59] = 0.330;
c.ptr.p_int[59] = 0;
a.ptr.p_double[60] = 0.330;
c.ptr.p_int[60] = 0;
a.ptr.p_double[61] = 0.340;
c.ptr.p_int[61] = 0;
a.ptr.p_double[62] = 0.340;
c.ptr.p_int[62] = 0;
a.ptr.p_double[63] = 0.370;
c.ptr.p_int[63] = 0;
a.ptr.p_double[64] = 0.380;
c.ptr.p_int[64] = 1;
a.ptr.p_double[65] = 0.380;
c.ptr.p_int[65] = 0;
a.ptr.p_double[66] = 0.410;
c.ptr.p_int[66] = 0;
a.ptr.p_double[67] = 0.460;
c.ptr.p_int[67] = 0;
a.ptr.p_double[68] = 0.520;
c.ptr.p_int[68] = 0;
a.ptr.p_double[69] = 0.530;
c.ptr.p_int[69] = 0;
a.ptr.p_double[70] = 0.540;
c.ptr.p_int[70] = 0;
a.ptr.p_double[71] = 0.560;
c.ptr.p_int[71] = 0;
a.ptr.p_double[72] = 0.560;
c.ptr.p_int[72] = 0;
a.ptr.p_double[73] = 0.570;
c.ptr.p_int[73] = 0;
a.ptr.p_double[74] = 0.600;
c.ptr.p_int[74] = 0;
a.ptr.p_double[75] = 0.600;
c.ptr.p_int[75] = 0;
a.ptr.p_double[76] = 0.620;
c.ptr.p_int[76] = 0;
a.ptr.p_double[77] = 0.650;
c.ptr.p_int[77] = 0;
a.ptr.p_double[78] = 0.660;
c.ptr.p_int[78] = 0;
a.ptr.p_double[79] = 0.680;
c.ptr.p_int[79] = 0;
a.ptr.p_double[80] = 0.700;
c.ptr.p_int[80] = 0;
a.ptr.p_double[81] = 0.750;
c.ptr.p_int[81] = 0;
a.ptr.p_double[82] = 0.770;
c.ptr.p_int[82] = 0;
a.ptr.p_double[83] = 0.770;
c.ptr.p_int[83] = 0;
a.ptr.p_double[84] = 0.770;
c.ptr.p_int[84] = 0;
a.ptr.p_double[85] = 0.790;
c.ptr.p_int[85] = 0;
a.ptr.p_double[86] = 0.810;
c.ptr.p_int[86] = 0;
a.ptr.p_double[87] = 0.840;
c.ptr.p_int[87] = 0;
a.ptr.p_double[88] = 0.860;
c.ptr.p_int[88] = 0;
a.ptr.p_double[89] = 0.870;
c.ptr.p_int[89] = 0;
a.ptr.p_double[90] = 0.890;
c.ptr.p_int[90] = 0;
a.ptr.p_double[91] = 0.900;
c.ptr.p_int[91] = 1;
a.ptr.p_double[92] = 0.900;
c.ptr.p_int[92] = 0;
a.ptr.p_double[93] = 0.910;
c.ptr.p_int[93] = 0;
a.ptr.p_double[94] = 0.940;
c.ptr.p_int[94] = 0;
a.ptr.p_double[95] = 0.950;
c.ptr.p_int[95] = 0;
a.ptr.p_double[96] = 0.952;
c.ptr.p_int[96] = 0;
a.ptr.p_double[97] = 0.970;
c.ptr.p_int[97] = 0;
a.ptr.p_double[98] = 0.970;
c.ptr.p_int[98] = 0;
a.ptr.p_double[99] = 0.980;
c.ptr.p_int[99] = 0;
a.ptr.p_double[100] = 1.000;
c.ptr.p_int[100] = 0;
a.ptr.p_double[101] = 1.000;
c.ptr.p_int[101] = 0;
a.ptr.p_double[102] = 1.000;
c.ptr.p_int[102] = 0;
a.ptr.p_double[103] = 1.000;
c.ptr.p_int[103] = 0;
a.ptr.p_double[104] = 1.000;
c.ptr.p_int[104] = 0;
a.ptr.p_double[105] = 1.020;
c.ptr.p_int[105] = 0;
a.ptr.p_double[106] = 1.090;
c.ptr.p_int[106] = 0;
a.ptr.p_double[107] = 1.130;
c.ptr.p_int[107] = 0;
a.ptr.p_double[108] = 1.840;
c.ptr.p_int[108] = 0;
a.ptr.p_double[109] = 2.470;
c.ptr.p_int[109] = 0;
dsoptimalsplit2(&a, &c, n, &info, &threshold, &pal, &pbl, &par, &pbr, &cve, _state);
if( info!=1 )
{
split2errors = ae_true;
}
else
{
split2errors = split2errors||ae_fp_greater(ae_fabs(threshold-0.195, _state),100*ae_machineepsilon);
split2errors = split2errors||ae_fp_greater(ae_fabs(pal-0.80, _state),0.02);
split2errors = split2errors||ae_fp_greater(ae_fabs(pbl-0.20, _state),0.02);
split2errors = split2errors||ae_fp_greater(ae_fabs(par-0.97, _state),0.02);
split2errors = split2errors||ae_fp_greater(ae_fabs(pbr-0.03, _state),0.02);
}
/*
* split-2 fast
*/
/*
* General tests for different N's
*/
for(n=1; n<=maxn; n++)
{
ae_vector_set_length(&a, n-1+1, _state);
ae_vector_set_length(&c, n-1+1, _state);
ae_vector_set_length(&tiebuf, n+1, _state);
ae_vector_set_length(&cntbuf, 3+1, _state);
/*
* one-tie test
*/
if( n%2==0 )
{
for(i=0; i<=n-1; i++)
{
a.ptr.p_double[i] = (double)(n);
c.ptr.p_int[i] = i%2;
}
dsoptimalsplit2fast(&a, &c, &tiebuf, &cntbuf, &sortrbuf, &sortibuf, n, 2, 0.00, &info, &threshold, &rms, &cvrms, _state);
if( info!=-3 )
{
split2errors = ae_true;
continue;
}
}
/*
* two-tie test
*/
/*
* test #1
*/
if( n>1 )
{
for(i=0; i<=n-1; i++)
{
a.ptr.p_double[i] = (double)(i/((n+1)/2));
c.ptr.p_int[i] = i/((n+1)/2);
}
dsoptimalsplit2fast(&a, &c, &tiebuf, &cntbuf, &sortrbuf, &sortibuf, n, 2, 0.00, &info, &threshold, &rms, &cvrms, _state);
if( info!=1 )
{
split2errors = ae_true;
continue;
}
split2errors = split2errors||ae_fp_greater(ae_fabs(threshold-0.5, _state),100*ae_machineepsilon);
split2errors = split2errors||ae_fp_greater(ae_fabs(rms-0, _state),100*ae_machineepsilon);
if( n==2 )
{
split2errors = split2errors||ae_fp_greater(ae_fabs(cvrms-0.5, _state),100*ae_machineepsilon);
}
else
{
if( n==3 )
{
split2errors = split2errors||ae_fp_greater(ae_fabs(cvrms-ae_sqrt((2*0+2*0+2*0.25)/6, _state), _state),100*ae_machineepsilon);
}
else
{
split2errors = split2errors||ae_fp_greater(ae_fabs(cvrms, _state),100*ae_machineepsilon);
}
}
}
}
/*
* special tests
*/
n = 10;
ae_vector_set_length(&a, n-1+1, _state);
ae_vector_set_length(&c, n-1+1, _state);
ae_vector_set_length(&tiebuf, n+1, _state);
ae_vector_set_length(&cntbuf, 2*3-1+1, _state);
for(i=0; i<=n-1; i++)
{
a.ptr.p_double[i] = (double)(i);
if( i<=n-3 )
{
c.ptr.p_int[i] = 0;
}
else
{
c.ptr.p_int[i] = i-(n-3);
}
}
dsoptimalsplit2fast(&a, &c, &tiebuf, &cntbuf, &sortrbuf, &sortibuf, n, 3, 0.00, &info, &threshold, &rms, &cvrms, _state);
if( info!=1 )
{
split2errors = ae_true;
}
else
{
split2errors = split2errors||ae_fp_greater(ae_fabs(threshold-(n-2.5), _state),100*ae_machineepsilon);
split2errors = split2errors||ae_fp_greater(ae_fabs(rms-ae_sqrt((0.25+0.25+0.25+0.25)/(3*n), _state), _state),100*ae_machineepsilon);
split2errors = split2errors||ae_fp_greater(ae_fabs(cvrms-ae_sqrt((double)(1+1+1+1)/(double)(3*n), _state), _state),100*ae_machineepsilon);
}
/*
* Optimal split-K
*/
/*
* General tests for different N's
*/
for(n=1; n<=maxnq; n++)
{
ae_vector_set_length(&a, n-1+1, _state);
ae_vector_set_length(&c, n-1+1, _state);
/*
* one-tie test
*/
if( n%2==0 )
{
for(i=0; i<=n-1; i++)
{
a.ptr.p_double[i] = (double)(n);
c.ptr.p_int[i] = i%2;
}
dsoptimalsplitk(&a, &c, n, 2, 2+ae_randominteger(5, _state), &info, &thresholds, &ni, &cve, _state);
if( info!=-3 )
{
optimalsplitkerrors = ae_true;
continue;
}
}
/*
* two-tie test
*/
/*
* test #1
*/
if( n>1 )
{
c0 = 0;
c1 = 0;
for(i=0; i<=n-1; i++)
{
a.ptr.p_double[i] = (double)(i/((n+1)/2));
c.ptr.p_int[i] = i/((n+1)/2);
if( c.ptr.p_int[i]==0 )
{
c0 = c0+1;
}
if( c.ptr.p_int[i]==1 )
{
c1 = c1+1;
}
}
dsoptimalsplitk(&a, &c, n, 2, 2+ae_randominteger(5, _state), &info, &thresholds, &ni, &cve, _state);
if( info!=1 )
{
optimalsplitkerrors = ae_true;
continue;
}
optimalsplitkerrors = optimalsplitkerrors||ni!=2;
optimalsplitkerrors = optimalsplitkerrors||ae_fp_greater(ae_fabs(thresholds.ptr.p_double[0]-0.5, _state),100*ae_machineepsilon);
optimalsplitkerrors = optimalsplitkerrors||ae_fp_greater(ae_fabs(cve-(-c0*ae_log((double)c0/(double)(c0+1), _state)-c1*ae_log((double)c1/(double)(c1+1), _state)), _state),100*ae_machineepsilon);
}
/*
* test #2
*/
if( n>2 )
{
c0 = 1+ae_randominteger(n-1, _state);
c1 = n-c0;
for(i=0; i<=n-1; i++)
{
if( i=16 )
{
/*
* Multi-tie test.
*
* First NC-1 ties have C0 entries, remaining NC-th tie
* have C1 entries.
*/
nc = ae_round(ae_sqrt((double)(n), _state), _state);
c0 = n/nc;
c1 = n-c0*(nc-1);
for(i=0; i<=nc-2; i++)
{
for(j=c0*i; j<=c0*(i+1)-1; j++)
{
a.ptr.p_double[j] = (double)(j);
c.ptr.p_int[j] = i;
}
}
for(j=c0*(nc-1); j<=n-1; j++)
{
a.ptr.p_double[j] = (double)(j);
c.ptr.p_int[j] = nc-1;
}
dsoptimalsplitk(&a, &c, n, nc, nc+ae_randominteger(nc, _state), &info, &thresholds, &ni, &cve, _state);
if( info!=1 )
{
optimalsplitkerrors = ae_true;
continue;
}
optimalsplitkerrors = optimalsplitkerrors||ni!=nc;
if( ni==nc )
{
for(i=0; i<=nc-2; i++)
{
optimalsplitkerrors = optimalsplitkerrors||ae_fp_greater(ae_fabs(thresholds.ptr.p_double[i]-(c0*(i+1)-1+0.5), _state),100*ae_machineepsilon);
}
cvr = -((nc-1)*c0*ae_log((double)c0/(double)(c0+nc-1), _state)+c1*ae_log((double)c1/(double)(c1+nc-1), _state));
optimalsplitkerrors = optimalsplitkerrors||ae_fp_greater(ae_fabs(cve-cvr, _state),100*ae_machineepsilon);
}
}
}
/*
* Non-optimal split-K
*/
/*
* General tests for different N's
*/
for(n=1; n<=maxnq; n++)
{
ae_vector_set_length(&a, n-1+1, _state);
ae_vector_set_length(&c, n-1+1, _state);
/*
* one-tie test
*/
if( n%2==0 )
{
for(i=0; i<=n-1; i++)
{
a.ptr.p_double[i] = (double)(99);
c.ptr.p_int[i] = i%2;
}
dssplitk(&a, &c, n, 2, 2+ae_randominteger(5, _state), &info, &thresholds, &ni, &cve, _state);
if( info!=-3 )
{
splitkerrors = ae_true;
continue;
}
}
/*
* two-tie test
*/
/*
* test #1
*/
if( n>1 )
{
c0 = 0;
c1 = 0;
for(i=0; i<=n-1; i++)
{
a.ptr.p_double[i] = (double)(i/((n+1)/2));
c.ptr.p_int[i] = i/((n+1)/2);
if( c.ptr.p_int[i]==0 )
{
c0 = c0+1;
}
if( c.ptr.p_int[i]==1 )
{
c1 = c1+1;
}
}
dssplitk(&a, &c, n, 2, 2+ae_randominteger(5, _state), &info, &thresholds, &ni, &cve, _state);
if( info!=1 )
{
splitkerrors = ae_true;
continue;
}
splitkerrors = splitkerrors||ni!=2;
if( ni==2 )
{
splitkerrors = splitkerrors||ae_fp_greater(ae_fabs(thresholds.ptr.p_double[0]-0.5, _state),100*ae_machineepsilon);
splitkerrors = splitkerrors||ae_fp_greater(ae_fabs(cve-(-c0*ae_log((double)c0/(double)(c0+1), _state)-c1*ae_log((double)c1/(double)(c1+1), _state)), _state),100*ae_machineepsilon);
}
}
/*
* test #2
*/
if( n>2 )
{
c0 = 1+ae_randominteger(n-1, _state);
c1 = n-c0;
for(i=0; i<=n-1; i++)
{
if( i1 )
{
nc = n/c0;
for(i=0; i<=nc-1; i++)
{
for(j=c0*i; j<=c0*(i+1)-1; j++)
{
a.ptr.p_double[j] = (double)(j);
c.ptr.p_int[j] = i;
}
}
dssplitk(&a, &c, n, nc, nc+ae_randominteger(nc, _state), &info, &thresholds, &ni, &cve, _state);
if( info!=1 )
{
splitkerrors = ae_true;
continue;
}
splitkerrors = splitkerrors||ni!=nc;
if( ni==nc )
{
for(i=0; i<=nc-2; i++)
{
splitkerrors = splitkerrors||ae_fp_greater(ae_fabs(thresholds.ptr.p_double[i]-(c0*(i+1)-1+0.5), _state),100*ae_machineepsilon);
}
cvr = -nc*c0*ae_log((double)c0/(double)(c0+nc-1), _state);
splitkerrors = splitkerrors||ae_fp_greater(ae_fabs(cve-cvr, _state),100*ae_machineepsilon);
}
}
}
}
/*
* report
*/
waserrors = ((tieserrors||split2errors)||optimalsplitkerrors)||splitkerrors;
if( !silent )
{
printf("TESTING BASIC DATASET SUBROUTINES\n");
printf("TIES: ");
if( !tieserrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("SPLIT-2: ");
if( !split2errors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("OPTIMAL SPLIT-K: ");
if( !optimalsplitkerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("SPLIT-K: ");
if( !splitkerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Unsets 1D array.
*************************************************************************/
static void testbdssunit_unset1di(/* Integer */ ae_vector* a,
ae_state *_state)
{
ae_vector_set_length(a, 0+1, _state);
a->ptr.p_int[0] = ae_randominteger(3, _state)-1;
}
static double testmlpbaseunit_vectordiff(/* Real */ ae_vector* g0,
/* Real */ ae_vector* g1,
ae_int_t n,
double s,
ae_state *_state);
static void testmlpbaseunit_createnetwork(multilayerperceptron* network,
ae_int_t nkind,
double a1,
double a2,
ae_int_t nin,
ae_int_t nhid1,
ae_int_t nhid2,
ae_int_t nout,
ae_state *_state);
static void testmlpbaseunit_unsetnetwork(multilayerperceptron* network,
ae_state *_state);
static void testmlpbaseunit_testinformational(ae_int_t nkind,
ae_int_t nin,
ae_int_t nhid1,
ae_int_t nhid2,
ae_int_t nout,
ae_int_t passcount,
ae_bool* err,
ae_state *_state);
static void testmlpbaseunit_testprocessing(ae_int_t nkind,
ae_int_t nin,
ae_int_t nhid1,
ae_int_t nhid2,
ae_int_t nout,
ae_int_t passcount,
ae_bool* err,
ae_state *_state);
static void testmlpbaseunit_testgradient(ae_int_t nkind,
ae_int_t nin,
ae_int_t nhid1,
ae_int_t nhid2,
ae_int_t nout,
ae_int_t passcount,
ae_int_t sizemin,
ae_int_t sizemax,
ae_bool* err,
ae_state *_state);
static void testmlpbaseunit_testhessian(ae_int_t nkind,
ae_int_t nin,
ae_int_t nhid1,
ae_int_t nhid2,
ae_int_t nout,
ae_int_t passcount,
ae_bool* err,
ae_state *_state);
static void testmlpbaseunit_testerr(ae_int_t nkind,
ae_int_t nin,
ae_int_t nhid1,
ae_int_t nhid2,
ae_int_t nout,
ae_int_t passcount,
ae_int_t sizemin,
ae_int_t sizemax,
ae_bool* err,
ae_state *_state);
static void testmlpbaseunit_spectests(ae_bool* inferrors,
ae_bool* procerrors,
ae_bool* graderrors,
ae_bool* hesserrors,
ae_bool* errerrors,
ae_state *_state);
static ae_bool testmlpbaseunit_testmlpgbsubset(ae_state *_state);
ae_bool testmlpbase(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_bool waserrors;
ae_int_t passcount;
ae_int_t maxn;
ae_int_t maxhid;
ae_int_t sizemin;
ae_int_t sizemax;
ae_int_t nf;
ae_int_t nl;
ae_int_t nhid1;
ae_int_t nhid2;
ae_int_t nkind;
multilayerperceptron network;
multilayerperceptron network2;
ae_matrix xy;
ae_matrix valxy;
ae_bool inferrors;
ae_bool procerrors;
ae_bool graderrors;
ae_bool hesserrors;
ae_bool errerrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&network, 0, sizeof(network));
memset(&network2, 0, sizeof(network2));
memset(&xy, 0, sizeof(xy));
memset(&valxy, 0, sizeof(valxy));
_multilayerperceptron_init(&network, _state, ae_true);
_multilayerperceptron_init(&network2, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&valxy, 0, 0, DT_REAL, _state, ae_true);
waserrors = ae_false;
inferrors = ae_false;
procerrors = ae_false;
graderrors = ae_false;
hesserrors = ae_false;
errerrors = ae_false;
passcount = 5;
maxn = 3;
maxhid = 3;
/*
* Special tests
*/
testmlpbaseunit_spectests(&inferrors, &procerrors, &graderrors, &hesserrors, &errerrors, _state);
/*
* General multilayer network tests.
* These tests are performed with small dataset, whose size is in [0,10].
* We test correctness of functions on small sets, but do not test code
* which splits large dataset into smaller chunks.
*/
sizemin = 0;
sizemax = 10;
for(nf=1; nf<=maxn; nf++)
{
for(nl=1; nl<=maxn; nl++)
{
for(nhid1=0; nhid1<=maxhid; nhid1++)
{
for(nhid2=0; nhid2<=maxhid; nhid2++)
{
for(nkind=0; nkind<=3; nkind++)
{
/*
* Skip meaningless parameters combinations
*/
if( nkind==1&&nl<2 )
{
continue;
}
if( nhid1==0&&nhid2!=0 )
{
continue;
}
/*
* Tests
*/
testmlpbaseunit_testinformational(nkind, nf, nhid1, nhid2, nl, passcount, &inferrors, _state);
testmlpbaseunit_testprocessing(nkind, nf, nhid1, nhid2, nl, passcount, &procerrors, _state);
testmlpbaseunit_testgradient(nkind, nf, nhid1, nhid2, nl, passcount, sizemin, sizemax, &graderrors, _state);
testmlpbaseunit_testhessian(nkind, nf, nhid1, nhid2, nl, passcount, &hesserrors, _state);
testmlpbaseunit_testerr(nkind, nf, nhid1, nhid2, nl, passcount, sizemin, sizemax, &errerrors, _state);
}
}
}
}
}
/*
* Special tests on large datasets: test ability to correctly split
* work into smaller chunks.
*/
nf = 2;
nhid1 = 20;
nhid2 = 20;
nl = 2;
sizemin = 50000;
sizemax = 50000;
testmlpbaseunit_testerr(0, nf, nhid1, nhid2, nl, 1, sizemin, sizemax, &errerrors, _state);
testmlpbaseunit_testgradient(0, nf, nhid1, nhid2, nl, 1, sizemin, sizemax, &graderrors, _state);
/*
* Test for MLPGradBatch____Subset()
*/
graderrors = graderrors||testmlpbaseunit_testmlpgbsubset(_state);
/*
* Final report
*/
waserrors = (((inferrors||procerrors)||graderrors)||hesserrors)||errerrors;
if( !silent )
{
printf("MLP TEST\n");
printf("INFORMATIONAL FUNCTIONS: ");
if( !inferrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("BASIC PROCESSING: ");
if( !procerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("GRADIENT CALCULATION: ");
if( !graderrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("HESSIAN CALCULATION: ");
if( !hesserrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("ERROR FUNCTIONS: ");
if( !errerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST SUMMARY: FAILED\n");
}
else
{
printf("TEST SUMMARY: PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function compares vectors G0 and G1 and returns
||G0-G1||/max(||G0||,||G1||,S)
For zero G0, G1 and S (all three quantities are zero) it returns zero.
*************************************************************************/
static double testmlpbaseunit_vectordiff(/* Real */ ae_vector* g0,
/* Real */ ae_vector* g1,
ae_int_t n,
double s,
ae_state *_state)
{
ae_int_t i;
double norm0;
double norm1;
double diff;
double result;
norm0 = (double)(0);
norm1 = (double)(0);
diff = (double)(0);
for(i=0; i<=n-1; i++)
{
norm0 = norm0+ae_sqr(g0->ptr.p_double[i], _state);
norm1 = norm1+ae_sqr(g1->ptr.p_double[i], _state);
diff = diff+ae_sqr(g0->ptr.p_double[i]-g1->ptr.p_double[i], _state);
}
norm0 = ae_sqrt(norm0, _state);
norm1 = ae_sqrt(norm1, _state);
diff = ae_sqrt(diff, _state);
if( (ae_fp_neq(norm0,(double)(0))||ae_fp_neq(norm1,(double)(0)))||ae_fp_neq(s,(double)(0)) )
{
diff = diff/ae_maxreal(ae_maxreal(norm0, norm1, _state), s, _state);
}
else
{
diff = (double)(0);
}
result = diff;
return result;
}
/*************************************************************************
Network creation
This function creates network with desired structure.
Network is created using one of the three methods:
a) straightforward creation using MLPCreate???()
b) MLPCreate???() for proxy object, which is copied with PassThroughSerializer()
c) MLPCreate???() for proxy object, which is copied with MLPCopy()
One of these methods is chosen at random.
*************************************************************************/
static void testmlpbaseunit_createnetwork(multilayerperceptron* network,
ae_int_t nkind,
double a1,
double a2,
ae_int_t nin,
ae_int_t nhid1,
ae_int_t nhid2,
ae_int_t nout,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t mkind;
multilayerperceptron tmp;
ae_frame_make(_state, &_frame_block);
memset(&tmp, 0, sizeof(tmp));
_multilayerperceptron_init(&tmp, _state, ae_true);
ae_assert(((nin>0&&nhid1>=0)&&nhid2>=0)&&nout>0, "CreateNetwork error", _state);
ae_assert(nhid1!=0||nhid2==0, "CreateNetwork error", _state);
ae_assert(nkind!=1||nout>=2, "CreateNetwork error", _state);
mkind = ae_randominteger(3, _state);
if( nhid1==0 )
{
/*
* No hidden layers
*/
if( nkind==0 )
{
if( mkind==0 )
{
mlpcreate0(nin, nout, network, _state);
}
if( mkind==1 )
{
mlpcreate0(nin, nout, &tmp, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
mlpalloc(&_local_serializer, &tmp, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpserialize(&_local_serializer, &tmp, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpunserialize(&_local_serializer, network, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
}
if( mkind==2 )
{
mlpcreate0(nin, nout, &tmp, _state);
mlpcopy(&tmp, network, _state);
}
}
else
{
if( nkind==1 )
{
if( mkind==0 )
{
mlpcreatec0(nin, nout, network, _state);
}
if( mkind==1 )
{
mlpcreatec0(nin, nout, &tmp, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
mlpalloc(&_local_serializer, &tmp, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpserialize(&_local_serializer, &tmp, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpunserialize(&_local_serializer, network, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
}
if( mkind==2 )
{
mlpcreatec0(nin, nout, &tmp, _state);
mlpcopy(&tmp, network, _state);
}
}
else
{
if( nkind==2 )
{
if( mkind==0 )
{
mlpcreateb0(nin, nout, a1, a2, network, _state);
}
if( mkind==1 )
{
mlpcreateb0(nin, nout, a1, a2, &tmp, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
mlpalloc(&_local_serializer, &tmp, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpserialize(&_local_serializer, &tmp, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpunserialize(&_local_serializer, network, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
}
if( mkind==2 )
{
mlpcreateb0(nin, nout, a1, a2, &tmp, _state);
mlpcopy(&tmp, network, _state);
}
}
else
{
if( nkind==3 )
{
if( mkind==0 )
{
mlpcreater0(nin, nout, a1, a2, network, _state);
}
if( mkind==1 )
{
mlpcreater0(nin, nout, a1, a2, &tmp, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
mlpalloc(&_local_serializer, &tmp, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpserialize(&_local_serializer, &tmp, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpunserialize(&_local_serializer, network, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
}
if( mkind==2 )
{
mlpcreater0(nin, nout, a1, a2, &tmp, _state);
mlpcopy(&tmp, network, _state);
}
}
}
}
}
mlprandomizefull(network, _state);
ae_frame_leave(_state);
return;
}
if( nhid2==0 )
{
/*
* One hidden layer
*/
if( nkind==0 )
{
if( mkind==0 )
{
mlpcreate1(nin, nhid1, nout, network, _state);
}
if( mkind==1 )
{
mlpcreate1(nin, nhid1, nout, &tmp, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
mlpalloc(&_local_serializer, &tmp, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpserialize(&_local_serializer, &tmp, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpunserialize(&_local_serializer, network, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
}
if( mkind==2 )
{
mlpcreate1(nin, nhid1, nout, &tmp, _state);
mlpcopy(&tmp, network, _state);
}
}
else
{
if( nkind==1 )
{
if( mkind==0 )
{
mlpcreatec1(nin, nhid1, nout, network, _state);
}
if( mkind==1 )
{
mlpcreatec1(nin, nhid1, nout, &tmp, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
mlpalloc(&_local_serializer, &tmp, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpserialize(&_local_serializer, &tmp, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpunserialize(&_local_serializer, network, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
}
if( mkind==2 )
{
mlpcreatec1(nin, nhid1, nout, &tmp, _state);
mlpcopy(&tmp, network, _state);
}
}
else
{
if( nkind==2 )
{
if( mkind==0 )
{
mlpcreateb1(nin, nhid1, nout, a1, a2, network, _state);
}
if( mkind==1 )
{
mlpcreateb1(nin, nhid1, nout, a1, a2, &tmp, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
mlpalloc(&_local_serializer, &tmp, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpserialize(&_local_serializer, &tmp, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpunserialize(&_local_serializer, network, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
}
if( mkind==2 )
{
mlpcreateb1(nin, nhid1, nout, a1, a2, &tmp, _state);
mlpcopy(&tmp, network, _state);
}
}
else
{
if( nkind==3 )
{
if( mkind==0 )
{
mlpcreater1(nin, nhid1, nout, a1, a2, network, _state);
}
if( mkind==1 )
{
mlpcreater1(nin, nhid1, nout, a1, a2, &tmp, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
mlpalloc(&_local_serializer, &tmp, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpserialize(&_local_serializer, &tmp, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpunserialize(&_local_serializer, network, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
}
if( mkind==2 )
{
mlpcreater1(nin, nhid1, nout, a1, a2, &tmp, _state);
mlpcopy(&tmp, network, _state);
}
}
}
}
}
mlprandomizefull(network, _state);
ae_frame_leave(_state);
return;
}
/*
* Two hidden layers
*/
if( nkind==0 )
{
if( mkind==0 )
{
mlpcreate2(nin, nhid1, nhid2, nout, network, _state);
}
if( mkind==1 )
{
mlpcreate2(nin, nhid1, nhid2, nout, &tmp, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
mlpalloc(&_local_serializer, &tmp, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpserialize(&_local_serializer, &tmp, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpunserialize(&_local_serializer, network, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
}
if( mkind==2 )
{
mlpcreate2(nin, nhid1, nhid2, nout, &tmp, _state);
mlpcopy(&tmp, network, _state);
}
}
else
{
if( nkind==1 )
{
if( mkind==0 )
{
mlpcreatec2(nin, nhid1, nhid2, nout, network, _state);
}
if( mkind==1 )
{
mlpcreatec2(nin, nhid1, nhid2, nout, &tmp, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
mlpalloc(&_local_serializer, &tmp, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpserialize(&_local_serializer, &tmp, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpunserialize(&_local_serializer, network, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
}
if( mkind==2 )
{
mlpcreatec2(nin, nhid1, nhid2, nout, &tmp, _state);
mlpcopy(&tmp, network, _state);
}
}
else
{
if( nkind==2 )
{
if( mkind==0 )
{
mlpcreateb2(nin, nhid1, nhid2, nout, a1, a2, network, _state);
}
if( mkind==1 )
{
mlpcreateb2(nin, nhid1, nhid2, nout, a1, a2, &tmp, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
mlpalloc(&_local_serializer, &tmp, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpserialize(&_local_serializer, &tmp, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpunserialize(&_local_serializer, network, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
}
if( mkind==2 )
{
mlpcreateb2(nin, nhid1, nhid2, nout, a1, a2, &tmp, _state);
mlpcopy(&tmp, network, _state);
}
}
else
{
if( nkind==3 )
{
if( mkind==0 )
{
mlpcreater2(nin, nhid1, nhid2, nout, a1, a2, network, _state);
}
if( mkind==1 )
{
mlpcreater2(nin, nhid1, nhid2, nout, a1, a2, &tmp, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
mlpalloc(&_local_serializer, &tmp, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpserialize(&_local_serializer, &tmp, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpunserialize(&_local_serializer, network, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
}
if( mkind==2 )
{
mlpcreater2(nin, nhid1, nhid2, nout, a1, a2, &tmp, _state);
mlpcopy(&tmp, network, _state);
}
}
}
}
}
mlprandomizefull(network, _state);
ae_frame_leave(_state);
}
/*************************************************************************
Unsets network (initialize it to smallest network possible
*************************************************************************/
static void testmlpbaseunit_unsetnetwork(multilayerperceptron* network,
ae_state *_state)
{
mlpcreate0(1, 1, network, _state);
}
/*************************************************************************
Informational functions test
*************************************************************************/
static void testmlpbaseunit_testinformational(ae_int_t nkind,
ae_int_t nin,
ae_int_t nhid1,
ae_int_t nhid2,
ae_int_t nout,
ae_int_t passcount,
ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
multilayerperceptron network;
ae_int_t n1;
ae_int_t n2;
ae_int_t wcount;
ae_int_t i;
ae_int_t j;
ae_int_t k;
double threshold;
ae_int_t nlayers;
ae_int_t nmax;
ae_matrix neurons;
ae_vector x;
ae_vector y;
double mean;
double sigma;
ae_int_t fkind;
double c;
double f;
double df;
double d2f;
double s;
ae_frame_make(_state, &_frame_block);
memset(&network, 0, sizeof(network));
memset(&neurons, 0, sizeof(neurons));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
_multilayerperceptron_init(&network, _state, ae_true);
ae_matrix_init(&neurons, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
threshold = 100000*ae_machineepsilon;
testmlpbaseunit_createnetwork(&network, nkind, 0.0, 0.0, nin, nhid1, nhid2, nout, _state);
/*
* test MLPProperties()
*/
mlpproperties(&network, &n1, &n2, &wcount, _state);
*err = ((*err||n1!=nin)||n2!=nout)||wcount<=0;
*err = ((*err||mlpgetinputscount(&network, _state)!=nin)||mlpgetoutputscount(&network, _state)!=nout)||mlpgetweightscount(&network, _state)!=wcount;
/*
* Test network geometry functions
*
* In order to do this we calculate neural network output using
* informational functions only, and compare results with ones
* obtained with MLPProcess():
* 1. we allocate 2-dimensional array of neurons and fill it by zeros
* 2. we full first layer of neurons by input values
* 3. we move through array, calculating values of subsequent layers
* 4. if we have classification network, we SOFTMAX-normalize output layer
* 5. we apply scaling to the outputs
* 6. we compare results with ones obtained by MLPProcess()
*
* NOTE: it is important to do (4) before (5), because on SOFTMAX network
* MLPGetOutputScaling() must return Mean=0 and Sigma=1. In order
* to test it implicitly, we apply it to the classifier results
* (already normalized). If one of the coefficients deviates from
* expected values, we will get error during (6).
*/
nlayers = 2;
nmax = ae_maxint(nin, nout, _state);
if( nhid1!=0 )
{
nlayers = 3;
nmax = ae_maxint(nmax, nhid1, _state);
}
if( nhid2!=0 )
{
nlayers = 4;
nmax = ae_maxint(nmax, nhid2, _state);
}
ae_matrix_set_length(&neurons, nlayers, nmax, _state);
for(i=0; i<=nlayers-1; i++)
{
for(j=0; j<=nmax-1; j++)
{
neurons.ptr.pp_double[i][j] = (double)(0);
}
}
ae_vector_set_length(&x, nin, _state);
for(i=0; i<=nin-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
ae_vector_set_length(&y, nout, _state);
for(i=0; i<=nout-1; i++)
{
y.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(j=0; j<=nin-1; j++)
{
mlpgetinputscaling(&network, j, &mean, &sigma, _state);
neurons.ptr.pp_double[0][j] = (x.ptr.p_double[j]-mean)/sigma;
}
for(i=1; i<=nlayers-1; i++)
{
for(j=0; j<=mlpgetlayersize(&network, i, _state)-1; j++)
{
for(k=0; k<=mlpgetlayersize(&network, i-1, _state)-1; k++)
{
neurons.ptr.pp_double[i][j] = neurons.ptr.pp_double[i][j]+mlpgetweight(&network, i-1, k, i, j, _state)*neurons.ptr.pp_double[i-1][k];
}
mlpgetneuroninfo(&network, i, j, &fkind, &c, _state);
mlpactivationfunction(neurons.ptr.pp_double[i][j]-c, fkind, &f, &df, &d2f, _state);
neurons.ptr.pp_double[i][j] = f;
}
}
if( nkind==1 )
{
s = (double)(0);
for(j=0; j<=nout-1; j++)
{
s = s+ae_exp(neurons.ptr.pp_double[nlayers-1][j], _state);
}
for(j=0; j<=nout-1; j++)
{
neurons.ptr.pp_double[nlayers-1][j] = ae_exp(neurons.ptr.pp_double[nlayers-1][j], _state)/s;
}
}
for(j=0; j<=nout-1; j++)
{
mlpgetoutputscaling(&network, j, &mean, &sigma, _state);
neurons.ptr.pp_double[nlayers-1][j] = neurons.ptr.pp_double[nlayers-1][j]*sigma+mean;
}
mlpprocess(&network, &x, &y, _state);
for(j=0; j<=nout-1; j++)
{
*err = *err||ae_fp_greater(ae_fabs(neurons.ptr.pp_double[nlayers-1][j]-y.ptr.p_double[j], _state),threshold);
}
ae_frame_leave(_state);
}
/*************************************************************************
Processing functions test
*************************************************************************/
static void testmlpbaseunit_testprocessing(ae_int_t nkind,
ae_int_t nin,
ae_int_t nhid1,
ae_int_t nhid2,
ae_int_t nout,
ae_int_t passcount,
ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
multilayerperceptron network;
multilayerperceptron network2;
sparsematrix sparsexy;
ae_matrix densexy;
ae_int_t npoints;
ae_int_t subnp;
ae_bool iscls;
ae_int_t n1;
ae_int_t n2;
ae_int_t wcount;
ae_bool zeronet;
double a1;
double a2;
ae_int_t pass;
ae_int_t i;
ae_int_t j;
ae_bool allsame;
ae_vector x1;
ae_vector x2;
ae_vector y1;
ae_vector y2;
ae_vector p0;
ae_vector p1;
ae_int_t pcount;
double v;
ae_frame_make(_state, &_frame_block);
memset(&network, 0, sizeof(network));
memset(&network2, 0, sizeof(network2));
memset(&sparsexy, 0, sizeof(sparsexy));
memset(&densexy, 0, sizeof(densexy));
memset(&x1, 0, sizeof(x1));
memset(&x2, 0, sizeof(x2));
memset(&y1, 0, sizeof(y1));
memset(&y2, 0, sizeof(y2));
memset(&p0, 0, sizeof(p0));
memset(&p1, 0, sizeof(p1));
_multilayerperceptron_init(&network, _state, ae_true);
_multilayerperceptron_init(&network2, _state, ae_true);
_sparsematrix_init(&sparsexy, _state, ae_true);
ae_matrix_init(&densexy, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&p0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&p1, 0, DT_REAL, _state, ae_true);
ae_assert(passcount>=2, "PassCount<2!", _state);
/*
* Prepare network
*/
a1 = (double)(0);
a2 = (double)(0);
if( nkind==2 )
{
a1 = 1000*ae_randomreal(_state)-500;
a2 = 2*ae_randomreal(_state)-1;
}
if( nkind==3 )
{
a1 = 1000*ae_randomreal(_state)-500;
a2 = a1+(2*ae_randominteger(2, _state)-1)*(0.1+0.9*ae_randomreal(_state));
}
testmlpbaseunit_createnetwork(&network, nkind, a1, a2, nin, nhid1, nhid2, nout, _state);
mlpproperties(&network, &n1, &n2, &wcount, _state);
iscls = mlpissoftmax(&network, _state);
/*
* Initialize arrays
*/
ae_vector_set_length(&x1, nin, _state);
ae_vector_set_length(&x2, nin, _state);
ae_vector_set_length(&y1, nout, _state);
ae_vector_set_length(&y2, nout, _state);
/*
* Initialize sets
*/
npoints = ae_randominteger(11, _state)+10;
if( iscls )
{
ae_matrix_set_length(&densexy, npoints, nin+1, _state);
sparsecreate(npoints, nin+1, npoints, &sparsexy, _state);
}
else
{
ae_matrix_set_length(&densexy, npoints, nin+nout, _state);
sparsecreate(npoints, nin+nout, npoints, &sparsexy, _state);
}
sparseconverttocrs(&sparsexy, _state);
/*
* Main cycle
*/
for(pass=1; pass<=passcount; pass++)
{
/*
* Last run is made on zero network
*/
mlprandomizefull(&network, _state);
zeronet = ae_false;
if( pass==passcount )
{
ae_v_muld(&network.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1), 0);
zeronet = ae_true;
}
/*
* Same inputs leads to same outputs
*/
for(i=0; i<=nin-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
for(i=0; i<=nout-1; i++)
{
y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
mlpprocess(&network, &x1, &y1, _state);
mlpprocess(&network, &x2, &y2, _state);
ae_set_error_flag(err, ae_fp_neq(testmlpbaseunit_vectordiff(&y1, &y2, nout, 1.0, _state),0.0), __FILE__, __LINE__, "testmlpbaseunit.ap:513");
/*
* Same inputs on original network leads to same outputs
* on copy created:
* * using MLPCopy
* * using MLPCopyShared
*/
for(i=0; i<=nin-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
for(i=0; i<=nout-1; i++)
{
y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=nout-1; i++)
{
y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
testmlpbaseunit_unsetnetwork(&network2, _state);
mlpcopy(&network, &network2, _state);
mlpprocess(&network, &x1, &y1, _state);
mlpprocess(&network2, &x2, &y2, _state);
ae_set_error_flag(err, ae_fp_neq(testmlpbaseunit_vectordiff(&y1, &y2, nout, 1.0, _state),0.0), __FILE__, __LINE__, "testmlpbaseunit.ap:534");
for(i=0; i<=nout-1; i++)
{
y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
testmlpbaseunit_unsetnetwork(&network2, _state);
mlpcopyshared(&network, &network2, _state);
mlpprocess(&network, &x1, &y1, _state);
mlpprocess(&network2, &x2, &y2, _state);
ae_set_error_flag(err, ae_fp_neq(testmlpbaseunit_vectordiff(&y1, &y2, nout, 1.0, _state),0.0), __FILE__, __LINE__, "testmlpbaseunit.ap:541");
/*
* Additionally we tests functions for copying of tunable
* parameters by:
* * copying network using MLPCopy
* * randomizing tunable parameters with MLPRandomizeFull()
* * copying tunable parameters with:
* a) MLPCopyTunableParameters
* b) combination of MLPExportTunableParameters and
* MLPImportTunableParameters - we export parameters
* to P1, copy PCount elements to P2, then test import.
*/
for(i=0; i<=nin-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
for(i=0; i<=nout-1; i++)
{
y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=nout-1; i++)
{
y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
testmlpbaseunit_unsetnetwork(&network2, _state);
mlpcopy(&network, &network2, _state);
mlprandomizefull(&network2, _state);
mlpcopytunableparameters(&network, &network2, _state);
mlpprocess(&network, &x1, &y1, _state);
mlpprocess(&network2, &x2, &y2, _state);
ae_set_error_flag(err, ae_fp_neq(testmlpbaseunit_vectordiff(&y1, &y2, nout, 1.0, _state),0.0), __FILE__, __LINE__, "testmlpbaseunit.ap:571");
for(i=0; i<=nout-1; i++)
{
y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
testmlpbaseunit_unsetnetwork(&network2, _state);
mlpcopy(&network, &network2, _state);
mlprandomizefull(&network2, _state);
mlpexporttunableparameters(&network, &p0, &pcount, _state);
ae_vector_set_length(&p1, pcount, _state);
for(i=0; i<=pcount-1; i++)
{
p1.ptr.p_double[i] = p0.ptr.p_double[i];
}
mlpimporttunableparameters(&network2, &p1, _state);
mlpprocess(&network, &x1, &y1, _state);
mlpprocess(&network2, &x2, &y2, _state);
ae_set_error_flag(err, ae_fp_neq(testmlpbaseunit_vectordiff(&y1, &y2, nout, 1.0, _state),0.0), __FILE__, __LINE__, "testmlpbaseunit.ap:585");
/*
* Same inputs on original network leads to same outputs
* on copy created using MLPSerialize
*/
testmlpbaseunit_unsetnetwork(&network2, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
mlpalloc(&_local_serializer, &network, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpserialize(&_local_serializer, &network, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpunserialize(&_local_serializer, &network2, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
for(i=0; i<=nin-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
for(i=0; i<=nout-1; i++)
{
y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
mlpprocess(&network, &x1, &y1, _state);
mlpprocess(&network2, &x2, &y2, _state);
allsame = ae_true;
for(i=0; i<=nout-1; i++)
{
allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]);
}
*err = *err||!allsame;
/*
* Different inputs leads to different outputs (non-zero network)
*/
if( !zeronet )
{
for(i=0; i<=nin-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=nout-1; i++)
{
y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
y2.ptr.p_double[i] = y1.ptr.p_double[i];
}
mlpprocess(&network, &x1, &y1, _state);
mlpprocess(&network, &x2, &y2, _state);
allsame = ae_true;
for(i=0; i<=nout-1; i++)
{
allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]);
}
*err = *err||allsame;
}
/*
* Randomization changes outputs (when inputs are unchanged, non-zero network)
*/
if( !zeronet )
{
for(i=0; i<=nin-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=nout-1; i++)
{
y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
y2.ptr.p_double[i] = y1.ptr.p_double[i];
}
mlpcopy(&network, &network2, _state);
mlprandomize(&network2, _state);
mlpprocess(&network, &x1, &y1, _state);
mlpprocess(&network2, &x1, &y2, _state);
allsame = ae_true;
for(i=0; i<=nout-1; i++)
{
allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]);
}
*err = *err||allsame;
}
/*
* Full randomization changes outputs (when inputs are unchanged, non-zero network)
*/
if( !zeronet )
{
for(i=0; i<=nin-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=nout-1; i++)
{
y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
y2.ptr.p_double[i] = y1.ptr.p_double[i];
}
mlpcopy(&network, &network2, _state);
mlprandomizefull(&network2, _state);
mlpprocess(&network, &x1, &y1, _state);
mlpprocess(&network2, &x1, &y2, _state);
allsame = ae_true;
for(i=0; i<=nout-1; i++)
{
allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]);
}
*err = *err||allsame;
}
/*
* Normalization properties
*/
if( nkind==1 )
{
/*
* Classifier network outputs are normalized
*/
for(i=0; i<=nin-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
mlpprocess(&network, &x1, &y1, _state);
v = (double)(0);
for(i=0; i<=nout-1; i++)
{
v = v+y1.ptr.p_double[i];
*err = *err||ae_fp_less(y1.ptr.p_double[i],(double)(0));
}
*err = *err||ae_fp_greater(ae_fabs(v-1, _state),1000*ae_machineepsilon);
}
if( nkind==2 )
{
/*
* B-type network outputs are bounded from above/below
*/
for(i=0; i<=nin-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
mlpprocess(&network, &x1, &y1, _state);
for(i=0; i<=nout-1; i++)
{
if( ae_fp_greater_eq(a2,(double)(0)) )
{
*err = *err||ae_fp_less(y1.ptr.p_double[i],a1);
}
else
{
*err = *err||ae_fp_greater(y1.ptr.p_double[i],a1);
}
}
}
if( nkind==3 )
{
/*
* R-type network outputs are within [A1,A2] (or [A2,A1])
*/
for(i=0; i<=nin-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
mlpprocess(&network, &x1, &y1, _state);
for(i=0; i<=nout-1; i++)
{
*err = (*err||ae_fp_less(y1.ptr.p_double[i],ae_minreal(a1, a2, _state)))||ae_fp_greater(y1.ptr.p_double[i],ae_maxreal(a1, a2, _state));
}
}
/*
* Comperison MLPInitPreprocessor results with
* MLPInitPreprocessorSparse results
*/
sparseconverttohash(&sparsexy, _state);
if( iscls )
{
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nin-1; j++)
{
densexy.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
sparseset(&sparsexy, i, j, densexy.ptr.pp_double[i][j], _state);
}
densexy.ptr.pp_double[i][nin] = (double)(ae_randominteger(nout, _state));
sparseset(&sparsexy, i, j, densexy.ptr.pp_double[i][nin], _state);
}
}
else
{
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nin+nout-1; j++)
{
densexy.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
sparseset(&sparsexy, i, j, densexy.ptr.pp_double[i][j], _state);
}
}
}
sparseconverttocrs(&sparsexy, _state);
mlpcopy(&network, &network2, _state);
mlpinitpreprocessor(&network, &densexy, npoints, _state);
mlpinitpreprocessorsparse(&network2, &sparsexy, npoints, _state);
subnp = ae_randominteger(npoints, _state);
for(i=0; i<=subnp-1; i++)
{
for(j=0; j<=nin-1; j++)
{
x1.ptr.p_double[j] = 2*ae_randomreal(_state)-1;
}
mlpprocess(&network, &x1, &y1, _state);
mlpprocess(&network2, &x1, &y2, _state);
for(j=0; j<=nout-1; j++)
{
*err = *err||ae_fp_greater(ae_fabs(y1.ptr.p_double[j]-y2.ptr.p_double[j], _state),1.0E-6);
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Gradient functions test
*************************************************************************/
static void testmlpbaseunit_testgradient(ae_int_t nkind,
ae_int_t nin,
ae_int_t nhid1,
ae_int_t nhid2,
ae_int_t nout,
ae_int_t passcount,
ae_int_t sizemin,
ae_int_t sizemax,
ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
multilayerperceptron network;
sparsematrix sparsexy;
sparsematrix sparsexy2;
ae_int_t n1;
ae_int_t n2;
ae_int_t wcount;
double h;
double etol;
double escale;
double gscale;
double nonstricttolerance;
double a1;
double a2;
ae_int_t pass;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t ssize;
ae_int_t subsetsize;
ae_int_t rowsize;
ae_matrix xy;
ae_matrix xy2;
ae_vector grad1;
ae_vector grad2;
ae_vector gradsp;
ae_vector x;
ae_vector y;
ae_vector x1;
ae_vector x2;
ae_vector y1;
ae_vector y2;
ae_vector idx;
double v;
double e;
double e1;
double e2;
double esp;
double v1;
double v2;
double v3;
double v4;
double wprev;
double referencee;
ae_vector referenceg;
ae_frame_make(_state, &_frame_block);
memset(&network, 0, sizeof(network));
memset(&sparsexy, 0, sizeof(sparsexy));
memset(&sparsexy2, 0, sizeof(sparsexy2));
memset(&xy, 0, sizeof(xy));
memset(&xy2, 0, sizeof(xy2));
memset(&grad1, 0, sizeof(grad1));
memset(&grad2, 0, sizeof(grad2));
memset(&gradsp, 0, sizeof(gradsp));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&x1, 0, sizeof(x1));
memset(&x2, 0, sizeof(x2));
memset(&y1, 0, sizeof(y1));
memset(&y2, 0, sizeof(y2));
memset(&idx, 0, sizeof(idx));
memset(&referenceg, 0, sizeof(referenceg));
_multilayerperceptron_init(&network, _state, ae_true);
_sparsematrix_init(&sparsexy, _state, ae_true);
_sparsematrix_init(&sparsexy2, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&grad1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&grad2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&gradsp, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&idx, 0, DT_INT, _state, ae_true);
ae_vector_init(&referenceg, 0, DT_REAL, _state, ae_true);
a1 = (double)(0);
a2 = (double)(0);
if( nkind==2 )
{
a1 = 1000*ae_randomreal(_state)-500;
a2 = 2*ae_randomreal(_state)-1;
}
if( nkind==3 )
{
a1 = 1000*ae_randomreal(_state)-500;
a2 = a1+(2*ae_randominteger(2, _state)-1)*(0.1+0.9*ae_randomreal(_state));
}
testmlpbaseunit_createnetwork(&network, nkind, a1, a2, nin, nhid1, nhid2, nout, _state);
mlpproperties(&network, &n1, &n2, &wcount, _state);
h = 0.0001;
etol = 1.0E-2;
escale = 1.0E-2;
gscale = 1.0E-2;
nonstricttolerance = 0.01;
/*
* Initialize
*/
ae_vector_set_length(&x, nin, _state);
ae_vector_set_length(&x1, nin, _state);
ae_vector_set_length(&x2, nin, _state);
ae_vector_set_length(&y, nout, _state);
ae_vector_set_length(&y1, nout, _state);
ae_vector_set_length(&y2, nout, _state);
ae_vector_set_length(&referenceg, wcount, _state);
ae_vector_set_length(&grad1, wcount, _state);
ae_vector_set_length(&grad2, wcount, _state);
/*
* Process
*/
for(pass=1; pass<=passcount; pass++)
{
/*
* Randomize network, then re-randomaze weights manually.
*
* NOTE: weights magnitude is chosen to be small, about 0.1,
* which allows us to avoid oversaturated network.
* In 10% of cases we use zero weights.
*/
mlprandomizefull(&network, _state);
if( ae_fp_less_eq(ae_randomreal(_state),0.1) )
{
for(i=0; i<=wcount-1; i++)
{
network.weights.ptr.p_double[i] = 0.0;
}
}
else
{
for(i=0; i<=wcount-1; i++)
{
network.weights.ptr.p_double[i] = 0.2*ae_randomreal(_state)-0.1;
}
}
/*
* Test MLPError(), MLPErrorSparse(), MLPGrad() for single-element dataset:
* * generate input X, output Y, combine them in dataset XY
* * calculate "reference" error on dataset manually (call MLPProcess and evaluate sum-of-squared errors)
* * calculate "reference" gradient by performing numerical differentiation of "reference" error
* using 4-point differentiation formula
* * test error/gradient returned by MLPGrad(), MLPError(), MLPErrorSparse()
*/
ae_matrix_set_length(&xy, 1, nin+nout, _state);
sparsecreate(1, nin+nout, nin+nout, &sparsexy, _state);
for(i=0; i<=nin-1; i++)
{
x.ptr.p_double[i] = 4*ae_randomreal(_state)-2;
}
ae_v_move(&xy.ptr.pp_double[0][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,nin-1));
for(i=0; i<=nin-1; i++)
{
sparseset(&sparsexy, 0, i, x.ptr.p_double[i], _state);
}
if( mlpissoftmax(&network, _state) )
{
for(i=0; i<=nout-1; i++)
{
y.ptr.p_double[i] = (double)(0);
}
xy.ptr.pp_double[0][nin] = (double)(ae_randominteger(nout, _state));
sparseset(&sparsexy, 0, nin, xy.ptr.pp_double[0][nin], _state);
y.ptr.p_double[ae_round(xy.ptr.pp_double[0][nin], _state)] = (double)(1);
}
else
{
for(i=0; i<=nout-1; i++)
{
y.ptr.p_double[i] = 4*ae_randomreal(_state)-2;
sparseset(&sparsexy, 0, nin+i, y.ptr.p_double[i], _state);
}
ae_v_move(&xy.ptr.pp_double[0][nin], 1, &y.ptr.p_double[0], 1, ae_v_len(nin,nin+nout-1));
}
sparseconverttocrs(&sparsexy, _state);
mlpprocess(&network, &x, &y2, _state);
ae_v_sub(&y2.ptr.p_double[0], 1, &y.ptr.p_double[0], 1, ae_v_len(0,nout-1));
referencee = ae_v_dotproduct(&y2.ptr.p_double[0], 1, &y2.ptr.p_double[0], 1, ae_v_len(0,nout-1));
referencee = referencee/2;
for(i=0; i<=wcount-1; i++)
{
wprev = network.weights.ptr.p_double[i];
network.weights.ptr.p_double[i] = wprev-2*h;
mlpprocess(&network, &x, &y1, _state);
ae_v_sub(&y1.ptr.p_double[0], 1, &y.ptr.p_double[0], 1, ae_v_len(0,nout-1));
v1 = ae_v_dotproduct(&y1.ptr.p_double[0], 1, &y1.ptr.p_double[0], 1, ae_v_len(0,nout-1));
v1 = v1/2;
network.weights.ptr.p_double[i] = wprev-h;
mlpprocess(&network, &x, &y1, _state);
ae_v_sub(&y1.ptr.p_double[0], 1, &y.ptr.p_double[0], 1, ae_v_len(0,nout-1));
v2 = ae_v_dotproduct(&y1.ptr.p_double[0], 1, &y1.ptr.p_double[0], 1, ae_v_len(0,nout-1));
v2 = v2/2;
network.weights.ptr.p_double[i] = wprev+h;
mlpprocess(&network, &x, &y1, _state);
ae_v_sub(&y1.ptr.p_double[0], 1, &y.ptr.p_double[0], 1, ae_v_len(0,nout-1));
v3 = ae_v_dotproduct(&y1.ptr.p_double[0], 1, &y1.ptr.p_double[0], 1, ae_v_len(0,nout-1));
v3 = v3/2;
network.weights.ptr.p_double[i] = wprev+2*h;
mlpprocess(&network, &x, &y1, _state);
ae_v_sub(&y1.ptr.p_double[0], 1, &y.ptr.p_double[0], 1, ae_v_len(0,nout-1));
v4 = ae_v_dotproduct(&y1.ptr.p_double[0], 1, &y1.ptr.p_double[0], 1, ae_v_len(0,nout-1));
v4 = v4/2;
network.weights.ptr.p_double[i] = wprev;
referenceg.ptr.p_double[i] = (v1-8*v2+8*v3-v4)/(12*h);
}
mlpgrad(&network, &x, &y, &e, &grad2, _state);
seterrorflagdiff(err, e, referencee, etol, escale, _state);
seterrorflagdiff(err, mlperror(&network, &xy, 1, _state), referencee, etol, escale, _state);
seterrorflagdiff(err, mlperrorsparse(&network, &sparsexy, 1, _state), referencee, etol, escale, _state);
ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &grad2, wcount, gscale, _state),etol), __FILE__, __LINE__, "testmlpbaseunit.ap:948");
/*
* Test MLPErrorN(), MLPGradN() for single-element dataset:
* * generate input X, output Y, combine them in dataset XY
* * calculate "reference" error on dataset manually (call MLPProcess and evaluate sum-of-squared errors)
* * calculate "reference" gradient by performing numerical differentiation of "reference" error
* * test error/gradient returned by MLPGradN(), MLPErrorN()
*
* NOTE: because we use inexact 2-point formula, we perform gradient test with NonStrictTolerance
*/
ae_matrix_set_length(&xy, 1, nin+nout, _state);
for(i=0; i<=nin-1; i++)
{
x.ptr.p_double[i] = 4*ae_randomreal(_state)-2;
}
ae_v_move(&xy.ptr.pp_double[0][0], 1, &x.ptr.p_double[0], 1, ae_v_len(0,nin-1));
if( mlpissoftmax(&network, _state) )
{
for(i=0; i<=nout-1; i++)
{
y.ptr.p_double[i] = (double)(0);
}
xy.ptr.pp_double[0][nin] = (double)(ae_randominteger(nout, _state));
y.ptr.p_double[ae_round(xy.ptr.pp_double[0][nin], _state)] = (double)(1);
}
else
{
for(i=0; i<=nout-1; i++)
{
y.ptr.p_double[i] = 4*ae_randomreal(_state)-2;
}
ae_v_move(&xy.ptr.pp_double[0][nin], 1, &y.ptr.p_double[0], 1, ae_v_len(nin,nin+nout-1));
}
mlpprocess(&network, &x, &y2, _state);
referencee = (double)(0);
if( nkind!=1 )
{
for(i=0; i<=nout-1; i++)
{
referencee = referencee+0.5*ae_sqr(y2.ptr.p_double[i]-y.ptr.p_double[i], _state);
}
}
else
{
for(i=0; i<=nout-1; i++)
{
if( ae_fp_neq(y.ptr.p_double[i],(double)(0)) )
{
if( ae_fp_eq(y2.ptr.p_double[i],(double)(0)) )
{
referencee = referencee+y.ptr.p_double[i]*ae_log(ae_maxrealnumber, _state);
}
else
{
referencee = referencee+y.ptr.p_double[i]*ae_log(y.ptr.p_double[i]/y2.ptr.p_double[i], _state);
}
}
}
}
for(i=0; i<=wcount-1; i++)
{
wprev = network.weights.ptr.p_double[i];
network.weights.ptr.p_double[i] = wprev+h;
mlpprocess(&network, &x, &y2, _state);
network.weights.ptr.p_double[i] = wprev-h;
mlpprocess(&network, &x, &y1, _state);
network.weights.ptr.p_double[i] = wprev;
v = (double)(0);
if( nkind!=1 )
{
for(j=0; j<=nout-1; j++)
{
v = v+0.5*(ae_sqr(y2.ptr.p_double[j]-y.ptr.p_double[j], _state)-ae_sqr(y1.ptr.p_double[j]-y.ptr.p_double[j], _state))/(2*h);
}
}
else
{
for(j=0; j<=nout-1; j++)
{
if( ae_fp_neq(y.ptr.p_double[j],(double)(0)) )
{
if( ae_fp_eq(y2.ptr.p_double[j],(double)(0)) )
{
v = v+y.ptr.p_double[j]*ae_log(ae_maxrealnumber, _state);
}
else
{
v = v+y.ptr.p_double[j]*ae_log(y.ptr.p_double[j]/y2.ptr.p_double[j], _state);
}
if( ae_fp_eq(y1.ptr.p_double[j],(double)(0)) )
{
v = v-y.ptr.p_double[j]*ae_log(ae_maxrealnumber, _state);
}
else
{
v = v-y.ptr.p_double[j]*ae_log(y.ptr.p_double[j]/y1.ptr.p_double[j], _state);
}
}
}
v = v/(2*h);
}
referenceg.ptr.p_double[i] = v;
}
mlpgradn(&network, &x, &y, &e, &grad2, _state);
seterrorflagdiff(err, e, referencee, etol, escale, _state);
seterrorflagdiff(err, mlperrorn(&network, &xy, 1, _state), referencee, etol, escale, _state);
ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &grad2, wcount, gscale, _state),nonstricttolerance), __FILE__, __LINE__, "testmlpbaseunit.ap:1029");
/*
* Test that gradient calculation functions automatically allocate
* space for gradient, if needed.
*
* NOTE: we perform test with empty dataset.
*/
sparsecreate(1, nin+nout, 0, &sparsexy, _state);
sparseconverttocrs(&sparsexy, _state);
ae_vector_set_length(&grad1, 1, _state);
mlpgradbatch(&network, &xy, 0, &e1, &grad1, _state);
ae_set_error_flag(err, grad1.cnt!=wcount, __FILE__, __LINE__, "testmlpbaseunit.ap:1042");
ae_vector_set_length(&grad1, 1, _state);
mlpgradbatchsparse(&network, &sparsexy, 0, &e1, &grad1, _state);
ae_set_error_flag(err, grad1.cnt!=wcount, __FILE__, __LINE__, "testmlpbaseunit.ap:1045");
ae_vector_set_length(&grad1, 1, _state);
mlpgradbatchsubset(&network, &xy, 0, &idx, 0, &e1, &grad1, _state);
ae_set_error_flag(err, grad1.cnt!=wcount, __FILE__, __LINE__, "testmlpbaseunit.ap:1048");
ae_vector_set_length(&grad1, 1, _state);
mlpgradbatchsparsesubset(&network, &sparsexy, 0, &idx, 0, &e1, &grad1, _state);
ae_set_error_flag(err, grad1.cnt!=wcount, __FILE__, __LINE__, "testmlpbaseunit.ap:1051");
/*
* Test MLPError(), MLPErrorSparse(), MLPGradBatch(), MLPGradBatchSparse() for many-element dataset:
* * generate random dataset XY
* * calculate "reference" error/gradient using MLPGrad(), which was tested in previous
* section and is assumed to work correctly
* * test results returned by MLPGradBatch/MLPGradBatchSparse against reference ones
*
* NOTE: about 10% of tests are performed with zero SSize
*/
ssize = sizemin+ae_randominteger(sizemax-sizemin+1, _state);
ae_matrix_set_length(&xy, ae_maxint(ssize, 1, _state), nin+nout, _state);
sparsecreate(ae_maxint(ssize, 1, _state), nin+nout, ssize*(nin+nout), &sparsexy, _state);
for(i=0; i<=wcount-1; i++)
{
referenceg.ptr.p_double[i] = (double)(0);
}
referencee = (double)(0);
for(i=0; i<=ssize-1; i++)
{
for(j=0; j<=nin-1; j++)
{
x1.ptr.p_double[j] = 4*ae_randomreal(_state)-2;
sparseset(&sparsexy, i, j, x1.ptr.p_double[j], _state);
}
ae_v_move(&xy.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,nin-1));
if( mlpissoftmax(&network, _state) )
{
for(j=0; j<=nout-1; j++)
{
y1.ptr.p_double[j] = (double)(0);
}
xy.ptr.pp_double[i][nin] = (double)(ae_randominteger(nout, _state));
sparseset(&sparsexy, i, nin, xy.ptr.pp_double[i][nin], _state);
y1.ptr.p_double[ae_round(xy.ptr.pp_double[i][nin], _state)] = (double)(1);
}
else
{
for(j=0; j<=nout-1; j++)
{
y1.ptr.p_double[j] = 4*ae_randomreal(_state)-2;
sparseset(&sparsexy, i, nin+j, y1.ptr.p_double[j], _state);
}
ae_v_move(&xy.ptr.pp_double[i][nin], 1, &y1.ptr.p_double[0], 1, ae_v_len(nin,nin+nout-1));
}
mlpgrad(&network, &x1, &y1, &v, &grad2, _state);
referencee = referencee+v;
ae_v_add(&referenceg.ptr.p_double[0], 1, &grad2.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
}
sparseconverttocrs(&sparsexy, _state);
e2 = mlperror(&network, &xy, ssize, _state);
seterrorflagdiff(err, e2, referencee, etol, escale, _state);
e2 = mlperrorsparse(&network, &sparsexy, ssize, _state);
seterrorflagdiff(err, e2, referencee, etol, escale, _state);
mlpgradbatch(&network, &xy, ssize, &e2, &grad2, _state);
seterrorflagdiff(err, e2, referencee, etol, escale, _state);
ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &grad2, wcount, gscale, _state),etol), __FILE__, __LINE__, "testmlpbaseunit.ap:1104");
mlpgradbatchsparse(&network, &sparsexy, ssize, &esp, &gradsp, _state);
seterrorflagdiff(err, esp, referencee, etol, escale, _state);
ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &gradsp, wcount, gscale, _state),etol), __FILE__, __LINE__, "testmlpbaseunit.ap:1107");
/*
* Test MLPErrorSubset(), MLPGradBatchSubset(), MLPErrorSparseSubset(), MLPGradBatchSparseSubset()
* for many-element dataset with different types of subsets:
* * generate random dataset XY
* * "reference" error/gradient are calculated with MLPGradBatch(),
* which was tested in previous section and is assumed to work correctly
* * we perform tests for different subsets:
* * SubsetSize<0 - subset is a full dataset
* * SubsetSize=0 - subset is empty
* * SubsetSize>0 - random subset
*/
ssize = sizemin+ae_randominteger(sizemax-sizemin+1, _state);
ae_matrix_set_length(&xy, ae_maxint(ssize, 1, _state), nin+nout, _state);
sparsecreate(ae_maxint(ssize, 1, _state), nin+nout, ssize*(nin+nout), &sparsexy, _state);
for(i=0; i<=ssize-1; i++)
{
for(j=0; j<=nin-1; j++)
{
x1.ptr.p_double[j] = 4*ae_randomreal(_state)-2;
sparseset(&sparsexy, i, j, x1.ptr.p_double[j], _state);
}
ae_v_move(&xy.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,nin-1));
if( mlpissoftmax(&network, _state) )
{
for(j=0; j<=nout-1; j++)
{
y1.ptr.p_double[j] = (double)(0);
}
xy.ptr.pp_double[i][nin] = (double)(ae_randominteger(nout, _state));
sparseset(&sparsexy, i, nin, xy.ptr.pp_double[i][nin], _state);
y1.ptr.p_double[ae_round(xy.ptr.pp_double[i][nin], _state)] = (double)(1);
}
else
{
for(j=0; j<=nout-1; j++)
{
y1.ptr.p_double[j] = 4*ae_randomreal(_state)-2;
sparseset(&sparsexy, i, nin+j, y1.ptr.p_double[j], _state);
}
ae_v_move(&xy.ptr.pp_double[i][nin], 1, &y1.ptr.p_double[0], 1, ae_v_len(nin,nin+nout-1));
}
}
sparseconverttocrs(&sparsexy, _state);
if( ssize>0 )
{
subsetsize = 1+ae_randominteger(10, _state);
ae_matrix_set_length(&xy2, subsetsize, nin+nout, _state);
ae_vector_set_length(&idx, subsetsize, _state);
sparsecreate(subsetsize, nin+nout, subsetsize*(nin+nout), &sparsexy2, _state);
if( mlpissoftmax(&network, _state) )
{
rowsize = nin+1;
}
else
{
rowsize = nin+nout;
}
for(i=0; i<=subsetsize-1; i++)
{
k = ae_randominteger(ssize, _state);
idx.ptr.p_int[i] = k;
for(j=0; j<=rowsize-1; j++)
{
xy2.ptr.pp_double[i][j] = xy.ptr.pp_double[k][j];
sparseset(&sparsexy2, i, j, sparseget(&sparsexy, k, j, _state), _state);
}
}
sparseconverttocrs(&sparsexy2, _state);
}
else
{
subsetsize = 0;
ae_matrix_set_length(&xy2, 0, 0, _state);
ae_vector_set_length(&idx, 0, _state);
sparsecreate(1, nin+nout, 0, &sparsexy2, _state);
sparseconverttocrs(&sparsexy2, _state);
}
mlpgradbatch(&network, &xy, ssize, &referencee, &referenceg, _state);
e2 = mlperrorsubset(&network, &xy, ssize, &idx, -1, _state);
esp = mlperrorsparsesubset(&network, &sparsexy, ssize, &idx, -1, _state);
seterrorflagdiff(err, e2, referencee, etol, escale, _state);
seterrorflagdiff(err, esp, referencee, etol, escale, _state);
mlpgradbatchsubset(&network, &xy, ssize, &idx, -1, &e2, &grad2, _state);
mlpgradbatchsparsesubset(&network, &sparsexy, ssize, &idx, -1, &esp, &gradsp, _state);
seterrorflagdiff(err, e2, referencee, etol, escale, _state);
seterrorflagdiff(err, esp, referencee, etol, escale, _state);
ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &grad2, wcount, gscale, _state),etol), __FILE__, __LINE__, "testmlpbaseunit.ap:1192");
ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &gradsp, wcount, gscale, _state),etol), __FILE__, __LINE__, "testmlpbaseunit.ap:1193");
mlpgradbatch(&network, &xy, 0, &referencee, &referenceg, _state);
e2 = mlperrorsubset(&network, &xy, ssize, &idx, 0, _state);
esp = mlperrorsparsesubset(&network, &sparsexy, ssize, &idx, 0, _state);
seterrorflagdiff(err, e2, referencee, etol, escale, _state);
seterrorflagdiff(err, esp, referencee, etol, escale, _state);
mlpgradbatchsubset(&network, &xy, ssize, &idx, 0, &e2, &grad2, _state);
mlpgradbatchsparsesubset(&network, &sparsexy, ssize, &idx, 0, &esp, &gradsp, _state);
seterrorflagdiff(err, e2, referencee, etol, escale, _state);
seterrorflagdiff(err, esp, referencee, etol, escale, _state);
ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &grad2, wcount, gscale, _state),etol), __FILE__, __LINE__, "testmlpbaseunit.ap:1205");
ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &gradsp, wcount, gscale, _state),etol), __FILE__, __LINE__, "testmlpbaseunit.ap:1206");
mlpgradbatch(&network, &xy2, subsetsize, &referencee, &referenceg, _state);
e2 = mlperrorsubset(&network, &xy, ssize, &idx, subsetsize, _state);
esp = mlperrorsparsesubset(&network, &sparsexy, ssize, &idx, subsetsize, _state);
seterrorflagdiff(err, e2, referencee, etol, escale, _state);
seterrorflagdiff(err, esp, referencee, etol, escale, _state);
mlpgradbatchsubset(&network, &xy, ssize, &idx, subsetsize, &e2, &grad2, _state);
mlpgradbatchsparsesubset(&network, &sparsexy, ssize, &idx, subsetsize, &esp, &gradsp, _state);
seterrorflagdiff(err, e2, referencee, etol, escale, _state);
seterrorflagdiff(err, esp, referencee, etol, escale, _state);
ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &grad2, wcount, gscale, _state),etol), __FILE__, __LINE__, "testmlpbaseunit.ap:1218");
ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &gradsp, wcount, gscale, _state),etol), __FILE__, __LINE__, "testmlpbaseunit.ap:1219");
/*
* Test MLPGradNBatch() for many-element dataset:
* * generate random dataset XY
* * calculate "reference" error/gradient using MLPGrad(), which was tested in previous
* section and is assumed to work correctly
* * test results returned by MLPGradNBatch against reference ones
*/
ssize = sizemin+ae_randominteger(sizemax-sizemin+1, _state);
ae_matrix_set_length(&xy, ssize, nin+nout, _state);
for(i=0; i<=wcount-1; i++)
{
referenceg.ptr.p_double[i] = (double)(0);
}
referencee = (double)(0);
for(i=0; i<=ssize-1; i++)
{
for(j=0; j<=nin-1; j++)
{
x1.ptr.p_double[j] = 4*ae_randomreal(_state)-2;
}
ae_v_move(&xy.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,nin-1));
if( mlpissoftmax(&network, _state) )
{
for(j=0; j<=nout-1; j++)
{
y1.ptr.p_double[j] = (double)(0);
}
xy.ptr.pp_double[i][nin] = (double)(ae_randominteger(nout, _state));
y1.ptr.p_double[ae_round(xy.ptr.pp_double[i][nin], _state)] = (double)(1);
}
else
{
for(j=0; j<=nout-1; j++)
{
y1.ptr.p_double[j] = 4*ae_randomreal(_state)-2;
}
ae_v_move(&xy.ptr.pp_double[i][nin], 1, &y1.ptr.p_double[0], 1, ae_v_len(nin,nin+nout-1));
}
mlpgradn(&network, &x1, &y1, &v, &grad2, _state);
referencee = referencee+v;
ae_v_add(&referenceg.ptr.p_double[0], 1, &grad2.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
}
mlpgradnbatch(&network, &xy, ssize, &e2, &grad2, _state);
seterrorflagdiff(err, e2, referencee, etol, escale, _state);
ae_set_error_flag(err, ae_fp_greater(testmlpbaseunit_vectordiff(&referenceg, &grad2, wcount, gscale, _state),etol), __FILE__, __LINE__, "testmlpbaseunit.ap:1258");
}
ae_frame_leave(_state);
}
/*************************************************************************
Hessian functions test
*************************************************************************/
static void testmlpbaseunit_testhessian(ae_int_t nkind,
ae_int_t nin,
ae_int_t nhid1,
ae_int_t nhid2,
ae_int_t nout,
ae_int_t passcount,
ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
multilayerperceptron network;
ae_int_t hkind;
ae_int_t n1;
ae_int_t n2;
ae_int_t wcount;
double h;
double etol;
ae_int_t pass;
ae_int_t i;
ae_int_t j;
ae_int_t ssize;
double a1;
double a2;
ae_matrix xy;
ae_matrix h1;
ae_matrix h2;
ae_vector grad1;
ae_vector grad2;
ae_vector grad3;
ae_vector x;
ae_vector y;
ae_vector x1;
ae_vector x2;
ae_vector y1;
ae_vector y2;
double v;
double e1;
double e2;
double wprev;
ae_frame_make(_state, &_frame_block);
memset(&network, 0, sizeof(network));
memset(&xy, 0, sizeof(xy));
memset(&h1, 0, sizeof(h1));
memset(&h2, 0, sizeof(h2));
memset(&grad1, 0, sizeof(grad1));
memset(&grad2, 0, sizeof(grad2));
memset(&grad3, 0, sizeof(grad3));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&x1, 0, sizeof(x1));
memset(&x2, 0, sizeof(x2));
memset(&y1, 0, sizeof(y1));
memset(&y2, 0, sizeof(y2));
_multilayerperceptron_init(&network, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&h1, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&h2, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&grad1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&grad2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&grad3, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
ae_assert(passcount>=2, "PassCount<2!", _state);
a1 = (double)(0);
a2 = (double)(0);
if( nkind==2 )
{
a1 = 1000*ae_randomreal(_state)-500;
a2 = 2*ae_randomreal(_state)-1;
}
if( nkind==3 )
{
a1 = 1000*ae_randomreal(_state)-500;
a2 = a1+(2*ae_randominteger(2, _state)-1)*(0.1+0.9*ae_randomreal(_state));
}
testmlpbaseunit_createnetwork(&network, nkind, a1, a2, nin, nhid1, nhid2, nout, _state);
mlpproperties(&network, &n1, &n2, &wcount, _state);
h = 0.0001;
etol = 0.05;
/*
* Initialize
*/
ae_vector_set_length(&x, nin-1+1, _state);
ae_vector_set_length(&x1, nin-1+1, _state);
ae_vector_set_length(&x2, nin-1+1, _state);
ae_vector_set_length(&y, nout-1+1, _state);
ae_vector_set_length(&y1, nout-1+1, _state);
ae_vector_set_length(&y2, nout-1+1, _state);
ae_vector_set_length(&grad1, wcount-1+1, _state);
ae_vector_set_length(&grad2, wcount-1+1, _state);
ae_vector_set_length(&grad3, wcount-1+1, _state);
ae_matrix_set_length(&h1, wcount-1+1, wcount-1+1, _state);
ae_matrix_set_length(&h2, wcount-1+1, wcount-1+1, _state);
/*
* Process
*/
for(pass=1; pass<=passcount; pass++)
{
mlprandomizefull(&network, _state);
/*
* Test hessian calculation .
* E1 contains total error (calculated using MLPGrad/MLPGradN)
* Grad1 contains total gradient (calculated using MLPGrad/MLPGradN)
* H1 contains Hessian calculated using differences of gradients
*
* E2, Grad2 and H2 contains corresponing values calculated using MLPHessianBatch/MLPHessianNBatch
*/
for(hkind=0; hkind<=1; hkind++)
{
ssize = 1+ae_randominteger(10, _state);
ae_matrix_set_length(&xy, ssize-1+1, nin+nout-1+1, _state);
for(i=0; i<=wcount-1; i++)
{
grad1.ptr.p_double[i] = (double)(0);
}
for(i=0; i<=wcount-1; i++)
{
for(j=0; j<=wcount-1; j++)
{
h1.ptr.pp_double[i][j] = (double)(0);
}
}
e1 = (double)(0);
for(i=0; i<=ssize-1; i++)
{
/*
* X, Y
*/
for(j=0; j<=nin-1; j++)
{
x1.ptr.p_double[j] = 4*ae_randomreal(_state)-2;
}
ae_v_move(&xy.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,nin-1));
if( mlpissoftmax(&network, _state) )
{
for(j=0; j<=nout-1; j++)
{
y1.ptr.p_double[j] = (double)(0);
}
xy.ptr.pp_double[i][nin] = (double)(ae_randominteger(nout, _state));
y1.ptr.p_double[ae_round(xy.ptr.pp_double[i][nin], _state)] = (double)(1);
}
else
{
for(j=0; j<=nout-1; j++)
{
y1.ptr.p_double[j] = 4*ae_randomreal(_state)-2;
}
ae_v_move(&xy.ptr.pp_double[i][nin], 1, &y1.ptr.p_double[0], 1, ae_v_len(nin,nin+nout-1));
}
/*
* E1, Grad1
*/
if( hkind==0 )
{
mlpgrad(&network, &x1, &y1, &v, &grad2, _state);
}
else
{
mlpgradn(&network, &x1, &y1, &v, &grad2, _state);
}
e1 = e1+v;
ae_v_add(&grad1.ptr.p_double[0], 1, &grad2.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
/*
* H1
*/
for(j=0; j<=wcount-1; j++)
{
wprev = network.weights.ptr.p_double[j];
network.weights.ptr.p_double[j] = wprev-2*h;
if( hkind==0 )
{
mlpgrad(&network, &x1, &y1, &v, &grad2, _state);
}
else
{
mlpgradn(&network, &x1, &y1, &v, &grad2, _state);
}
network.weights.ptr.p_double[j] = wprev-h;
if( hkind==0 )
{
mlpgrad(&network, &x1, &y1, &v, &grad3, _state);
}
else
{
mlpgradn(&network, &x1, &y1, &v, &grad3, _state);
}
ae_v_subd(&grad2.ptr.p_double[0], 1, &grad3.ptr.p_double[0], 1, ae_v_len(0,wcount-1), 8);
network.weights.ptr.p_double[j] = wprev+h;
if( hkind==0 )
{
mlpgrad(&network, &x1, &y1, &v, &grad3, _state);
}
else
{
mlpgradn(&network, &x1, &y1, &v, &grad3, _state);
}
ae_v_addd(&grad2.ptr.p_double[0], 1, &grad3.ptr.p_double[0], 1, ae_v_len(0,wcount-1), 8);
network.weights.ptr.p_double[j] = wprev+2*h;
if( hkind==0 )
{
mlpgrad(&network, &x1, &y1, &v, &grad3, _state);
}
else
{
mlpgradn(&network, &x1, &y1, &v, &grad3, _state);
}
ae_v_sub(&grad2.ptr.p_double[0], 1, &grad3.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
v = 1/(12*h);
ae_v_addd(&h1.ptr.pp_double[j][0], 1, &grad2.ptr.p_double[0], 1, ae_v_len(0,wcount-1), v);
network.weights.ptr.p_double[j] = wprev;
}
}
if( hkind==0 )
{
mlphessianbatch(&network, &xy, ssize, &e2, &grad2, &h2, _state);
}
else
{
mlphessiannbatch(&network, &xy, ssize, &e2, &grad2, &h2, _state);
}
*err = *err||ae_fp_greater(ae_fabs(e1-e2, _state)/e1,etol);
for(i=0; i<=wcount-1; i++)
{
if( ae_fp_greater(ae_fabs(grad1.ptr.p_double[i], _state),1.0E-2) )
{
*err = *err||ae_fp_greater(ae_fabs((grad2.ptr.p_double[i]-grad1.ptr.p_double[i])/grad1.ptr.p_double[i], _state),etol);
}
else
{
*err = *err||ae_fp_greater(ae_fabs(grad2.ptr.p_double[i]-grad1.ptr.p_double[i], _state),etol);
}
}
for(i=0; i<=wcount-1; i++)
{
for(j=0; j<=wcount-1; j++)
{
if( ae_fp_greater(ae_fabs(h1.ptr.pp_double[i][j], _state),5.0E-2) )
{
*err = *err||ae_fp_greater(ae_fabs((h1.ptr.pp_double[i][j]-h2.ptr.pp_double[i][j])/h1.ptr.pp_double[i][j], _state),etol);
}
else
{
*err = *err||ae_fp_greater(ae_fabs(h2.ptr.pp_double[i][j]-h1.ptr.pp_double[i][j], _state),etol);
}
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Error functions (other than MLPError and MLPErrorN) test.
Network of type NKind is created, with NIn inputs, NHid1*NHid2 hidden
layers (one layer if NHid2=0), NOut outputs. PassCount random passes is
performed. Dataset has random size in [SizeMin,SizeMax].
*************************************************************************/
static void testmlpbaseunit_testerr(ae_int_t nkind,
ae_int_t nin,
ae_int_t nhid1,
ae_int_t nhid2,
ae_int_t nout,
ae_int_t passcount,
ae_int_t sizemin,
ae_int_t sizemax,
ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
multilayerperceptron network;
sparsematrix sparsexy;
ae_int_t n1;
ae_int_t n2;
ae_int_t wcount;
double etol;
double escale;
double a1;
double a2;
ae_int_t pass;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t ssize;
ae_int_t subsetsize;
ae_matrix xy;
ae_vector y;
ae_vector x1;
ae_vector y1;
ae_vector idx;
ae_vector dummy;
double refrmserror;
double refclserror;
double refrelclserror;
double refavgce;
double refavgerror;
double refavgrelerror;
ae_int_t avgrelcnt;
modelerrors allerrors;
ae_int_t nnmax;
ae_int_t dsmax;
double relclstolerance;
ae_frame_make(_state, &_frame_block);
memset(&network, 0, sizeof(network));
memset(&sparsexy, 0, sizeof(sparsexy));
memset(&xy, 0, sizeof(xy));
memset(&y, 0, sizeof(y));
memset(&x1, 0, sizeof(x1));
memset(&y1, 0, sizeof(y1));
memset(&idx, 0, sizeof(idx));
memset(&dummy, 0, sizeof(dummy));
memset(&allerrors, 0, sizeof(allerrors));
_multilayerperceptron_init(&network, _state, ae_true);
_sparsematrix_init(&sparsexy, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&idx, 0, DT_INT, _state, ae_true);
ae_vector_init(&dummy, 0, DT_INT, _state, ae_true);
_modelerrors_init(&allerrors, _state, ae_true);
a1 = (double)(0);
a2 = (double)(0);
if( nkind==2 )
{
a1 = 1000*ae_randomreal(_state)-500;
a2 = 2*ae_randomreal(_state)-1;
}
if( nkind==3 )
{
a1 = 1000*ae_randomreal(_state)-500;
a2 = a1+(2*ae_randominteger(2, _state)-1)*(0.1+0.9*ae_randomreal(_state));
}
testmlpbaseunit_createnetwork(&network, nkind, a1, a2, nin, nhid1, nhid2, nout, _state);
mlpproperties(&network, &n1, &n2, &wcount, _state);
etol = 1.0E-4;
escale = 1.0E-2;
/*
* Initialize
*/
ae_vector_set_length(&x1, nin, _state);
ae_vector_set_length(&y, nout, _state);
ae_vector_set_length(&y1, nout, _state);
/*
* Process
*/
for(pass=1; pass<=passcount; pass++)
{
/*
* Randomize network, then re-randomaze weights manually.
*
* NOTE: weights magnitude is chosen to be small, about 0.1,
* which allows us to avoid oversaturated network.
* In 10% of cases we use zero weights.
*/
mlprandomizefull(&network, _state);
if( ae_fp_less_eq(ae_randomreal(_state),0.1) )
{
for(i=0; i<=wcount-1; i++)
{
network.weights.ptr.p_double[i] = 0.0;
}
}
else
{
for(i=0; i<=wcount-1; i++)
{
network.weights.ptr.p_double[i] = 0.2*ae_randomreal(_state)-0.1;
}
}
/*
* Generate random dataset.
* Calculate reference errors.
*
* NOTE: about 10% of tests are performed with zero SSize
*/
ssize = sizemin+ae_randominteger(sizemax-sizemin+1, _state);
if( mlpissoftmax(&network, _state) )
{
ae_matrix_set_length(&xy, ae_maxint(ssize, 1, _state), nin+1, _state);
sparsecreate(ae_maxint(ssize, 1, _state), nin+1, 0, &sparsexy, _state);
}
else
{
ae_matrix_set_length(&xy, ae_maxint(ssize, 1, _state), nin+nout, _state);
sparsecreate(ae_maxint(ssize, 1, _state), nin+nout, 0, &sparsexy, _state);
}
refrmserror = 0.0;
refclserror = 0.0;
refavgce = 0.0;
refavgerror = 0.0;
refavgrelerror = 0.0;
avgrelcnt = 0;
for(i=0; i<=ssize-1; i++)
{
/*
* Fill I-th row
*/
for(j=0; j<=nin-1; j++)
{
x1.ptr.p_double[j] = 4*ae_randomreal(_state)-2;
sparseset(&sparsexy, i, j, x1.ptr.p_double[j], _state);
}
ae_v_move(&xy.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,nin-1));
if( mlpissoftmax(&network, _state) )
{
for(j=0; j<=nout-1; j++)
{
y1.ptr.p_double[j] = (double)(0);
}
xy.ptr.pp_double[i][nin] = (double)(ae_randominteger(nout, _state));
sparseset(&sparsexy, i, nin, xy.ptr.pp_double[i][nin], _state);
y1.ptr.p_double[ae_round(xy.ptr.pp_double[i][nin], _state)] = (double)(1);
}
else
{
for(j=0; j<=nout-1; j++)
{
y1.ptr.p_double[j] = 4*ae_randomreal(_state)-2;
sparseset(&sparsexy, i, nin+j, y1.ptr.p_double[j], _state);
}
ae_v_move(&xy.ptr.pp_double[i][nin], 1, &y1.ptr.p_double[0], 1, ae_v_len(nin,nin+nout-1));
}
/*
* Process
*/
mlpprocess(&network, &x1, &y, _state);
/*
* Update reference errors
*/
nnmax = 0;
if( mlpissoftmax(&network, _state) )
{
if( ae_fp_greater(y.ptr.p_double[ae_round(xy.ptr.pp_double[i][nin], _state)],(double)(0)) )
{
refavgce = refavgce+ae_log(1/y.ptr.p_double[ae_round(xy.ptr.pp_double[i][nin], _state)], _state);
}
else
{
refavgce = refavgce+ae_log(ae_maxrealnumber, _state);
}
}
if( mlpissoftmax(&network, _state) )
{
dsmax = ae_round(xy.ptr.pp_double[i][nin], _state);
}
else
{
dsmax = 0;
}
for(j=0; j<=nout-1; j++)
{
refrmserror = refrmserror+ae_sqr(y.ptr.p_double[j]-y1.ptr.p_double[j], _state);
refavgerror = refavgerror+ae_fabs(y.ptr.p_double[j]-y1.ptr.p_double[j], _state);
if( ae_fp_neq(y1.ptr.p_double[j],(double)(0)) )
{
refavgrelerror = refavgrelerror+ae_fabs(y.ptr.p_double[j]-y1.ptr.p_double[j], _state)/ae_fabs(y1.ptr.p_double[j], _state);
avgrelcnt = avgrelcnt+1;
}
if( ae_fp_greater(y.ptr.p_double[j],y.ptr.p_double[nnmax]) )
{
nnmax = j;
}
if( !mlpissoftmax(&network, _state)&&ae_fp_greater(y1.ptr.p_double[j],y1.ptr.p_double[dsmax]) )
{
dsmax = j;
}
}
if( nnmax!=dsmax )
{
refclserror = refclserror+1;
}
}
sparseconverttocrs(&sparsexy, _state);
if( ssize>0 )
{
refrmserror = ae_sqrt(refrmserror/(ssize*nout), _state);
refavgerror = refavgerror/(ssize*nout);
refrelclserror = refclserror/ssize;
refavgce = refavgce/(ssize*ae_log((double)(2), _state));
}
else
{
refrelclserror = 0.0;
}
if( avgrelcnt>0 )
{
refavgrelerror = refavgrelerror/avgrelcnt;
}
/*
* Test "continuous" errors on full dataset
*/
seterrorflagdiff(err, mlprmserror(&network, &xy, ssize, _state), refrmserror, etol, escale, _state);
seterrorflagdiff(err, mlpavgce(&network, &xy, ssize, _state), refavgce, etol, escale, _state);
seterrorflagdiff(err, mlpavgerror(&network, &xy, ssize, _state), refavgerror, etol, escale, _state);
seterrorflagdiff(err, mlpavgrelerror(&network, &xy, ssize, _state), refavgrelerror, etol, escale, _state);
seterrorflagdiff(err, mlprmserrorsparse(&network, &sparsexy, ssize, _state), refrmserror, etol, escale, _state);
seterrorflagdiff(err, mlpavgcesparse(&network, &sparsexy, ssize, _state), refavgce, etol, escale, _state);
seterrorflagdiff(err, mlpavgerrorsparse(&network, &sparsexy, ssize, _state), refavgerror, etol, escale, _state);
seterrorflagdiff(err, mlpavgrelerrorsparse(&network, &sparsexy, ssize, _state), refavgrelerror, etol, escale, _state);
mlpallerrorssubset(&network, &xy, ssize, &dummy, -1, &allerrors, _state);
seterrorflagdiff(err, allerrors.avgce, refavgce, etol, escale, _state);
seterrorflagdiff(err, allerrors.rmserror, refrmserror, etol, escale, _state);
seterrorflagdiff(err, allerrors.avgerror, refavgerror, etol, escale, _state);
seterrorflagdiff(err, allerrors.avgrelerror, refavgrelerror, etol, escale, _state);
mlpallerrorssparsesubset(&network, &sparsexy, ssize, &dummy, -1, &allerrors, _state);
seterrorflagdiff(err, allerrors.avgce, refavgce, etol, escale, _state);
seterrorflagdiff(err, allerrors.rmserror, refrmserror, etol, escale, _state);
seterrorflagdiff(err, allerrors.avgerror, refavgerror, etol, escale, _state);
seterrorflagdiff(err, allerrors.avgrelerror, refavgrelerror, etol, escale, _state);
/*
* Test errors on dataset given by subset.
* We perform only limited test for RMS error, assuming that either all errors
* are calculated correctly (subject to subset given by Idx) - or none of them.
*/
if( ssize>0 )
{
subsetsize = ae_randominteger(10, _state);
}
else
{
subsetsize = 0;
}
ae_vector_set_length(&idx, subsetsize, _state);
refrmserror = 0.0;
for(i=0; i<=subsetsize-1; i++)
{
k = ae_randominteger(ssize, _state);
idx.ptr.p_int[i] = k;
ae_v_move(&x1.ptr.p_double[0], 1, &xy.ptr.pp_double[k][0], 1, ae_v_len(0,nin-1));
if( mlpissoftmax(&network, _state) )
{
for(j=0; j<=nout-1; j++)
{
y1.ptr.p_double[j] = (double)(0);
}
y1.ptr.p_double[ae_round(xy.ptr.pp_double[k][nin], _state)] = (double)(1);
}
else
{
for(j=0; j<=nout-1; j++)
{
y1.ptr.p_double[j] = xy.ptr.pp_double[k][nin+j];
}
}
mlpprocess(&network, &x1, &y, _state);
for(j=0; j<=nout-1; j++)
{
refrmserror = refrmserror+ae_sqr(y.ptr.p_double[j]-y1.ptr.p_double[j], _state);
}
}
if( subsetsize>0 )
{
refrmserror = ae_sqrt(refrmserror/(subsetsize*nout), _state);
}
mlpallerrorssubset(&network, &xy, ssize, &idx, subsetsize, &allerrors, _state);
seterrorflagdiff(err, allerrors.rmserror, refrmserror, etol, escale, _state);
mlpallerrorssparsesubset(&network, &sparsexy, ssize, &idx, subsetsize, &allerrors, _state);
seterrorflagdiff(err, allerrors.rmserror, refrmserror, etol, escale, _state);
/*
* Test "discontinuous" error function.
* Even slight changes in the network output may force these functions
* to change by 1. So, we test them with relaxed criteria, corresponding to
* difference in classification of two samples.
*/
if( ssize>0 )
{
relclstolerance = 2.5/ssize;
ae_set_error_flag(err, ae_fp_greater(ae_fabs(mlpclserror(&network, &xy, ssize, _state)-refclserror, _state),ssize*relclstolerance), __FILE__, __LINE__, "testmlpbaseunit.ap:1728");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(mlprelclserror(&network, &xy, ssize, _state)-refrelclserror, _state),relclstolerance), __FILE__, __LINE__, "testmlpbaseunit.ap:1729");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(mlprelclserrorsparse(&network, &sparsexy, ssize, _state)-refrelclserror, _state),relclstolerance), __FILE__, __LINE__, "testmlpbaseunit.ap:1730");
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Special tests
*************************************************************************/
static void testmlpbaseunit_spectests(ae_bool* inferrors,
ae_bool* procerrors,
ae_bool* graderrors,
ae_bool* hesserrors,
ae_bool* errerrors,
ae_state *_state)
{
ae_frame _frame_block;
multilayerperceptron net;
ae_matrix xy;
double f;
ae_vector g;
ae_int_t i;
ae_frame_make(_state, &_frame_block);
memset(&net, 0, sizeof(net));
memset(&xy, 0, sizeof(xy));
memset(&g, 0, sizeof(g));
_multilayerperceptron_init(&net, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&g, 0, DT_REAL, _state, ae_true);
/*
* Special test for overflow in TanH:
* * create 1x1x1 linear network
* * create dataset with 1 item: [x, y] = [0, 1]
* * set network weights to [10000000, 10000000, 10000000, 10000000]
* * check that error function is finite
* * check that gradient is finite
*/
mlpcreate1(1, 1, 1, &net, _state);
ae_matrix_set_length(&xy, 1, 2, _state);
xy.ptr.pp_double[0][0] = (double)(0);
xy.ptr.pp_double[0][1] = 1.0;
for(i=0; i<=mlpgetweightscount(&net, _state)-1; i++)
{
net.weights.ptr.p_double[i] = 10000000.0;
}
mlpgradbatch(&net, &xy, 1, &f, &g, _state);
ae_set_error_flag(graderrors, !ae_isfinite(f, _state), __FILE__, __LINE__, "testmlpbaseunit.ap:1903");
ae_set_error_flag(graderrors, !ae_isfinite(mlperror(&net, &xy, 1, _state), _state), __FILE__, __LINE__, "testmlpbaseunit.ap:1904");
for(i=0; i<=mlpgetweightscount(&net, _state)-1; i++)
{
ae_set_error_flag(graderrors, !ae_isfinite(g.ptr.p_double[i], _state), __FILE__, __LINE__, "testmlpbaseunit.ap:1906");
}
/*
* Special test for overflow in SOFTMAX layer:
* * create 1x1x2 classifier network
* * create dataset with 1 item: [x, y] = [0, 1]
* * set network weights to [10000000, 10000000, 10000000, 10000000]
* * check that error function is finite
* * check that gradient is finite
*/
mlpcreatec1(1, 1, 2, &net, _state);
ae_matrix_set_length(&xy, 1, 2, _state);
xy.ptr.pp_double[0][0] = (double)(0);
xy.ptr.pp_double[0][1] = (double)(1);
for(i=0; i<=mlpgetweightscount(&net, _state)-1; i++)
{
net.weights.ptr.p_double[i] = 10000000.0;
}
mlpgradbatch(&net, &xy, 1, &f, &g, _state);
ae_set_error_flag(graderrors, !ae_isfinite(f, _state), __FILE__, __LINE__, "testmlpbaseunit.ap:1924");
ae_set_error_flag(graderrors, !ae_isfinite(mlperror(&net, &xy, 1, _state), _state), __FILE__, __LINE__, "testmlpbaseunit.ap:1925");
for(i=0; i<=mlpgetweightscount(&net, _state)-1; i++)
{
ae_set_error_flag(graderrors, !ae_isfinite(g.ptr.p_double[i], _state), __FILE__, __LINE__, "testmlpbaseunit.ap:1927");
}
ae_frame_leave(_state);
}
/*************************************************************************
The function test functions MLPGradBatchMasked and MLPGradBatchSparseMasked.
*************************************************************************/
static ae_bool testmlpbaseunit_testmlpgbsubset(ae_state *_state)
{
ae_frame _frame_block;
multilayerperceptron net;
ae_matrix a;
ae_matrix parta;
sparsematrix sa;
sparsematrix partsa;
ae_vector idx;
double e1;
double e2;
ae_vector grad1;
ae_vector grad2;
ae_int_t nin;
ae_int_t nout;
ae_int_t w;
ae_int_t wcount;
ae_int_t nhid1;
ae_int_t nhid2;
ae_int_t nkind;
double a1;
double a2;
ae_int_t n1;
ae_int_t n2;
ae_int_t ssize;
ae_int_t maxssize;
ae_int_t sbsize;
ae_int_t nvar;
ae_int_t variant;
ae_int_t i;
ae_int_t j;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&net, 0, sizeof(net));
memset(&a, 0, sizeof(a));
memset(&parta, 0, sizeof(parta));
memset(&sa, 0, sizeof(sa));
memset(&partsa, 0, sizeof(partsa));
memset(&idx, 0, sizeof(idx));
memset(&grad1, 0, sizeof(grad1));
memset(&grad2, 0, sizeof(grad2));
_multilayerperceptron_init(&net, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&parta, 0, 0, DT_REAL, _state, ae_true);
_sparsematrix_init(&sa, _state, ae_true);
_sparsematrix_init(&partsa, _state, ae_true);
ae_vector_init(&idx, 0, DT_INT, _state, ae_true);
ae_vector_init(&grad1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&grad2, 0, DT_REAL, _state, ae_true);
/*
* Variant:
* * 1 - there are all rows;
* * 2 - there are no one rows;
* * 3 - there are some random rows.
*/
nvar = 3;
maxssize = 96;
for(ssize=0; ssize<=maxssize; ssize++)
{
ae_vector_set_length(&idx, ssize, _state);
nkind = ae_randominteger(4, _state);
a1 = (double)(0);
a2 = (double)(0);
if( nkind==2 )
{
a1 = 1000*ae_randomreal(_state)-500;
a2 = 2*ae_randomreal(_state)-1;
}
if( nkind==3 )
{
a1 = 1000*ae_randomreal(_state)-500;
a2 = a1+(2*ae_randominteger(2, _state)-1)*(0.1+0.9*ae_randomreal(_state));
}
nin = ae_randominteger(20, _state)+1;
nhid1 = ae_randominteger(5, _state);
if( nhid1==0 )
{
nhid2 = 0;
}
else
{
nhid2 = ae_randominteger(5, _state);
}
nout = ae_randominteger(20, _state)+2;
testmlpbaseunit_createnetwork(&net, nkind, a1, a2, nin, nhid1, nhid2, nout, _state);
mlpproperties(&net, &n1, &n2, &wcount, _state);
if( mlpissoftmax(&net, _state) )
{
w = nin+1;
if( ssize>0 )
{
ae_matrix_set_length(&a, ssize, w, _state);
sparsecreate(ssize, w, ssize*w, &sa, _state);
}
else
{
ae_matrix_set_length(&a, 0, 0, _state);
sparsecreate(1, 1, 0, &sa, _state);
}
for(i=0; i<=ssize-1; i++)
{
for(j=0; j<=w-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state);
}
}
for(i=0; i<=ssize-1; i++)
{
a.ptr.pp_double[i][nin] = (double)(ae_randominteger(nout, _state));
sparseset(&sa, i, nin, a.ptr.pp_double[i][nin], _state);
}
}
else
{
w = nin+nout;
if( ssize>0 )
{
ae_matrix_set_length(&a, ssize, w, _state);
sparsecreate(ssize, w, ssize*w, &sa, _state);
}
else
{
ae_matrix_set_length(&a, 0, 0, _state);
sparsecreate(1, 1, 0, &sa, _state);
}
for(i=0; i<=ssize-1; i++)
{
for(j=0; j<=w-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state);
}
}
}
sparseconverttocrs(&sa, _state);
for(variant=1; variant<=nvar; variant++)
{
sbsize = -1;
if( variant==1 )
{
sbsize = ssize;
for(i=0; i<=sbsize-1; i++)
{
idx.ptr.p_int[i] = i;
}
}
if( variant==2 )
{
sbsize = 0;
}
if( variant==3 )
{
if( ssize==0 )
{
sbsize = 0;
}
else
{
sbsize = ae_randominteger(ssize, _state);
}
for(i=0; i<=sbsize-1; i++)
{
idx.ptr.p_int[i] = ae_randominteger(ssize, _state);
}
}
ae_assert(sbsize>=0, "mlpbase test: integrity check failed", _state);
if( sbsize!=0 )
{
ae_matrix_set_length(&parta, sbsize, w, _state);
sparsecreate(sbsize, w, sbsize*w, &partsa, _state);
}
else
{
ae_matrix_set_length(&parta, 0, 0, _state);
sparsecreate(1, 1, 0, &partsa, _state);
}
for(i=0; i<=sbsize-1; i++)
{
ae_v_move(&parta.ptr.pp_double[i][0], 1, &a.ptr.pp_double[idx.ptr.p_int[i]][0], 1, ae_v_len(0,w-1));
for(j=0; j<=w-1; j++)
{
sparseset(&partsa, i, j, parta.ptr.pp_double[i][j], _state);
}
}
sparseconverttocrs(&partsa, _state);
mlpgradbatch(&net, &parta, sbsize, &e1, &grad1, _state);
mlpgradbatchsubset(&net, &a, ssize, &idx, sbsize, &e2, &grad2, _state);
/*
* Test for dense matrix
*/
if( ae_fp_greater(ae_fabs(e1-e2, _state),1.0E-6) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=wcount-1; i++)
{
if( ae_fp_greater(ae_fabs(grad1.ptr.p_double[i]-grad2.ptr.p_double[i], _state),1.0E-6) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
/*
* Test for sparse matrix
*/
mlpgradbatchsparse(&net, &partsa, sbsize, &e1, &grad1, _state);
mlpgradbatchsparsesubset(&net, &sa, ssize, &idx, sbsize, &e2, &grad2, _state);
if( ae_fp_greater(ae_fabs(e1-e2, _state),1.0E-6) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=wcount-1; i++)
{
if( ae_fp_greater(ae_fabs(grad1.ptr.p_double[i]-grad2.ptr.p_double[i], _state),1.0E-6) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
static void testldaunit_gensimpleset(ae_int_t nfeatures,
ae_int_t nclasses,
ae_int_t nsamples,
ae_int_t axis,
/* Real */ ae_matrix* xy,
ae_state *_state);
static void testldaunit_gendeg1set(ae_int_t nfeatures,
ae_int_t nclasses,
ae_int_t nsamples,
ae_int_t axis,
/* Real */ ae_matrix* xy,
ae_state *_state);
static double testldaunit_generatenormal(double mean,
double sigma,
ae_state *_state);
static ae_bool testldaunit_testwn(/* Real */ ae_matrix* xy,
/* Real */ ae_matrix* wn,
ae_int_t ns,
ae_int_t nf,
ae_int_t nc,
ae_int_t ndeg,
ae_state *_state);
static double testldaunit_calcj(ae_int_t nf,
/* Real */ ae_matrix* st,
/* Real */ ae_matrix* sw,
/* Real */ ae_vector* w,
double* p,
double* q,
ae_state *_state);
static void testldaunit_fishers(/* Real */ ae_matrix* xy,
ae_int_t npoints,
ae_int_t nfeatures,
ae_int_t nclasses,
/* Real */ ae_matrix* st,
/* Real */ ae_matrix* sw,
ae_state *_state);
ae_bool testlda(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t maxnf;
ae_int_t maxns;
ae_int_t maxnc;
ae_int_t passcount;
ae_bool ldanerrors;
ae_bool lda1errors;
ae_bool waserrors;
ae_int_t nf;
ae_int_t nc;
ae_int_t ns;
ae_int_t i;
ae_int_t info;
ae_int_t pass;
ae_int_t axis;
ae_matrix xy;
ae_matrix wn;
ae_vector w1;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
memset(&wn, 0, sizeof(wn));
memset(&w1, 0, sizeof(w1));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&wn, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w1, 0, DT_REAL, _state, ae_true);
/*
* Primary settings
*/
maxnf = 10;
maxns = 1000;
maxnc = 5;
passcount = 1;
waserrors = ae_false;
ldanerrors = ae_false;
lda1errors = ae_false;
/*
* General tests
*/
for(nf=1; nf<=maxnf; nf++)
{
for(nc=2; nc<=maxnc; nc++)
{
for(pass=1; pass<=passcount; pass++)
{
/*
* Simple test for LDA-N/LDA-1
*/
axis = ae_randominteger(nf, _state);
ns = maxns/2+ae_randominteger(maxns/2, _state);
testldaunit_gensimpleset(nf, nc, ns, axis, &xy, _state);
fisherldan(&xy, ns, nf, nc, &info, &wn, _state);
if( info!=1 )
{
ldanerrors = ae_true;
continue;
}
ldanerrors = ldanerrors||!testldaunit_testwn(&xy, &wn, ns, nf, nc, 0, _state);
ldanerrors = ldanerrors||ae_fp_less_eq(ae_fabs(wn.ptr.pp_double[axis][0], _state),0.75);
fisherlda(&xy, ns, nf, nc, &info, &w1, _state);
for(i=0; i<=nf-1; i++)
{
lda1errors = lda1errors||ae_fp_neq(w1.ptr.p_double[i],wn.ptr.pp_double[i][0]);
}
/*
* Degenerate test for LDA-N
*/
if( nf>=3 )
{
ns = maxns/2+ae_randominteger(maxns/2, _state);
/*
* there are two duplicate features,
* axis is oriented along non-duplicate feature
*/
axis = ae_randominteger(nf-2, _state);
testldaunit_gendeg1set(nf, nc, ns, axis, &xy, _state);
fisherldan(&xy, ns, nf, nc, &info, &wn, _state);
if( info!=2 )
{
ldanerrors = ae_true;
continue;
}
ldanerrors = ldanerrors||ae_fp_less_eq(wn.ptr.pp_double[axis][0],0.75);
fisherlda(&xy, ns, nf, nc, &info, &w1, _state);
for(i=0; i<=nf-1; i++)
{
lda1errors = lda1errors||ae_fp_neq(w1.ptr.p_double[i],wn.ptr.pp_double[i][0]);
}
}
}
}
}
/*
* Final report
*/
waserrors = ldanerrors||lda1errors;
if( !silent )
{
printf("LDA TEST\n");
printf("FISHER LDA-N: ");
if( !ldanerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("FISHER LDA-1: ");
if( !lda1errors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST SUMMARY: FAILED\n");
}
else
{
printf("TEST SUMMARY: PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Generates 'simple' set - a sequence of unit 'balls' at (0,0), (1,0), (2,0)
and so on.
*************************************************************************/
static void testldaunit_gensimpleset(ae_int_t nfeatures,
ae_int_t nclasses,
ae_int_t nsamples,
ae_int_t axis,
/* Real */ ae_matrix* xy,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_int_t c;
ae_matrix_clear(xy);
ae_assert(axis>=0&&axisptr.pp_double[i][j] = testldaunit_generatenormal(0.0, 1.0, _state);
}
c = i%nclasses;
xy->ptr.pp_double[i][axis] = xy->ptr.pp_double[i][axis]+c;
xy->ptr.pp_double[i][nfeatures] = (double)(c);
}
}
/*************************************************************************
Generates 'degenerate' set #1.
NFeatures>=3.
*************************************************************************/
static void testldaunit_gendeg1set(ae_int_t nfeatures,
ae_int_t nclasses,
ae_int_t nsamples,
ae_int_t axis,
/* Real */ ae_matrix* xy,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_int_t c;
ae_matrix_clear(xy);
ae_assert(axis>=0&&axis=3, "GenDeg1Set: wrong NFeatures!", _state);
ae_matrix_set_length(xy, nsamples-1+1, nfeatures+1, _state);
if( axis>=nfeatures-2 )
{
axis = nfeatures-3;
}
for(i=0; i<=nsamples-1; i++)
{
for(j=0; j<=nfeatures-2; j++)
{
xy->ptr.pp_double[i][j] = testldaunit_generatenormal(0.0, 1.0, _state);
}
xy->ptr.pp_double[i][nfeatures-1] = xy->ptr.pp_double[i][nfeatures-2];
c = i%nclasses;
xy->ptr.pp_double[i][axis] = xy->ptr.pp_double[i][axis]+c;
xy->ptr.pp_double[i][nfeatures] = (double)(c);
}
}
/*************************************************************************
Normal random number
*************************************************************************/
static double testldaunit_generatenormal(double mean,
double sigma,
ae_state *_state)
{
double u;
double v;
double sum;
double result;
result = mean;
for(;;)
{
u = (2*ae_randominteger(2, _state)-1)*ae_randomreal(_state);
v = (2*ae_randominteger(2, _state)-1)*ae_randomreal(_state);
sum = u*u+v*v;
if( ae_fp_less(sum,(double)(1))&&ae_fp_greater(sum,(double)(0)) )
{
sum = ae_sqrt(-2*ae_log(sum, _state)/sum, _state);
result = sigma*u*sum+mean;
break;
}
}
return result;
}
/*************************************************************************
Tests WN for correctness
*************************************************************************/
static ae_bool testldaunit_testwn(/* Real */ ae_matrix* xy,
/* Real */ ae_matrix* wn,
ae_int_t ns,
ae_int_t nf,
ae_int_t nc,
ae_int_t ndeg,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix st;
ae_matrix sw;
ae_matrix a;
ae_matrix z;
ae_vector tx;
ae_vector jp;
ae_vector jq;
ae_vector work;
ae_int_t i;
ae_int_t j;
double v;
double wprev;
double tol;
double p;
double q;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&st, 0, sizeof(st));
memset(&sw, 0, sizeof(sw));
memset(&a, 0, sizeof(a));
memset(&z, 0, sizeof(z));
memset(&tx, 0, sizeof(tx));
memset(&jp, 0, sizeof(jp));
memset(&jq, 0, sizeof(jq));
memset(&work, 0, sizeof(work));
ae_matrix_init(&st, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&sw, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&jp, 0, DT_REAL, _state, ae_true);
ae_vector_init(&jq, 0, DT_REAL, _state, ae_true);
ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
tol = (double)(10000);
result = ae_true;
testldaunit_fishers(xy, ns, nf, nc, &st, &sw, _state);
/*
* Test for decreasing of J
*/
ae_vector_set_length(&tx, nf-1+1, _state);
ae_vector_set_length(&jp, nf-1+1, _state);
ae_vector_set_length(&jq, nf-1+1, _state);
for(j=0; j<=nf-1; j++)
{
ae_v_move(&tx.ptr.p_double[0], 1, &wn->ptr.pp_double[0][j], wn->stride, ae_v_len(0,nf-1));
v = testldaunit_calcj(nf, &st, &sw, &tx, &p, &q, _state);
jp.ptr.p_double[j] = p;
jq.ptr.p_double[j] = q;
}
for(i=1; i<=nf-1-ndeg; i++)
{
result = result&&ae_fp_greater_eq(jp.ptr.p_double[i-1]/jq.ptr.p_double[i-1],(1-tol*ae_machineepsilon)*jp.ptr.p_double[i]/jq.ptr.p_double[i]);
}
for(i=nf-1-ndeg+1; i<=nf-1; i++)
{
result = result&&ae_fp_less_eq(jp.ptr.p_double[i],tol*ae_machineepsilon*jp.ptr.p_double[0]);
}
/*
* Test for J optimality
*/
ae_v_move(&tx.ptr.p_double[0], 1, &wn->ptr.pp_double[0][0], wn->stride, ae_v_len(0,nf-1));
v = testldaunit_calcj(nf, &st, &sw, &tx, &p, &q, _state);
for(i=0; i<=nf-1; i++)
{
wprev = tx.ptr.p_double[i];
tx.ptr.p_double[i] = wprev+0.01;
result = result&&ae_fp_greater_eq(v,(1-tol*ae_machineepsilon)*testldaunit_calcj(nf, &st, &sw, &tx, &p, &q, _state));
tx.ptr.p_double[i] = wprev-0.01;
result = result&&ae_fp_greater_eq(v,(1-tol*ae_machineepsilon)*testldaunit_calcj(nf, &st, &sw, &tx, &p, &q, _state));
tx.ptr.p_double[i] = wprev;
}
/*
* Test for linear independence of W
*/
ae_vector_set_length(&work, nf+1, _state);
ae_matrix_set_length(&a, nf-1+1, nf-1+1, _state);
matrixmatrixmultiply(wn, 0, nf-1, 0, nf-1, ae_false, wn, 0, nf-1, 0, nf-1, ae_true, 1.0, &a, 0, nf-1, 0, nf-1, 0.0, &work, _state);
if( smatrixevd(&a, nf, 1, ae_true, &tx, &z, _state) )
{
result = result&&ae_fp_greater(tx.ptr.p_double[0],tx.ptr.p_double[nf-1]*1000*ae_machineepsilon);
}
/*
* Test for other properties
*/
for(j=0; j<=nf-1; j++)
{
v = ae_v_dotproduct(&wn->ptr.pp_double[0][j], wn->stride, &wn->ptr.pp_double[0][j], wn->stride, ae_v_len(0,nf-1));
v = ae_sqrt(v, _state);
result = result&&ae_fp_less_eq(ae_fabs(v-1, _state),1000*ae_machineepsilon);
v = (double)(0);
for(i=0; i<=nf-1; i++)
{
v = v+wn->ptr.pp_double[i][j];
}
result = result&&ae_fp_greater_eq(v,(double)(0));
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Calculates J
*************************************************************************/
static double testldaunit_calcj(ae_int_t nf,
/* Real */ ae_matrix* st,
/* Real */ ae_matrix* sw,
/* Real */ ae_vector* w,
double* p,
double* q,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector tx;
ae_int_t i;
double v;
double result;
ae_frame_make(_state, &_frame_block);
memset(&tx, 0, sizeof(tx));
*p = 0;
*q = 0;
ae_vector_init(&tx, 0, DT_REAL, _state, ae_true);
ae_vector_set_length(&tx, nf-1+1, _state);
for(i=0; i<=nf-1; i++)
{
v = ae_v_dotproduct(&st->ptr.pp_double[i][0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,nf-1));
tx.ptr.p_double[i] = v;
}
v = ae_v_dotproduct(&w->ptr.p_double[0], 1, &tx.ptr.p_double[0], 1, ae_v_len(0,nf-1));
*p = v;
for(i=0; i<=nf-1; i++)
{
v = ae_v_dotproduct(&sw->ptr.pp_double[i][0], 1, &w->ptr.p_double[0], 1, ae_v_len(0,nf-1));
tx.ptr.p_double[i] = v;
}
v = ae_v_dotproduct(&w->ptr.p_double[0], 1, &tx.ptr.p_double[0], 1, ae_v_len(0,nf-1));
*q = v;
result = *p/(*q);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Calculates ST/SW
*************************************************************************/
static void testldaunit_fishers(/* Real */ ae_matrix* xy,
ae_int_t npoints,
ae_int_t nfeatures,
ae_int_t nclasses,
/* Real */ ae_matrix* st,
/* Real */ ae_matrix* sw,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
ae_vector c;
ae_vector mu;
ae_matrix muc;
ae_vector nc;
ae_vector tf;
ae_vector work;
ae_frame_make(_state, &_frame_block);
memset(&c, 0, sizeof(c));
memset(&mu, 0, sizeof(mu));
memset(&muc, 0, sizeof(muc));
memset(&nc, 0, sizeof(nc));
memset(&tf, 0, sizeof(tf));
memset(&work, 0, sizeof(work));
ae_matrix_clear(st);
ae_matrix_clear(sw);
ae_vector_init(&c, 0, DT_INT, _state, ae_true);
ae_vector_init(&mu, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&muc, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&nc, 0, DT_INT, _state, ae_true);
ae_vector_init(&tf, 0, DT_REAL, _state, ae_true);
ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
/*
* Prepare temporaries
*/
ae_vector_set_length(&tf, nfeatures-1+1, _state);
ae_vector_set_length(&work, nfeatures+1, _state);
/*
* Convert class labels from reals to integers (just for convenience)
*/
ae_vector_set_length(&c, npoints-1+1, _state);
for(i=0; i<=npoints-1; i++)
{
c.ptr.p_int[i] = ae_round(xy->ptr.pp_double[i][nfeatures], _state);
}
/*
* Calculate class sizes and means
*/
ae_vector_set_length(&mu, nfeatures-1+1, _state);
ae_matrix_set_length(&muc, nclasses-1+1, nfeatures-1+1, _state);
ae_vector_set_length(&nc, nclasses-1+1, _state);
for(j=0; j<=nfeatures-1; j++)
{
mu.ptr.p_double[j] = (double)(0);
}
for(i=0; i<=nclasses-1; i++)
{
nc.ptr.p_int[i] = 0;
for(j=0; j<=nfeatures-1; j++)
{
muc.ptr.pp_double[i][j] = (double)(0);
}
}
for(i=0; i<=npoints-1; i++)
{
ae_v_add(&mu.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nfeatures-1));
ae_v_add(&muc.ptr.pp_double[c.ptr.p_int[i]][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nfeatures-1));
nc.ptr.p_int[c.ptr.p_int[i]] = nc.ptr.p_int[c.ptr.p_int[i]]+1;
}
for(i=0; i<=nclasses-1; i++)
{
v = (double)1/(double)nc.ptr.p_int[i];
ae_v_muld(&muc.ptr.pp_double[i][0], 1, ae_v_len(0,nfeatures-1), v);
}
v = (double)1/(double)npoints;
ae_v_muld(&mu.ptr.p_double[0], 1, ae_v_len(0,nfeatures-1), v);
/*
* Create ST matrix
*/
ae_matrix_set_length(st, nfeatures-1+1, nfeatures-1+1, _state);
for(i=0; i<=nfeatures-1; i++)
{
for(j=0; j<=nfeatures-1; j++)
{
st->ptr.pp_double[i][j] = (double)(0);
}
}
for(k=0; k<=npoints-1; k++)
{
ae_v_move(&tf.ptr.p_double[0], 1, &xy->ptr.pp_double[k][0], 1, ae_v_len(0,nfeatures-1));
ae_v_sub(&tf.ptr.p_double[0], 1, &mu.ptr.p_double[0], 1, ae_v_len(0,nfeatures-1));
for(i=0; i<=nfeatures-1; i++)
{
v = tf.ptr.p_double[i];
ae_v_addd(&st->ptr.pp_double[i][0], 1, &tf.ptr.p_double[0], 1, ae_v_len(0,nfeatures-1), v);
}
}
/*
* Create SW matrix
*/
ae_matrix_set_length(sw, nfeatures-1+1, nfeatures-1+1, _state);
for(i=0; i<=nfeatures-1; i++)
{
for(j=0; j<=nfeatures-1; j++)
{
sw->ptr.pp_double[i][j] = (double)(0);
}
}
for(k=0; k<=npoints-1; k++)
{
ae_v_move(&tf.ptr.p_double[0], 1, &xy->ptr.pp_double[k][0], 1, ae_v_len(0,nfeatures-1));
ae_v_sub(&tf.ptr.p_double[0], 1, &muc.ptr.pp_double[c.ptr.p_int[k]][0], 1, ae_v_len(0,nfeatures-1));
for(i=0; i<=nfeatures-1; i++)
{
v = tf.ptr.p_double[i];
ae_v_addd(&sw->ptr.pp_double[i][0], 1, &tf.ptr.p_double[0], 1, ae_v_len(0,nfeatures-1), v);
}
}
ae_frame_leave(_state);
}
static void testssaunit_testgeneral(ae_bool* errorflag, ae_state *_state);
static void testssaunit_testspecial(ae_bool* errorflag, ae_state *_state);
ae_bool testssa(ae_bool silent, ae_state *_state)
{
ae_bool specerrors;
ae_bool generrors;
ae_bool wereerrors;
ae_bool result;
specerrors = ae_false;
generrors = ae_false;
testssaunit_testspecial(&specerrors, _state);
testssaunit_testgeneral(&generrors, _state);
/*
* Final report
*/
wereerrors = specerrors||generrors;
if( !silent )
{
printf("SSA TEST\n");
printf("* GENERAL TEST SUITE ");
if( !generrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* SPECIAL CASES ");
if( !specerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( wereerrors )
{
printf("TEST SUMMARY: FAILED\n");
}
else
{
printf("TEST SUMMARY: PASSED\n");
}
printf("\n\n");
}
result = !wereerrors;
return result;
}
/*************************************************************************
This function tests SSA on several general purpose analysis/prediction
problems.
On failure sets ErrorFlag, on success it is untouched.
*************************************************************************/
static void testssaunit_testgeneral(ae_bool* errorflag, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
double vv;
ae_int_t pass;
ssamodel state;
ssamodel state2;
ae_int_t ntracks;
ae_int_t windowwidth;
ae_int_t nlasttracklen;
ae_int_t nzeros;
ae_int_t nlinear;
double sinefreq;
double sineoffs;
double sineamp;
ae_int_t windowwidth2;
ae_int_t nbasis;
ae_int_t nbasis2;
ae_int_t ninitial;
ae_vector x;
ae_vector x2;
ae_vector trend;
ae_vector noise;
ae_vector sv;
ae_vector sv2;
ae_vector tmp0;
ae_vector trend2;
ae_vector noise2;
ae_int_t algotype;
ae_int_t nticks;
ae_int_t nnoise;
ae_int_t navg;
ae_matrix a;
ae_matrix a2;
ae_matrix b;
double tol;
ae_int_t datalen;
ae_int_t forecastlen;
ae_int_t mlimit;
hqrndstate rs;
ae_int_t passcount;
double skipprob;
ae_frame_make(_state, &_frame_block);
memset(&state, 0, sizeof(state));
memset(&state2, 0, sizeof(state2));
memset(&x, 0, sizeof(x));
memset(&x2, 0, sizeof(x2));
memset(&trend, 0, sizeof(trend));
memset(&noise, 0, sizeof(noise));
memset(&sv, 0, sizeof(sv));
memset(&sv2, 0, sizeof(sv2));
memset(&tmp0, 0, sizeof(tmp0));
memset(&trend2, 0, sizeof(trend2));
memset(&noise2, 0, sizeof(noise2));
memset(&a, 0, sizeof(a));
memset(&a2, 0, sizeof(a2));
memset(&b, 0, sizeof(b));
memset(&rs, 0, sizeof(rs));
_ssamodel_init(&state, _state, ae_true);
_ssamodel_init(&state2, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&trend, 0, DT_REAL, _state, ae_true);
ae_vector_init(&noise, 0, DT_REAL, _state, ae_true);
ae_vector_init(&sv, 0, DT_REAL, _state, ae_true);
ae_vector_init(&sv2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&trend2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&noise2, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
/*
* Initialize RNG, test pass count and skip probability.
*
* When we perform several sequential tests on the same model, we may
* skip some of them with probability SkipProb in order to make sure
* that no carry-over effect is observed between tests.
*/
hqrndrandomize(&rs, _state);
passcount = 500;
skipprob = 0.50;
/*
* Iterate over several algorithm types.
* Algorithms unsupported by tests are skipped within tests.
*/
for(algotype=1; algotype<=3; algotype++)
{
/*
* Test that on perfectly constant dataset SSA correctly predicts
* perfectly constant trend. Additionally test that analysis phase
* correctly returns nearly-zero noise and nearly-constant trend.
*
* Dataset is a one/few sequences with different constants; top-1
* algorithm is used (or precomputed unit-normalized vector of 1's).
*/
for(pass=1; pass<=passcount; pass++)
{
nlasttracklen = -9999999;
ntracks = 1+hqrnduniformi(&rs, 3, _state);
windowwidth = 2+hqrnduniformi(&rs, 3, _state);
ssacreate(&state, _state);
ssasetwindow(&state, windowwidth, _state);
for(k=0; k<=ntracks-1; k++)
{
nlasttracklen = windowwidth+hqrnduniformi(&rs, windowwidth, _state);
v = hqrndnormal(&rs, _state);
ae_vector_set_length(&x, nlasttracklen, _state);
for(i=0; i<=nlasttracklen-1; i++)
{
x.ptr.p_double[i] = v;
}
ssaaddsequence(&state, &x, nlasttracklen, _state);
}
if( algotype==1 )
{
ae_matrix_set_length(&b, windowwidth, 1, _state);
for(i=0; i<=windowwidth-1; i++)
{
b.ptr.pp_double[i][0] = 1/ae_sqrt((double)(windowwidth), _state);
}
ssasetalgoprecomputed(&state, &b, windowwidth, 1, _state);
}
else
{
if( algotype==2 )
{
ssasetalgotopkdirect(&state, 1, _state);
}
else
{
if( algotype==3 )
{
ssasetalgotopkrealtime(&state, 1, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
tol = 1.0E-6;
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
ssaanalyzelastwindow(&state, &trend, &noise, &nticks, _state);
ae_set_error_flag(errorflag, nticks!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:143");
ae_set_error_flag(errorflag, noise.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:144");
ae_set_error_flag(errorflag, trend.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:145");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=windowwidth-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[nlasttracklen+i-windowwidth], _state),tol), __FILE__, __LINE__, "testssaunit.ap:150");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:151");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
ssaanalyzelast(&state, nlasttracklen, &trend, &noise, _state);
ae_set_error_flag(errorflag, noise.cnt!=nlasttracklen, __FILE__, __LINE__, "testssaunit.ap:157");
ae_set_error_flag(errorflag, trend.cnt!=nlasttracklen, __FILE__, __LINE__, "testssaunit.ap:158");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=nlasttracklen-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:163");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:164");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nticks = 1+hqrnduniformi(&rs, 2*windowwidth, _state);
ae_vector_set_length(&trend, 0, _state);
ssaforecastlast(&state, nticks, &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:172");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=trend.cnt-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[nlasttracklen-1], _state),tol), __FILE__, __LINE__, "testssaunit.ap:176");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nticks = 1+hqrnduniformi(&rs, 2*windowwidth, _state);
navg = 1+hqrnduniformi(&rs, windowwidth+3, _state);
ae_vector_set_length(&trend, 0, _state);
ssaforecastavglast(&state, navg, nticks, &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:184");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=trend.cnt-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[nlasttracklen-1], _state),tol), __FILE__, __LINE__, "testssaunit.ap:188");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
datalen = windowwidth+hqrnduniformi(&rs, 10, _state);
forecastlen = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&x, datalen, _state);
x.ptr.p_double[0] = hqrndnormal(&rs, _state);
for(i=1; i<=datalen-1; i++)
{
x.ptr.p_double[i] = x.ptr.p_double[i-1];
}
ae_vector_set_length(&trend, 0, _state);
ssaforecastsequence(&state, &x, datalen, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=forecastlen, __FILE__, __LINE__, "testssaunit.ap:200");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=forecastlen-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[datalen-1], _state),tol), __FILE__, __LINE__, "testssaunit.ap:204");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
datalen = windowwidth+hqrnduniformi(&rs, 10, _state);
navg = 1+hqrnduniformi(&rs, windowwidth+3, _state);
forecastlen = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&x, datalen, _state);
x.ptr.p_double[0] = hqrndnormal(&rs, _state);
for(i=1; i<=datalen-1; i++)
{
x.ptr.p_double[i] = x.ptr.p_double[i-1];
}
ae_vector_set_length(&trend, 0, _state);
ssaforecastavgsequence(&state, &x, datalen, navg, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=forecastlen, __FILE__, __LINE__, "testssaunit.ap:217");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=forecastlen-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[datalen-1], _state),tol), __FILE__, __LINE__, "testssaunit.ap:221");
}
}
}
/*
* Test that on specially designed linear dataset SSA correctly
* predicts perfectly linear trend. Additionally test that analysis
* phase correctly returns nearly-zero noise and nearly-linear trend.
* Also test that correct basis vectors are returned.
*
* Dataset consists of many WindowWidth-sized (exactly) sequences with
* linear trend. Trend coefficients vary accross sequences. Top-2
* algorithm is used (or precomputed unit-normalized linear trend basis).
*
* NOTE: this test requires NTracks>=2, WindowWidth>=3 and TopK=2 to work;
* however, in order to improve numerical properties (diversity among
* samples, different slopes and offsets) we set NTracks to be
* at least 5.
*
* NOTE: one more version of this test verifies scaling properties
* by solving larger task (WindowWidth=100, NTracks=5,
* TrackLen=2*WindowWidth). This version makes just 5 checks because
* of higher cost.
*/
for(pass=1; pass<=passcount; pass++)
{
ntracks = 5+hqrnduniformi(&rs, 10, _state);
windowwidth = 3+hqrnduniformi(&rs, 3, _state);
ssacreate(&state, _state);
ssasetwindow(&state, windowwidth, _state);
ae_vector_set_length(&x, windowwidth, _state);
for(k=0; k<=ntracks-1; k++)
{
v = hqrndnormal(&rs, _state);
x.ptr.p_double[0] = hqrndnormal(&rs, _state);
for(i=1; i<=windowwidth-1; i++)
{
x.ptr.p_double[i] = x.ptr.p_double[i-1]+v;
}
ssaaddsequence(&state, &x, windowwidth, _state);
}
if( algotype==1 )
{
ae_matrix_set_length(&b, windowwidth, 2, _state);
v = 0.0;
for(i=0; i<=windowwidth-1; i++)
{
b.ptr.pp_double[i][0] = 1/ae_sqrt((double)(windowwidth), _state);
b.ptr.pp_double[i][1] = (double)(i);
v = v+(double)i/(double)windowwidth;
}
vv = 0.0;
for(i=0; i<=windowwidth-1; i++)
{
b.ptr.pp_double[i][1] = b.ptr.pp_double[i][1]-v;
vv = vv+ae_sqr(b.ptr.pp_double[i][1], _state);
}
for(i=0; i<=windowwidth-1; i++)
{
b.ptr.pp_double[i][1] = b.ptr.pp_double[i][1]/ae_sqrt(vv, _state);
}
ssasetalgoprecomputed(&state, &b, windowwidth, 2, _state);
}
else
{
if( algotype==2 )
{
ssasetalgotopkdirect(&state, 2, _state);
}
else
{
if( algotype==3 )
{
ssasetalgotopkrealtime(&state, 2, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
tol = 1.0E-6;
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
/*
* Basis vectors must be linear/constant functions
*/
ssagetbasis(&state, &a, &sv, &windowwidth2, &nbasis, _state);
ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:293");
ae_set_error_flag(errorflag, nbasis!=2, __FILE__, __LINE__, "testssaunit.ap:294");
ae_set_error_flag(errorflag, a.cols!=nbasis, __FILE__, __LINE__, "testssaunit.ap:295");
ae_set_error_flag(errorflag, a.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:296");
ae_set_error_flag(errorflag, sv.cnt!=nbasis, __FILE__, __LINE__, "testssaunit.ap:297");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(j=0; j<=nbasis-1; j++)
{
v = a.ptr.pp_double[1][j]-a.ptr.pp_double[0][j];
for(i=2; i<=windowwidth-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-a.ptr.pp_double[i-1][j]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:304");
}
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
ssaanalyzelastwindow(&state, &trend, &noise, &nticks, _state);
ae_set_error_flag(errorflag, nticks!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:310");
ae_set_error_flag(errorflag, noise.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:311");
ae_set_error_flag(errorflag, trend.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:312");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=windowwidth-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:317");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:318");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
ssaanalyzelast(&state, windowwidth, &trend, &noise, _state);
ae_set_error_flag(errorflag, noise.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:324");
ae_set_error_flag(errorflag, trend.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:325");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=windowwidth-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:330");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:331");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nticks = 1+hqrnduniformi(&rs, 2*windowwidth, _state);
ssaforecastlast(&state, nticks, &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:338");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
v = x.ptr.p_double[windowwidth-1]-x.ptr.p_double[windowwidth-2];
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[0]-x.ptr.p_double[windowwidth-1]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:342");
for(i=1; i<=nticks-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-trend.ptr.p_double[i-1]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:344");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nticks = 1+hqrnduniformi(&rs, 2*windowwidth, _state);
navg = 1+hqrnduniformi(&rs, windowwidth+5, _state);
ae_vector_set_length(&trend, 0, _state);
ssaforecastavglast(&state, navg, nticks, &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:352");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
v = x.ptr.p_double[windowwidth-1]-x.ptr.p_double[windowwidth-2];
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[0]-x.ptr.p_double[windowwidth-1]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:356");
for(i=1; i<=nticks-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-trend.ptr.p_double[i-1]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:358");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
datalen = windowwidth+hqrnduniformi(&rs, 10, _state);
forecastlen = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&x, datalen, _state);
v = hqrndnormal(&rs, _state);
x.ptr.p_double[0] = hqrndnormal(&rs, _state);
for(i=1; i<=datalen-1; i++)
{
x.ptr.p_double[i] = x.ptr.p_double[i-1]+v;
}
ae_vector_set_length(&trend, 0, _state);
ssaforecastsequence(&state, &x, datalen, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=forecastlen, __FILE__, __LINE__, "testssaunit.ap:371");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[0]-x.ptr.p_double[datalen-1]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:374");
for(i=1; i<=forecastlen-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-trend.ptr.p_double[i-1]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:376");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
datalen = windowwidth+hqrnduniformi(&rs, 10, _state);
navg = 1+hqrnduniformi(&rs, windowwidth+5, _state);
forecastlen = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&x, datalen, _state);
v = hqrndnormal(&rs, _state);
x.ptr.p_double[0] = hqrndnormal(&rs, _state);
for(i=1; i<=datalen-1; i++)
{
x.ptr.p_double[i] = x.ptr.p_double[i-1]+v;
}
ae_vector_set_length(&trend, 0, _state);
ssaforecastavgsequence(&state, &x, datalen, navg, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=forecastlen, __FILE__, __LINE__, "testssaunit.ap:390");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[0]-x.ptr.p_double[datalen-1]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:393");
for(i=1; i<=forecastlen-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-trend.ptr.p_double[i-1]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:395");
}
}
}
for(pass=1; pass<=5; pass++)
{
ntracks = 5+hqrnduniformi(&rs, 10, _state);
windowwidth = 100;
nlasttracklen = 2*windowwidth;
ssacreate(&state, _state);
ssasetwindow(&state, windowwidth, _state);
ae_vector_set_length(&x, nlasttracklen, _state);
for(k=0; k<=ntracks-1; k++)
{
v = hqrndnormal(&rs, _state);
x.ptr.p_double[0] = hqrndnormal(&rs, _state);
for(i=1; i<=nlasttracklen-1; i++)
{
x.ptr.p_double[i] = x.ptr.p_double[i-1]+v;
}
ssaaddsequence(&state, &x, nlasttracklen, _state);
}
if( algotype==1 )
{
ae_matrix_set_length(&b, windowwidth, 2, _state);
v = 0.0;
for(i=0; i<=windowwidth-1; i++)
{
b.ptr.pp_double[i][0] = 1/ae_sqrt((double)(windowwidth), _state);
b.ptr.pp_double[i][1] = (double)(i);
v = v+(double)i/(double)windowwidth;
}
vv = 0.0;
for(i=0; i<=windowwidth-1; i++)
{
b.ptr.pp_double[i][1] = b.ptr.pp_double[i][1]-v;
vv = vv+ae_sqr(b.ptr.pp_double[i][1], _state);
}
for(i=0; i<=windowwidth-1; i++)
{
b.ptr.pp_double[i][1] = b.ptr.pp_double[i][1]/ae_sqrt(vv, _state);
}
ssasetalgoprecomputed(&state, &b, windowwidth, 2, _state);
}
else
{
if( algotype==2 )
{
ssasetalgotopkdirect(&state, 2, _state);
}
else
{
if( algotype==3 )
{
ssasetalgotopkrealtime(&state, 2, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
tol = 1.0E-6;
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
ssaanalyzelastwindow(&state, &trend, &noise, &nticks, _state);
ae_set_error_flag(errorflag, nticks!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:444");
ae_set_error_flag(errorflag, noise.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:445");
ae_set_error_flag(errorflag, trend.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:446");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=windowwidth-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[nlasttracklen+i-windowwidth], _state),tol), __FILE__, __LINE__, "testssaunit.ap:451");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:452");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
ssaanalyzelast(&state, nlasttracklen, &trend, &noise, _state);
ae_set_error_flag(errorflag, noise.cnt!=nlasttracklen, __FILE__, __LINE__, "testssaunit.ap:458");
ae_set_error_flag(errorflag, trend.cnt!=nlasttracklen, __FILE__, __LINE__, "testssaunit.ap:459");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=nlasttracklen-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:464");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:465");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nticks = 1+hqrnduniformi(&rs, 10, _state);
ssaforecastlast(&state, nticks, &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:472");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
v = x.ptr.p_double[nlasttracklen-1]-x.ptr.p_double[nlasttracklen-2];
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[0]-x.ptr.p_double[nlasttracklen-1]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:476");
for(i=1; i<=nticks-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-trend.ptr.p_double[i-1]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:478");
}
}
}
/*
* Test that on specially designed dataset with two sinusoidal components
* with significantly different amplitudes, whose periods are integer
* divisors of window width, SSA correctly separates leading sine from
* its smaller counterpart. Also test that we can correctly predict future
* values of the sequence.
*
* Dataset consists of many sequences, each of them featuring either
* sine with period=WindowWidth or sine with period=WindowWidth/2. Such
* dataset is necessary because sum of two sines is not well separated by
* SVD (it performs only approximate, asymptotic separation). But when
* every sequence is either one of the sines, but not two together, we
* can easily separate them.
*
* Sine coefficients are changed from sequence to sequence.
*
* NOTE: this test requires large WindowWidth and TopK=2 to work.
*
* NOTE: this test uses reduced number of passes because of higher computational complexity
*/
for(pass=1; pass<=10; pass++)
{
/*
* Skip "precomputed basis" algorithm
*/
if( algotype==1 )
{
continue;
}
/*
* Generate dataset
*/
ntracks = 100+hqrnduniformi(&rs, 2, _state);
windowwidth = 64;
nlasttracklen = windowwidth+hqrnduniformi(&rs, 10, _state);
ssacreate(&state, _state);
ae_vector_set_length(&x, nlasttracklen, _state);
for(k=0; k<=ntracks-1; k++)
{
sineoffs = (double)(hqrnduniformi(&rs, windowwidth, _state));
if( k%2==0 )
{
sineamp = 1+hqrnduniformr(&rs, _state);
sinefreq = (double)(1);
}
else
{
sineamp = 0.1*(1+hqrnduniformr(&rs, _state));
sinefreq = (double)(2);
}
for(i=0; i<=nlasttracklen-1; i++)
{
x.ptr.p_double[i] = sineamp*ae_sin((i+sineoffs)/windowwidth*2*ae_pi*sinefreq, _state);
}
ssaaddsequence(&state, &x, nlasttracklen, _state);
}
if( algotype==2 )
{
ssasetalgotopkdirect(&state, 2, _state);
}
else
{
if( algotype==3 )
{
ssasetalgotopkrealtime(&state, 2, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
tol = 1.0E-6;
/*
* Test analysis with WindowWidth=SinePeriod:
* * analyze sine with frequency=1, it must be recognized as trend
* * analyze sine with frequency=2, with smoothing enabled
* it must be discarded as noise;
*/
ssasetwindow(&state, windowwidth, _state);
nticks = windowwidth+1+hqrnduniformi(&rs, windowwidth, _state);
sineoffs = (double)(hqrnduniformi(&rs, windowwidth, _state));
sineamp = 1+hqrnduniformr(&rs, _state);
sinefreq = (double)(1);
ae_vector_set_length(&x, nticks, _state);
for(i=0; i<=nticks-1; i++)
{
x.ptr.p_double[i] = sineamp*ae_sin((i+sineoffs)/windowwidth*2*ae_pi*sinefreq, _state);
}
ssaanalyzesequence(&state, &x, nticks, &trend, &noise, _state);
ae_set_error_flag(errorflag, noise.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:558");
ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:559");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=nticks-1; i++)
{
v = sineamp*ae_sin((i+sineoffs)/windowwidth*2*ae_pi*sinefreq, _state);
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:565");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:566");
}
forecastlen = 1+hqrnduniformi(&rs, nticks-windowwidth, _state);
datalen = nticks-forecastlen;
ae_vector_set_length(&x2, datalen, _state);
for(i=0; i<=datalen-1; i++)
{
x2.ptr.p_double[i] = x.ptr.p_double[i];
}
ssaforecastsequence(&state, &x2, datalen, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state);
for(i=0; i<=forecastlen-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[datalen+i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:575");
}
ae_vector_set_length(&tmp0, 0, _state);
windowwidth2 = -1;
ssagetlrr(&state, &tmp0, &windowwidth2, _state);
ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:579");
ae_set_error_flag(errorflag, tmp0.cnt!=windowwidth-1, __FILE__, __LINE__, "testssaunit.ap:580");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=windowwidth-1; i<=nticks-1; i++)
{
v = ae_v_dotproduct(&x.ptr.p_double[i-(windowwidth-1)], 1, &tmp0.ptr.p_double[0], 1, ae_v_len(i-(windowwidth-1),i-1));
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v-x.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:586");
}
nticks = windowwidth+1+hqrnduniformi(&rs, windowwidth, _state);
sineoffs = (double)(hqrnduniformi(&rs, windowwidth, _state));
sineamp = 1+hqrnduniformr(&rs, _state);
sinefreq = (double)(2);
ae_vector_set_length(&x, nticks, _state);
for(i=0; i<=nticks-1; i++)
{
x.ptr.p_double[i] = sineamp*ae_sin((i+sineoffs)/windowwidth*2*ae_pi*sinefreq, _state);
}
ssaanalyzesequence(&state, &x, nticks, &trend, &noise, _state);
ae_set_error_flag(errorflag, noise.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:597");
ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:598");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=nticks-1; i++)
{
v = sineamp*ae_sin((i+sineoffs)/windowwidth*2*ae_pi*sinefreq, _state);
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:604");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i]-v, _state),tol), __FILE__, __LINE__, "testssaunit.ap:605");
}
forecastlen = 1+hqrnduniformi(&rs, nticks-windowwidth, _state);
datalen = nticks-forecastlen;
ae_vector_set_length(&x2, datalen, _state);
for(i=0; i<=datalen-1; i++)
{
x2.ptr.p_double[i] = x.ptr.p_double[i];
}
ssaforecastsequence(&state, &x2, datalen, forecastlen, ae_true, &trend, _state);
for(i=0; i<=forecastlen-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:614");
}
}
/*
* Test appendPoint() functionality.
*
* We have specially designed dataset:
* * NZeros ticks of exactly zero values
* * NLinear ticks of series which linearly grow from 0 to 1
* * NLinear ticks of series which linearly decrease from 1 to 0
* * NZeros ticks of exactly zero values
* * NZeros=100
* * NLinear=20
*
* SSA settings have following values:
* * WindowWidth=4 or 25 (large widths are more problematic for
* iterative solvers, so they help to debug incremental updates)
* * NBasis=2
*
* We choose number of initial values to start with NInitial
* in [1..2*WindowWidth], then add points one
* by one with SSAAppendPointAndUpdate(). In the end we compare
* results returned by SSAGetBasis() with that returned by model
* which was created from full dataset.
*
* NOTE: we perform limited amount of passes because this test
* has high cost.
*/
for(pass=1; pass<=25; pass++)
{
/*
* Generate dataset
*/
tol = 1.0E-6;
nzeros = 100;
nlinear = 50;
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
windowwidth = 25;
}
else
{
windowwidth = 4;
}
nbasis = 2;
ninitial = 1+hqrnduniformi(&rs, 2*windowwidth, _state);
ae_vector_set_length(&x, 2*nzeros+2*nlinear, _state);
for(i=0; i<=x.cnt-1; i++)
{
x.ptr.p_double[i] = 0.0;
}
for(i=0; i<=nlinear-1; i++)
{
x.ptr.p_double[nzeros+i] = (double)i/(double)nlinear;
x.ptr.p_double[nzeros+nlinear+i] = 1-(double)i/(double)nlinear;
}
rmatrixrndorthogonal(windowwidth, &b, _state);
/*
* Build model using many sequential appends
*
* NOTE: for NInitial>=WindowWidth with probability 50%
* we enforce basis calculation before first
* append() call. It helps to debug different
* branches of algorithms.
*
* NOTE: we may also request delayed power-up of the
* algorithm. It also checks various branches of
* the algo, although with such settings delayed
* power-up is hard to check (initial dataset is
* just zeros, zeros, zeros..).
*/
ae_vector_set_length(&x2, ninitial, _state);
for(i=0; i<=x2.cnt-1; i++)
{
x2.ptr.p_double[i] = x.ptr.p_double[i];
}
ssacreate(&state, _state);
ssasetwindow(&state, windowwidth, _state);
ssaaddsequence(&state, &x2, x2.cnt, _state);
if( algotype==1 )
{
ssasetalgoprecomputed(&state, &b, windowwidth, nbasis, _state);
}
else
{
if( algotype==2 )
{
ssasetalgotopkdirect(&state, nbasis, _state);
}
else
{
if( algotype==3 )
{
ssasetalgotopkrealtime(&state, nbasis, _state);
if( ae_fp_greater(hqrnduniformr(&rs, _state),0.5) )
{
ssasetpoweruplength(&state, 10, _state);
}
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
if( ninitial>=windowwidth&&ae_fp_greater(hqrnduniformr(&rs, _state),0.5) )
{
ae_matrix_set_length(&a, 0, 0, _state);
ae_vector_set_length(&sv, 0, _state);
windowwidth2 = -1;
nbasis2 = -1;
ssagetbasis(&state, &a, &sv, &windowwidth2, &nbasis2, _state);
ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:705");
ae_set_error_flag(errorflag, nbasis2!=nbasis, __FILE__, __LINE__, "testssaunit.ap:706");
ae_set_error_flag(errorflag, a.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:707");
ae_set_error_flag(errorflag, a.cols!=nbasis, __FILE__, __LINE__, "testssaunit.ap:708");
ae_set_error_flag(errorflag, sv.cnt!=nbasis, __FILE__, __LINE__, "testssaunit.ap:709");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
}
for(i=x2.cnt; i<=x.cnt-1; i++)
{
ssaappendpointandupdate(&state, x.ptr.p_double[i], 1.0, _state);
}
ae_matrix_set_length(&a, 0, 0, _state);
ae_vector_set_length(&sv, 0, _state);
windowwidth2 = -1;
nbasis2 = -1;
ssagetbasis(&state, &a, &sv, &windowwidth2, &nbasis2, _state);
ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:720");
ae_set_error_flag(errorflag, nbasis2!=nbasis, __FILE__, __LINE__, "testssaunit.ap:721");
ae_set_error_flag(errorflag, a.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:722");
ae_set_error_flag(errorflag, a.cols!=nbasis, __FILE__, __LINE__, "testssaunit.ap:723");
ae_set_error_flag(errorflag, sv.cnt!=nbasis, __FILE__, __LINE__, "testssaunit.ap:724");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
/*
* Build model using one big sequence
*/
ssacreate(&state2, _state);
ssasetwindow(&state2, windowwidth, _state);
ssaaddsequence(&state2, &x, x.cnt, _state);
if( algotype==1 )
{
ssasetalgoprecomputed(&state2, &b, windowwidth, nbasis, _state);
}
else
{
if( algotype==2 )
{
ssasetalgotopkdirect(&state2, nbasis, _state);
}
else
{
if( algotype==3 )
{
ssasetalgotopkrealtime(&state2, nbasis, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
ae_matrix_set_length(&a2, 0, 0, _state);
ae_vector_set_length(&sv2, 0, _state);
windowwidth2 = -1;
nbasis2 = -1;
ssagetbasis(&state2, &a2, &sv2, &windowwidth2, &nbasis2, _state);
ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:747");
ae_set_error_flag(errorflag, nbasis2!=nbasis, __FILE__, __LINE__, "testssaunit.ap:748");
ae_set_error_flag(errorflag, a2.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:749");
ae_set_error_flag(errorflag, a2.cols!=nbasis, __FILE__, __LINE__, "testssaunit.ap:750");
ae_set_error_flag(errorflag, sv2.cnt!=nbasis, __FILE__, __LINE__, "testssaunit.ap:751");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
/*
* Compare results
*/
for(i=0; i<=nbasis-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(sv.ptr.p_double[i]-sv2.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:759");
}
for(j=0; j<=nbasis-1; j++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[0][j], a.stride, &a2.ptr.pp_double[0][j], a2.stride, ae_v_len(0,windowwidth-1));
for(i=0; i<=windowwidth-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-ae_sign(v, _state)*a2.ptr.pp_double[i][j], _state),tol), __FILE__, __LINE__, "testssaunit.ap:764");
}
}
}
/*
* Test appendSequence() functionality.
*
* We have specially designed dataset:
* * NNoise sequences of Gaussian noise
* * NLinear linear sequences partially corrupted by noise
* * NZeros exactly zero sequences (used to let incremental algo converge)
* * all sequences have random size in [WindowWidth-2,WindowWidth+2]
* * NNoise=20
* * NLinear=20
*
* SSA settings have following values:
* * WindowWidth=4 or 25 (large widths are more problematic for
* iterative solvers, so they help to debug incremental updates)
* * NBasis=2
*
* We have two solvers:
* * one is trained on complete dataset
* * another one starts from NNoise noisy sequences, linear/zero sequenes
* are incrementally appended with AppendSequence
*
* NOTE: we perform limited amount of passes because this test
* has high cost.
*/
for(pass=1; pass<=25; pass++)
{
/*
* Problem metrics
*/
tol = 1.0E-5;
nnoise = 20;
nlinear = 20;
nzeros = 50;
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
windowwidth = 25;
}
else
{
windowwidth = 4;
}
nbasis = 2;
/*
* Initialize solvers
*
* NOTE: we set State.DefaultSubspaceIts to large value in order
* to ensure convergence to same basis.
*/
rmatrixrndorthogonal(windowwidth, &b, _state);
ssacreate(&state, _state);
ssacreate(&state2, _state);
state.defaultsubspaceits = 50;
ssasetwindow(&state, windowwidth, _state);
ssasetwindow(&state2, windowwidth, _state);
if( algotype==1 )
{
ssasetalgoprecomputed(&state, &b, windowwidth, nbasis, _state);
ssasetalgoprecomputed(&state2, &b, windowwidth, nbasis, _state);
}
else
{
if( algotype==2 )
{
ssasetalgotopkdirect(&state, nbasis, _state);
ssasetalgotopkdirect(&state2, nbasis, _state);
}
else
{
if( algotype==3 )
{
ssasetalgotopkrealtime(&state, nbasis, _state);
ssasetalgotopkrealtime(&state2, nbasis, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
/*
* Feed noisy sequences
*/
for(i=0; i<=nnoise-1; i++)
{
k = windowwidth+(hqrnduniformi(&rs, 5, _state)-2);
ae_vector_set_length(&x, k, _state);
for(j=0; j<=k-1; j++)
{
x.ptr.p_double[j] = hqrndnormal(&rs, _state);
}
ssaaddsequence(&state, &x, x.cnt, _state);
ssaaddsequence(&state2, &x, x.cnt, _state);
}
/*
* Feed linear and zero sequences.
*
* NOTE: with probability 50% we call SSAGetBasis(State2).
* Ideally, SSA should be able to handle appends correctly
* with or without preceeding call which requires basis
* to be evaluated.
*/
if( ae_fp_greater(hqrnduniformr(&rs, _state),0.5) )
{
ae_matrix_set_length(&a2, 0, 0, _state);
ae_vector_set_length(&sv2, 0, _state);
windowwidth2 = -1;
nbasis2 = -1;
ssagetbasis(&state2, &a2, &sv2, &windowwidth2, &nbasis2, _state);
ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:865");
ae_set_error_flag(errorflag, nbasis2!=nbasis, __FILE__, __LINE__, "testssaunit.ap:866");
ae_set_error_flag(errorflag, a2.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:867");
ae_set_error_flag(errorflag, a2.cols!=nbasis, __FILE__, __LINE__, "testssaunit.ap:868");
ae_set_error_flag(errorflag, sv2.cnt!=nbasis, __FILE__, __LINE__, "testssaunit.ap:869");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
}
for(i=0; i<=nlinear-1; i++)
{
k = windowwidth+(hqrnduniformi(&rs, 5, _state)-2);
v = hqrndnormal(&rs, _state);
vv = hqrndnormal(&rs, _state);
ae_vector_set_length(&x, k, _state);
x.ptr.p_double[0] = v;
for(j=1; j<=k-1; j++)
{
x.ptr.p_double[j] = x.ptr.p_double[j-1]+vv+0.1*hqrndnormal(&rs, _state);
}
ssaaddsequence(&state, &x, x.cnt, _state);
ssaappendsequenceandupdate(&state2, &x, x.cnt, 1.0, _state);
}
for(i=0; i<=nzeros-1; i++)
{
k = windowwidth+(hqrnduniformi(&rs, 5, _state)-2);
ae_vector_set_length(&x, k, _state);
for(j=0; j<=k-1; j++)
{
x.ptr.p_double[j] = (double)(0);
}
ssaaddsequence(&state, &x, x.cnt, _state);
ssaappendsequenceandupdate(&state2, &x, x.cnt, 1.0, _state);
}
/*
* Compare results
*/
ae_matrix_set_length(&a, 0, 0, _state);
ae_vector_set_length(&sv, 0, _state);
windowwidth2 = -1;
nbasis2 = -1;
ssagetbasis(&state, &a, &sv, &windowwidth2, &nbasis2, _state);
ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:903");
ae_set_error_flag(errorflag, nbasis2!=nbasis, __FILE__, __LINE__, "testssaunit.ap:904");
ae_set_error_flag(errorflag, a.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:905");
ae_set_error_flag(errorflag, a.cols!=nbasis, __FILE__, __LINE__, "testssaunit.ap:906");
ae_set_error_flag(errorflag, sv.cnt!=nbasis, __FILE__, __LINE__, "testssaunit.ap:907");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
ae_matrix_set_length(&a2, 0, 0, _state);
ae_vector_set_length(&sv2, 0, _state);
windowwidth2 = -1;
nbasis2 = -1;
ssagetbasis(&state2, &a2, &sv2, &windowwidth2, &nbasis2, _state);
ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:915");
ae_set_error_flag(errorflag, nbasis2!=nbasis, __FILE__, __LINE__, "testssaunit.ap:916");
ae_set_error_flag(errorflag, a2.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:917");
ae_set_error_flag(errorflag, a2.cols!=nbasis, __FILE__, __LINE__, "testssaunit.ap:918");
ae_set_error_flag(errorflag, sv2.cnt!=nbasis, __FILE__, __LINE__, "testssaunit.ap:919");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=nbasis-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(sv.ptr.p_double[i]-sv2.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:923");
}
for(j=0; j<=nbasis-1; j++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[0][j], a.stride, &a2.ptr.pp_double[0][j], a2.stride, ae_v_len(0,windowwidth-1));
for(i=0; i<=windowwidth-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(a.ptr.pp_double[i][j]-ae_sign(v, _state)*a2.ptr.pp_double[i][j], _state),tol), __FILE__, __LINE__, "testssaunit.ap:928");
}
}
}
/*
* Test memory limit functionality.
*
* Compare results obtained with HUGE limit vs ones obtained with small limit.
*/
for(windowwidth=1; windowwidth<=20; windowwidth++)
{
for(mlimit=-1; mlimit<=16; mlimit++)
{
/*
* Not tested
*/
if( algotype==1 )
{
continue;
}
/*
* Problem metrics
*/
tol = 1.0E-5;
nticks = 1000+hqrnduniformi(&rs, 1000, _state);
if( windowwidth>5 )
{
nbasis = 1+hqrnduniformi(&rs, 5, _state);
}
else
{
nbasis = 1;
}
/*
* Create solvers, dataset, set limits
*/
ssacreate(&state, _state);
ssacreate(&state2, _state);
if( mlimit>=0 )
{
ssasetmemorylimit(&state, ae_round(ae_pow((double)(2), (double)(mlimit), _state), _state), _state);
}
else
{
ssasetmemorylimit(&state, 0, _state);
}
ssasetmemorylimit(&state2, 999999999, _state);
ssasetwindow(&state, windowwidth, _state);
ssasetwindow(&state2, windowwidth, _state);
if( algotype==2 )
{
ssasetalgotopkdirect(&state, nbasis, _state);
ssasetalgotopkdirect(&state2, nbasis, _state);
}
else
{
if( algotype==3 )
{
ssasetalgotopkrealtime(&state, nbasis, _state);
ssasetalgotopkrealtime(&state2, nbasis, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
ae_vector_set_length(&x, nticks, _state);
for(i=0; i<=nticks-1; i++)
{
x.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ssaaddsequence(&state, &x, x.cnt, _state);
ssaaddsequence(&state2, &x, x.cnt, _state);
/*
* Reset internal temporaries for this test.
* Implementation-dependent, may fail due to future changes in the core.
*/
ae_matrix_set_length(&state.uxbatch, 0, 0, _state);
ae_matrix_set_length(&state.aseqtrajectory, 0, 0, _state);
ae_matrix_set_length(&state.aseqtbproduct, 0, 0, _state);
/*
* Test
*/
ssaanalyzelast(&state, nticks, &trend, &noise, _state);
ssaanalyzelast(&state2, nticks, &trend2, &noise2, _state);
for(i=0; i<=nticks-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-trend2.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:1001");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i]-noise2.ptr.p_double[i], _state),tol), __FILE__, __LINE__, "testssaunit.ap:1002");
}
/*
* Additional tests for sizes of internal arrays.
* Implementation-dependent, may fail due to future changes in the core.
*/
if( mlimit>=0 )
{
k = ae_maxint(4*windowwidth*windowwidth, ae_round(ae_pow((double)(2), (double)(mlimit), _state), _state), _state);
ae_set_error_flag(errorflag, state.uxbatch.cols*state.uxbatch.rows>k, __FILE__, __LINE__, "testssaunit.ap:1012");
ae_set_error_flag(errorflag, state.aseqtrajectory.cols*state.aseqtrajectory.rows>k, __FILE__, __LINE__, "testssaunit.ap:1013");
ae_set_error_flag(errorflag, state.aseqtbproduct.cols*state.aseqtbproduct.rows>k, __FILE__, __LINE__, "testssaunit.ap:1014");
}
else
{
ae_set_error_flag(errorflag, state.uxbatch.rows!=nticks-windowwidth+1, __FILE__, __LINE__, "testssaunit.ap:1018");
ae_set_error_flag(errorflag, state.aseqtrajectory.rows!=nticks-windowwidth+1, __FILE__, __LINE__, "testssaunit.ap:1019");
ae_set_error_flag(errorflag, state.aseqtbproduct.rows!=nticks-windowwidth+1, __FILE__, __LINE__, "testssaunit.ap:1020");
}
}
}
}
/*
* Test power-up ability of the real-time algorithm.
*
* We have specially designed dataset:
* * NTicks ticks of linearly descending from 1 to 0 linear trend,
* corrupted by random Gaussian noise
* * NZeros ticks of exactly zero values
* * NTicks=100
* * NZeros=100
*
* SSA settings have following values:
* * WindowWidth=4 or 25 (large widths are more problematic for
* iterative solvers, so they help to debug incremental updates)
* * NBasis=1..2 (only top vectors converge stable enough for unit testing)
* * powerup length is 10
*
* We perform two SSAs:
* * one with full dataset and no powerup
* * one with powerup, NTicks+WindowWidth first elements, followed by appending of NZeros zeros
*
* We check that:
* * basis found by second model (right after initialization) is different
* from basis of the first one
* * basis found by second model after last append is same as the first one
*
* NOTE: we perform limited amount of passes because this test
* has high cost.
*/
for(pass=1; pass<=25; pass++)
{
/*
* Generate dataset
*/
tol = 1.0E-3;
nticks = 100;
nzeros = 50;
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
windowwidth = 25;
}
else
{
windowwidth = 4;
}
nbasis = 1+hqrnduniformi(&rs, 2, _state);
ae_vector_set_length(&x, nticks+nzeros, _state);
for(i=0; i<=x.cnt-1; i++)
{
x.ptr.p_double[i] = 0.0;
}
for(i=0; i<=nticks-1; i++)
{
x.ptr.p_double[i] = 1-(double)i/(double)nticks+0.05*hqrndnormal(&rs, _state);
}
/*
* Build complete model
*
* NOTE: we tweak S.DefaultSubspaceIts in order to enforce convergence to
* same basis; for this test we need extra-precise convergence.
*/
ssacreate(&state2, _state);
ssasetwindow(&state2, windowwidth, _state);
ssaaddsequence(&state2, &x, x.cnt, _state);
ssasetalgotopkrealtime(&state2, nbasis, _state);
ae_matrix_set_length(&a2, 0, 0, _state);
ae_vector_set_length(&sv2, 0, _state);
windowwidth2 = -1;
nbasis2 = -1;
ssagetbasis(&state2, &a2, &sv2, &windowwidth2, &nbasis2, _state);
ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1088");
ae_set_error_flag(errorflag, nbasis2!=nbasis, __FILE__, __LINE__, "testssaunit.ap:1089");
ae_set_error_flag(errorflag, a2.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1090");
ae_set_error_flag(errorflag, a2.cols!=nbasis, __FILE__, __LINE__, "testssaunit.ap:1091");
ae_set_error_flag(errorflag, sv2.cnt!=nbasis, __FILE__, __LINE__, "testssaunit.ap:1092");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
/*
* Build model with power-up cycle
*
* NOTE: with probability 50% we enforce basis calculation
* before first append() call and compare basis with
* one returned by full analysis. We do it only in 50%
* of the cases because randomness helps to debug different
* branches of algorithms.
*/
ae_vector_set_length(&x2, nticks+windowwidth, _state);
for(i=0; i<=x2.cnt-1; i++)
{
x2.ptr.p_double[i] = x.ptr.p_double[i];
}
ssacreate(&state, _state);
ssasetwindow(&state, windowwidth, _state);
ssaaddsequence(&state, &x2, x2.cnt, _state);
ssasetalgotopkrealtime(&state, nbasis, _state);
ssasetpoweruplength(&state, 10, _state);
if( ae_fp_greater(hqrnduniformr(&rs, _state),0.5) )
{
ae_matrix_set_length(&a, 0, 0, _state);
ae_vector_set_length(&sv, 0, _state);
windowwidth2 = -1;
nbasis2 = -1;
ssagetbasis(&state, &a, &sv, &windowwidth2, &nbasis2, _state);
ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1120");
ae_set_error_flag(errorflag, nbasis2!=nbasis, __FILE__, __LINE__, "testssaunit.ap:1121");
ae_set_error_flag(errorflag, a.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1122");
ae_set_error_flag(errorflag, a.cols!=nbasis, __FILE__, __LINE__, "testssaunit.ap:1123");
ae_set_error_flag(errorflag, sv.cnt!=nbasis, __FILE__, __LINE__, "testssaunit.ap:1124");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
vv = 0.0;
for(i=0; i<=nbasis-1; i++)
{
vv = ae_maxreal(vv, ae_fabs(sv.ptr.p_double[i]-sv2.ptr.p_double[i], _state), _state);
}
for(j=0; j<=nbasis-1; j++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[0][j], a.stride, &a2.ptr.pp_double[0][j], a2.stride, ae_v_len(0,windowwidth-1));
for(i=0; i<=windowwidth-1; i++)
{
vv = ae_maxreal(vv, ae_fabs(a.ptr.pp_double[i][j]-ae_sign(v, _state)*a2.ptr.pp_double[i][j], _state), _state);
}
}
ae_set_error_flag(errorflag, ae_fp_less(ae_fabs(vv, _state),tol), __FILE__, __LINE__, "testssaunit.ap:1136");
}
for(i=x2.cnt; i<=x.cnt-1; i++)
{
ssaappendpointandupdate(&state, x.ptr.p_double[i], 1.0, _state);
}
ae_matrix_set_length(&a, 0, 0, _state);
ae_vector_set_length(&sv, 0, _state);
windowwidth2 = -1;
nbasis2 = -1;
ssagetbasis(&state, &a, &sv, &windowwidth2, &nbasis2, _state);
ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1145");
ae_set_error_flag(errorflag, nbasis2!=nbasis, __FILE__, __LINE__, "testssaunit.ap:1146");
ae_set_error_flag(errorflag, a.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1147");
ae_set_error_flag(errorflag, a.cols!=nbasis, __FILE__, __LINE__, "testssaunit.ap:1148");
ae_set_error_flag(errorflag, sv.cnt!=nbasis, __FILE__, __LINE__, "testssaunit.ap:1149");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
vv = 0.0;
for(i=0; i<=nbasis-1; i++)
{
vv = ae_maxreal(vv, ae_fabs(sv.ptr.p_double[i]-sv2.ptr.p_double[i], _state), _state);
}
for(j=0; j<=nbasis-1; j++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[0][j], a.stride, &a2.ptr.pp_double[0][j], a2.stride, ae_v_len(0,windowwidth-1));
for(i=0; i<=windowwidth-1; i++)
{
vv = ae_maxreal(vv, ae_fabs(a.ptr.pp_double[i][j]-ae_sign(v, _state)*a2.ptr.pp_double[i][j], _state), _state);
}
}
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(vv, _state),tol), __FILE__, __LINE__, "testssaunit.ap:1161");
}
/*
* Test that SSAForecastAvgLast/Sequence() actually performs averaging.
* We test it by comparing its results vs manually averaged predictions.
*
* Dataset is a small linear trend + Gaussian noise. We are not interested
* in getting meaningful components, we just want to check correctness of math.
*/
for(pass=1; pass<=100; pass++)
{
nticks = 75+hqrnduniformi(&rs, 75, _state);
windowwidth = 5+hqrnduniformi(&rs, 5, _state);
navg = 1+hqrnduniformi(&rs, 2*windowwidth, _state);
forecastlen = 1+hqrnduniformi(&rs, 2*windowwidth, _state);
ssacreate(&state, _state);
ssasetwindow(&state, windowwidth, _state);
ae_vector_set_length(&x, nticks, _state);
for(i=0; i<=nticks-1; i++)
{
x.ptr.p_double[i] = 0.1*i+hqrndnormal(&rs, _state);
}
ssaaddsequence(&state, &x, nticks, _state);
ssasetalgotopkdirect(&state, 1+hqrnduniformi(&rs, 3, _state), _state);
tol = 1.0E-9;
ssaforecastavglast(&state, navg, forecastlen, &trend, _state);
ae_vector_set_length(&trend2, forecastlen, _state);
for(i=0; i<=forecastlen-1; i++)
{
trend2.ptr.p_double[i] = 0.0;
}
for(i=0; i<=navg-1; i++)
{
ssaforecastsequence(&state, &x, nticks-i, forecastlen+i, ae_true, &tmp0, _state);
for(j=0; j<=forecastlen-1; j++)
{
trend2.ptr.p_double[j] = trend2.ptr.p_double[j]+tmp0.ptr.p_double[i+j]/navg;
}
}
for(i=0; i<=forecastlen-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-trend2.ptr.p_double[i], _state),tol*maxreal3(ae_fabs(trend.ptr.p_double[i], _state), ae_fabs(trend2.ptr.p_double[i], _state), 1.0, _state)), __FILE__, __LINE__, "testssaunit.ap:1198");
}
nticks = 75+hqrnduniformi(&rs, 75, _state);
j = hqrnduniformi(&rs, 150, _state)-75;
ae_vector_set_length(&x2, nticks, _state);
for(i=0; i<=nticks-1; i++)
{
x2.ptr.p_double[i] = 0.1*(i+j)+hqrndnormal(&rs, _state);
}
ssaforecastavgsequence(&state, &x2, nticks, navg, forecastlen, ae_true, &trend, _state);
ae_vector_set_length(&trend2, forecastlen, _state);
for(i=0; i<=forecastlen-1; i++)
{
trend2.ptr.p_double[i] = 0.0;
}
for(i=0; i<=navg-1; i++)
{
ssaforecastsequence(&state, &x2, nticks-i, forecastlen+i, ae_true, &tmp0, _state);
for(j=0; j<=forecastlen-1; j++)
{
trend2.ptr.p_double[j] = trend2.ptr.p_double[j]+tmp0.ptr.p_double[i+j]/navg;
}
}
for(i=0; i<=forecastlen-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-trend2.ptr.p_double[i], _state),tol*maxreal3(ae_fabs(trend.ptr.p_double[i], _state), ae_fabs(trend2.ptr.p_double[i], _state), 1.0, _state)), __FILE__, __LINE__, "testssaunit.ap:1217");
}
nticks = 75+hqrnduniformi(&rs, 75, _state);
j = hqrnduniformi(&rs, 150, _state)-75;
ae_vector_set_length(&x2, nticks, _state);
for(i=0; i<=nticks-1; i++)
{
x2.ptr.p_double[i] = 0.1*(i+j)+hqrndnormal(&rs, _state);
}
ssaforecastavgsequence(&state, &x2, nticks, navg, forecastlen, ae_false, &trend, _state);
ae_vector_set_length(&trend2, forecastlen, _state);
for(i=0; i<=forecastlen-1; i++)
{
trend2.ptr.p_double[i] = 0.0;
}
for(i=0; i<=navg-1; i++)
{
ssaforecastsequence(&state, &x2, nticks-i, forecastlen+i, ae_false, &tmp0, _state);
for(j=0; j<=forecastlen-1; j++)
{
trend2.ptr.p_double[j] = trend2.ptr.p_double[j]+tmp0.ptr.p_double[i+j]/navg;
}
}
for(i=0; i<=forecastlen-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-trend2.ptr.p_double[i], _state),tol*maxreal3(ae_fabs(trend.ptr.p_double[i], _state), ae_fabs(trend2.ptr.p_double[i], _state), 1.0, _state)), __FILE__, __LINE__, "testssaunit.ap:1236");
}
}
ae_frame_leave(_state);
}
/*************************************************************************
This function tests different special cases (mostly - degenerate ones).
On failure sets ErrorFlag, on success it is untouched.
*************************************************************************/
static void testssaunit_testspecial(ae_bool* errorflag, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
ae_int_t pass;
ssamodel state;
ssamodel state2;
ae_matrix a;
ae_matrix b;
ae_vector x;
ae_vector x2;
ae_vector sv;
ae_vector trend;
ae_vector noise;
ae_vector trend2;
ae_vector noise2;
ae_int_t algotype;
ae_int_t nticks;
ae_int_t nanalyzed;
ae_int_t nlasttracklen;
ae_int_t ntracks;
ae_int_t maxtracklen;
ae_int_t mintracklen;
ae_int_t datalen;
ae_int_t forecastlen;
ae_int_t windowwidth;
ae_int_t nbasis;
ae_int_t windowwidth2;
ae_matrix tracksmatrix;
ae_vector trackssizes;
hqrndstate rs;
ae_int_t passcount;
double skipprob;
ae_frame_make(_state, &_frame_block);
memset(&state, 0, sizeof(state));
memset(&state2, 0, sizeof(state2));
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
memset(&x, 0, sizeof(x));
memset(&x2, 0, sizeof(x2));
memset(&sv, 0, sizeof(sv));
memset(&trend, 0, sizeof(trend));
memset(&noise, 0, sizeof(noise));
memset(&trend2, 0, sizeof(trend2));
memset(&noise2, 0, sizeof(noise2));
memset(&tracksmatrix, 0, sizeof(tracksmatrix));
memset(&trackssizes, 0, sizeof(trackssizes));
memset(&rs, 0, sizeof(rs));
_ssamodel_init(&state, _state, ae_true);
_ssamodel_init(&state2, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&sv, 0, DT_REAL, _state, ae_true);
ae_vector_init(&trend, 0, DT_REAL, _state, ae_true);
ae_vector_init(&noise, 0, DT_REAL, _state, ae_true);
ae_vector_init(&trend2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&noise2, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&tracksmatrix, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&trackssizes, 0, DT_INT, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
/*
* Initialize RNG, test pass count and skip probability.
*
* When we perform several sequential tests on the same model, we may
* skip some of them with probability SkipProb in order to make sure
* that no carry-over effect is observed between tests.
*/
hqrndrandomize(&rs, _state);
passcount = 500;
skipprob = 0.50;
/*
* Test that for empty model in default state:
* * SSAGetBasis() returns zero 1x1 basis
* * SSAAnalyzeLastWindow() returns zeros as trend/noise
* * SSAAnalyzeLast() returns zeros as trend/noise
* * SSAAnalyzeSequence() returns zeros as trend, sequence as noise
* * SSAForecastLast() returns zero trend
* * SSAForecastSequence() returns zero trend
*/
for(pass=1; pass<=passcount; pass++)
{
ssacreate(&state, _state);
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
ssagetbasis(&state, &a, &sv, &windowwidth, &nbasis, _state);
ae_set_error_flag(errorflag, windowwidth!=1, __FILE__, __LINE__, "testssaunit.ap:1299");
ae_set_error_flag(errorflag, nbasis!=1, __FILE__, __LINE__, "testssaunit.ap:1300");
ae_set_error_flag(errorflag, a.rows!=1, __FILE__, __LINE__, "testssaunit.ap:1301");
ae_set_error_flag(errorflag, a.cols!=1, __FILE__, __LINE__, "testssaunit.ap:1302");
ae_set_error_flag(errorflag, sv.cnt!=1, __FILE__, __LINE__, "testssaunit.ap:1303");
for(i=0; i<=a.rows-1; i++)
{
for(j=0; j<=a.cols-1; j++)
{
ae_set_error_flag(errorflag, ae_fp_neq(a.ptr.pp_double[i][j],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1306");
}
}
for(i=0; i<=sv.cnt-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(sv.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1308");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
windowwidth = -1;
ae_vector_set_length(&trend, 0, _state);
ae_vector_set_length(&noise, 0, _state);
ssaanalyzelastwindow(&state, &trend, &noise, &windowwidth, _state);
ae_set_error_flag(errorflag, windowwidth!=1, __FILE__, __LINE__, "testssaunit.ap:1316");
ae_set_error_flag(errorflag, trend.cnt!=1||ae_fp_neq(trend.ptr.p_double[0],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1317");
ae_set_error_flag(errorflag, noise.cnt!=1||ae_fp_neq(noise.ptr.p_double[0],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1318");
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nticks = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&trend, 0, _state);
ae_vector_set_length(&noise, 0, _state);
ssaanalyzelast(&state, nticks, &trend, &noise, _state);
ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1326");
ae_set_error_flag(errorflag, noise.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1327");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=nticks-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1332");
ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1333");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nticks = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&x, nticks, _state);
for(i=0; i<=nticks-1; i++)
{
x.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&trend, 0, _state);
ae_vector_set_length(&noise, 0, _state);
ssaanalyzesequence(&state, &x, nticks, &trend, &noise, _state);
ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1345");
ae_set_error_flag(errorflag, noise.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1346");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=nticks-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1351");
ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],x.ptr.p_double[i]), __FILE__, __LINE__, "testssaunit.ap:1352");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nticks = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&trend, 0, _state);
ssaforecastlast(&state, nticks, &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1360");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=nticks-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1364");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
datalen = 1+hqrnduniformi(&rs, 10, _state);
forecastlen = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&x, datalen, _state);
for(i=0; i<=datalen-1; i++)
{
x.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&trend, 0, _state);
ssaforecastsequence(&state, &x, datalen, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=forecastlen, __FILE__, __LINE__, "testssaunit.ap:1375");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=forecastlen-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1379");
}
}
}
/*
* Test that for empty model with non-default window, but default
* algorithm and no data:
* * SSAGetBasis() returns zero WINDOWx1 basis
* * SSAAnalyzeLastWindow() returns zeros as trend/noise
* * SSAAnalyzeLast() returns zeros as trend/noise
* * SSAAnalyzeSequence() returns zeros as trend, sequence as noise
* * SSAForecastLast() returns zero trend
* * SSAForecastSequence() returns zero trend
*/
for(pass=1; pass<=passcount; pass++)
{
windowwidth2 = 1+hqrnduniformi(&rs, 10, _state);
ssacreate(&state, _state);
ssasetwindow(&state, windowwidth2, _state);
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
ssagetbasis(&state, &a, &sv, &windowwidth, &nbasis, _state);
ae_set_error_flag(errorflag, windowwidth!=windowwidth2, __FILE__, __LINE__, "testssaunit.ap:1401");
ae_set_error_flag(errorflag, nbasis!=1, __FILE__, __LINE__, "testssaunit.ap:1402");
ae_set_error_flag(errorflag, a.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1403");
ae_set_error_flag(errorflag, a.cols!=1, __FILE__, __LINE__, "testssaunit.ap:1404");
ae_set_error_flag(errorflag, sv.cnt!=1, __FILE__, __LINE__, "testssaunit.ap:1405");
for(i=0; i<=a.rows-1; i++)
{
for(j=0; j<=a.cols-1; j++)
{
ae_set_error_flag(errorflag, ae_fp_neq(a.ptr.pp_double[i][j],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1408");
}
}
for(i=0; i<=sv.cnt-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(sv.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1410");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
windowwidth = -1;
ae_vector_set_length(&trend, 0, _state);
ae_vector_set_length(&noise, 0, _state);
ssaanalyzelastwindow(&state, &trend, &noise, &windowwidth, _state);
ae_set_error_flag(errorflag, windowwidth!=windowwidth2, __FILE__, __LINE__, "testssaunit.ap:1418");
ae_set_error_flag(errorflag, trend.cnt!=windowwidth2, __FILE__, __LINE__, "testssaunit.ap:1419");
ae_set_error_flag(errorflag, noise.cnt!=windowwidth2, __FILE__, __LINE__, "testssaunit.ap:1420");
for(i=0; i<=trend.cnt-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1422");
}
for(i=0; i<=noise.cnt-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1424");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nticks = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&trend, 0, _state);
ae_vector_set_length(&noise, 0, _state);
ssaanalyzelast(&state, nticks, &trend, &noise, _state);
ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1432");
ae_set_error_flag(errorflag, noise.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1433");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=nticks-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1438");
ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1439");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nticks = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&x, nticks, _state);
for(i=0; i<=nticks-1; i++)
{
x.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&trend, 0, _state);
ae_vector_set_length(&noise, 0, _state);
ssaanalyzesequence(&state, &x, nticks, &trend, &noise, _state);
ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1451");
ae_set_error_flag(errorflag, noise.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1452");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=nticks-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1457");
ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],x.ptr.p_double[i]), __FILE__, __LINE__, "testssaunit.ap:1458");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nticks = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&trend, 0, _state);
ssaforecastlast(&state, nticks, &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1466");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=nticks-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1470");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
datalen = 1+hqrnduniformi(&rs, 10, _state);
forecastlen = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&x, datalen, _state);
for(i=0; i<=datalen-1; i++)
{
x.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&trend, 0, _state);
ssaforecastsequence(&state, &x, datalen, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=forecastlen, __FILE__, __LINE__, "testssaunit.ap:1481");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=forecastlen-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1485");
}
}
}
/*
* Test that for empty model with default algorithm and one/few tracks
* (which are sometimes shorter than window, sometimes longer than window)
* * SSAGetBasis() returns zero WINDOWx1 basis
* * SSAAnalyzeLastWindow() returns zeros as trend and correctly aligned
* cropped/padded copy of X in the noise
* * SSAAnalyzeLast() returns zeros as trend and correctly aligned
* cropped/padded copy of X in the noise
* * SSAAnalyzeSequence() returns zeros as trend, sequence as noise
* * SSAForecastLast() returns zero trend
* * SSAForecastSequence() returns zero trend
*/
for(pass=1; pass<=passcount; pass++)
{
/*
* Generate task; last track is stored in X, its length in NLastTrackLen
*/
nlasttracklen = -999999;
windowwidth2 = 1+hqrnduniformi(&rs, 10, _state);
ntracks = 1+hqrnduniformi(&rs, 3, _state);
ssacreate(&state, _state);
ssasetwindow(&state, windowwidth2, _state);
ae_matrix_set_length(&tracksmatrix, ntracks, 2*windowwidth2, _state);
ae_vector_set_length(&trackssizes, ntracks, _state);
for(k=0; k<=ntracks-1; k++)
{
nlasttracklen = hqrnduniformi(&rs, 2*windowwidth2, _state);
ae_vector_set_length(&x, nlasttracklen, _state);
for(i=0; i<=nlasttracklen-1; i++)
{
x.ptr.p_double[i] = hqrndnormal(&rs, _state);
tracksmatrix.ptr.pp_double[k][i] = x.ptr.p_double[i];
}
trackssizes.ptr.p_int[k] = nlasttracklen;
ssaaddsequence(&state, &x, nlasttracklen, _state);
}
/*
* Test
*/
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
ssagetbasis(&state, &a, &sv, &windowwidth, &nbasis, _state);
ae_set_error_flag(errorflag, windowwidth!=windowwidth2, __FILE__, __LINE__, "testssaunit.ap:1532");
ae_set_error_flag(errorflag, nbasis!=1, __FILE__, __LINE__, "testssaunit.ap:1533");
ae_set_error_flag(errorflag, a.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1534");
ae_set_error_flag(errorflag, a.cols!=1, __FILE__, __LINE__, "testssaunit.ap:1535");
ae_set_error_flag(errorflag, sv.cnt!=1, __FILE__, __LINE__, "testssaunit.ap:1536");
for(i=0; i<=a.rows-1; i++)
{
for(j=0; j<=a.cols-1; j++)
{
ae_set_error_flag(errorflag, ae_fp_neq(a.ptr.pp_double[i][j],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1539");
}
}
for(i=0; i<=sv.cnt-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(sv.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1541");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
windowwidth = -1;
ae_vector_set_length(&trend, 0, _state);
ae_vector_set_length(&noise, 0, _state);
ssaanalyzelastwindow(&state, &trend, &noise, &windowwidth, _state);
ae_set_error_flag(errorflag, windowwidth!=windowwidth2, __FILE__, __LINE__, "testssaunit.ap:1549");
ae_set_error_flag(errorflag, trend.cnt!=windowwidth2, __FILE__, __LINE__, "testssaunit.ap:1550");
ae_set_error_flag(errorflag, noise.cnt!=windowwidth2, __FILE__, __LINE__, "testssaunit.ap:1551");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=windowwidth-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1555");
}
for(i=0; i<=ae_maxint(windowwidth-nlasttracklen, 0, _state)-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1557");
}
for(i=ae_maxint(windowwidth-nlasttracklen, 0, _state); i<=windowwidth-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],x.ptr.p_double[nlasttracklen+(i-windowwidth)]), __FILE__, __LINE__, "testssaunit.ap:1559");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nanalyzed = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&trend, 0, _state);
ae_vector_set_length(&noise, 0, _state);
ssaanalyzelast(&state, nanalyzed, &trend, &noise, _state);
ae_set_error_flag(errorflag, trend.cnt!=nanalyzed, __FILE__, __LINE__, "testssaunit.ap:1567");
ae_set_error_flag(errorflag, noise.cnt!=nanalyzed, __FILE__, __LINE__, "testssaunit.ap:1568");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=nanalyzed-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1572");
}
for(i=0; i<=ae_maxint(nanalyzed-nlasttracklen, 0, _state)-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1574");
}
for(i=ae_maxint(nanalyzed-nlasttracklen, 0, _state); i<=nanalyzed-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],x.ptr.p_double[nlasttracklen+(i-nanalyzed)]), __FILE__, __LINE__, "testssaunit.ap:1576");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nticks = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&x, nticks, _state);
for(i=0; i<=nticks-1; i++)
{
x.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&trend, 0, _state);
ae_vector_set_length(&noise, 0, _state);
ssaanalyzesequence(&state, &x, nticks, &trend, &noise, _state);
ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1587");
ae_set_error_flag(errorflag, noise.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1588");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=nticks-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1593");
ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],x.ptr.p_double[i]), __FILE__, __LINE__, "testssaunit.ap:1594");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nticks = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&trend, 0, _state);
ssaforecastlast(&state, nticks, &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1602");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=nticks-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1606");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
datalen = 1+hqrnduniformi(&rs, 10, _state);
forecastlen = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&x, datalen, _state);
for(i=0; i<=datalen-1; i++)
{
x.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&trend, 0, _state);
ssaforecastsequence(&state, &x, datalen, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=forecastlen, __FILE__, __LINE__, "testssaunit.ap:1617");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=forecastlen-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1621");
}
}
}
/*
* Tests below are performed for all algorithms supported.
*/
for(algotype=1; algotype<=3; algotype++)
{
/*
* Test that SSAClearData() actually clears data
*/
for(pass=1; pass<=passcount; pass++)
{
if( algotype==1 )
{
continue;
}
/*
* Create two models, one is created after cleardata() call
* which should erase all traces of the previous dataset.
*/
ssacreate(&state, _state);
ssacreate(&state2, _state);
ssasetwindow(&state, 5, _state);
ssasetwindow(&state2, 5, _state);
if( algotype==2 )
{
ssasetalgotopkdirect(&state, 2, _state);
ssasetalgotopkdirect(&state2, 2, _state);
}
else
{
if( algotype==3 )
{
ssasetalgotopkrealtime(&state, 2, _state);
ssasetalgotopkrealtime(&state2, 2, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
ae_vector_set_length(&x, 10, _state);
for(i=0; i<=x.cnt-1; i++)
{
x.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ssaaddsequence(&state, &x, x.cnt, _state);
ssacleardata(&state, _state);
for(i=0; i<=x.cnt-1; i++)
{
x.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ssaaddsequence(&state, &x, x.cnt, _state);
ssaaddsequence(&state2, &x, x.cnt, _state);
/*
* Test
*/
ssaanalyzelast(&state, x.cnt, &trend, &noise, _state);
ssaanalyzelast(&state2, x.cnt, &trend2, &noise2, _state);
for(i=0; i<=x.cnt-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-trend2.ptr.p_double[i], _state),1.0E-5), __FILE__, __LINE__, "testssaunit.ap:1675");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i]-noise2.ptr.p_double[i], _state),1.0E-5), __FILE__, __LINE__, "testssaunit.ap:1676");
}
}
/*
* Test that for model with some algo being set, one/few tracks and unit window length:
* * SSAGetBasis() returns 1x1 basis (unit matrix)
* * SSAAnalyzeLastWindow() returns last element of track as trend and zeros
* as noise (with minor rounding error)
* * SSAAnalyzeLast() returns tracks as trend and zeros as noise (with
* minor rounding error possible). For NTicks>TrackLength result is correctly
* prepended with zeros.
* * SSAAnalyzeSequence() returns sequence as trend, zeros as noise (up to
* machine precision)
* * SSAForecastLast() returns just copies of the last element
* * SSAForecastSequence() returns just copies of the last element
*/
for(pass=1; pass<=passcount; pass++)
{
/*
* Generate task; last track is stored in X, its length in NLastTrackLen
*/
nlasttracklen = -999999;
maxtracklen = 10;
ntracks = 1+hqrnduniformi(&rs, 3, _state);
ssacreate(&state, _state);
ssasetwindow(&state, 1, _state);
ae_matrix_set_length(&tracksmatrix, ntracks, maxtracklen, _state);
ae_vector_set_length(&trackssizes, ntracks, _state);
for(k=0; k<=ntracks-1; k++)
{
nlasttracklen = 1+hqrnduniformi(&rs, maxtracklen, _state);
ae_vector_set_length(&x, nlasttracklen, _state);
for(i=0; i<=nlasttracklen-1; i++)
{
x.ptr.p_double[i] = hqrndnormal(&rs, _state);
tracksmatrix.ptr.pp_double[k][i] = x.ptr.p_double[i];
}
trackssizes.ptr.p_int[k] = nlasttracklen;
ssaaddsequence(&state, &x, nlasttracklen, _state);
}
if( algotype==1 )
{
ae_matrix_set_length(&b, 1, 1, _state);
b.ptr.pp_double[0][0] = (double)(2*hqrnduniformi(&rs, 2, _state)-1);
ssasetalgoprecomputed(&state, &b, 1, 1, _state);
}
else
{
if( algotype==2 )
{
ssasetalgotopkdirect(&state, 1, _state);
}
else
{
if( algotype==3 )
{
ssasetalgotopkrealtime(&state, 1, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
/*
* Test
*/
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
ssagetbasis(&state, &a, &sv, &windowwidth, &nbasis, _state);
ae_set_error_flag(errorflag, windowwidth!=1, __FILE__, __LINE__, "testssaunit.ap:1736");
ae_set_error_flag(errorflag, nbasis!=1, __FILE__, __LINE__, "testssaunit.ap:1737");
ae_set_error_flag(errorflag, a.rows!=1, __FILE__, __LINE__, "testssaunit.ap:1738");
ae_set_error_flag(errorflag, a.cols!=1, __FILE__, __LINE__, "testssaunit.ap:1739");
ae_set_error_flag(errorflag, sv.cnt!=1, __FILE__, __LINE__, "testssaunit.ap:1740");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(ae_fabs(a.ptr.pp_double[0][0], _state)-1, _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1741");
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
windowwidth = -1;
ae_vector_set_length(&trend, 0, _state);
ae_vector_set_length(&noise, 0, _state);
ssaanalyzelastwindow(&state, &trend, &noise, &windowwidth, _state);
ae_set_error_flag(errorflag, windowwidth!=1, __FILE__, __LINE__, "testssaunit.ap:1749");
ae_set_error_flag(errorflag, trend.cnt!=1, __FILE__, __LINE__, "testssaunit.ap:1750");
ae_set_error_flag(errorflag, noise.cnt!=1, __FILE__, __LINE__, "testssaunit.ap:1751");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[0]-x.ptr.p_double[nlasttracklen-1], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1754");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[0], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1755");
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nanalyzed = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&trend, 0, _state);
ae_vector_set_length(&noise, 0, _state);
ssaanalyzelast(&state, nanalyzed, &trend, &noise, _state);
ae_set_error_flag(errorflag, trend.cnt!=nanalyzed, __FILE__, __LINE__, "testssaunit.ap:1763");
ae_set_error_flag(errorflag, noise.cnt!=nanalyzed, __FILE__, __LINE__, "testssaunit.ap:1764");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=ae_maxint(nanalyzed-nlasttracklen, 0, _state)-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1769");
ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1770");
}
for(i=ae_maxint(nanalyzed-nlasttracklen, 0, _state); i<=nanalyzed-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[i-nanalyzed+nlasttracklen], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1774");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1775");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nticks = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&x2, nticks, _state);
for(i=0; i<=nticks-1; i++)
{
x2.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&trend, 0, _state);
ae_vector_set_length(&noise, 0, _state);
ssaanalyzesequence(&state, &x2, nticks, &trend, &noise, _state);
ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1787");
ae_set_error_flag(errorflag, noise.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1788");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=nticks-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x2.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1793");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1794");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nticks = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&trend, 0, _state);
ssaforecastlast(&state, nticks, &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1802");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=nticks-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],x.ptr.p_double[nlasttracklen-1]), __FILE__, __LINE__, "testssaunit.ap:1806");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
datalen = 1+hqrnduniformi(&rs, 10, _state);
forecastlen = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&x, datalen, _state);
for(i=0; i<=datalen-1; i++)
{
x.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&trend, 0, _state);
ssaforecastsequence(&state, &x, datalen, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=forecastlen, __FILE__, __LINE__, "testssaunit.ap:1817");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=forecastlen-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],x.ptr.p_double[datalen-1]), __FILE__, __LINE__, "testssaunit.ap:1821");
}
}
}
/*
* Test that for model with non-unit window, some algo being set to calculate ALL
* components, and one/few tracks which have at least window length ticks:
* * SSAGetBasis() returns full orthonormal basis
* * SSAAnalyzeLastWindow() returns last elements of track as trend and zeros
* as noise (with minor rounding error)
* * SSAAnalyzeLast() returns track as trend and zeros as noise (with
* minor rounding error possible). For NTicks>TrackLength result is correctly
* prepended with zeros.
* * SSAAnalyzeSequence() returns:
* * for sequences with length at least window width - sequence as trend,
* zeros as noise (up to machine precision)
* * for sequences shorter than window width - zeros as trend,
* sequence as noise (exactly)
* * SSAForecastLast() returns just copies of the last element
* * SSAForecastSequence() returns just copies of the last element for long enough
* sequences, zeros for shorter sequences
*/
for(pass=1; pass<=passcount; pass++)
{
/*
* Generate task; last track is stored in X, its length in NLastTrackLen
*/
windowwidth = 1+hqrnduniformi(&rs, 5, _state);
ntracks = 1+hqrnduniformi(&rs, 3, _state);
mintracklen = windowwidth;
maxtracklen = mintracklen+2*windowwidth;
ssacreate(&state, _state);
ssasetwindow(&state, windowwidth, _state);
ae_matrix_set_length(&tracksmatrix, ntracks, maxtracklen, _state);
ae_vector_set_length(&trackssizes, ntracks, _state);
nlasttracklen = 0;
for(k=0; k<=ntracks-1; k++)
{
nlasttracklen = mintracklen+hqrnduniformi(&rs, maxtracklen-mintracklen+1, _state);
ae_vector_set_length(&x, nlasttracklen, _state);
for(i=0; i<=nlasttracklen-1; i++)
{
x.ptr.p_double[i] = hqrndnormal(&rs, _state);
tracksmatrix.ptr.pp_double[k][i] = x.ptr.p_double[i];
}
trackssizes.ptr.p_int[k] = nlasttracklen;
ssaaddsequence(&state, &x, nlasttracklen, _state);
}
if( algotype==1 )
{
rmatrixrndorthogonal(windowwidth, &b, _state);
ssasetalgoprecomputed(&state, &b, windowwidth, windowwidth, _state);
}
else
{
if( algotype==2 )
{
ssasetalgotopkdirect(&state, windowwidth, _state);
}
else
{
if( algotype==3 )
{
ssasetalgotopkrealtime(&state, windowwidth, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
/*
* Test
*/
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
ssagetbasis(&state, &a, &sv, &windowwidth2, &nbasis, _state);
ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1888");
ae_set_error_flag(errorflag, nbasis!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1889");
ae_set_error_flag(errorflag, a.rows!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1890");
ae_set_error_flag(errorflag, a.cols!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1891");
ae_set_error_flag(errorflag, sv.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1892");
for(i=0; i<=windowwidth-1; i++)
{
for(j=0; j<=windowwidth-1; j++)
{
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &a.ptr.pp_double[j][0], 1, ae_v_len(0,windowwidth-1));
if( i==j )
{
v = v-1;
}
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v, _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1899");
}
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
windowwidth2 = -1;
ae_vector_set_length(&trend, 0, _state);
ae_vector_set_length(&noise, 0, _state);
ssaanalyzelastwindow(&state, &trend, &noise, &windowwidth2, _state);
ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1908");
ae_set_error_flag(errorflag, trend.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1909");
ae_set_error_flag(errorflag, noise.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:1910");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=windowwidth-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[i-windowwidth+nlasttracklen], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1915");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1916");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nanalyzed = 1+hqrnduniformi(&rs, 2*maxtracklen, _state);
ae_vector_set_length(&trend, 0, _state);
ae_vector_set_length(&noise, 0, _state);
ssaanalyzelast(&state, nanalyzed, &trend, &noise, _state);
ae_set_error_flag(errorflag, trend.cnt!=nanalyzed, __FILE__, __LINE__, "testssaunit.ap:1925");
ae_set_error_flag(errorflag, noise.cnt!=nanalyzed, __FILE__, __LINE__, "testssaunit.ap:1926");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=ae_maxint(nanalyzed-nlasttracklen, 0, _state)-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1931");
ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:1932");
}
for(i=ae_maxint(nanalyzed-nlasttracklen, 0, _state); i<=nanalyzed-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x.ptr.p_double[i-nanalyzed+nlasttracklen], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1936");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1937");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nticks = 1+hqrnduniformi(&rs, 2*windowwidth, _state);
ae_vector_set_length(&x2, nticks, _state);
for(i=0; i<=nticks-1; i++)
{
x2.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&trend, 0, _state);
ae_vector_set_length(&noise, 0, _state);
ssaanalyzesequence(&state, &x2, nticks, &trend, &noise, _state);
ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1949");
ae_set_error_flag(errorflag, noise.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1950");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=nticks-1; i++)
{
if( nticks>=windowwidth )
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i]-x2.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1957");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1958");
}
else
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(trend.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1962");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(noise.ptr.p_double[i]-x2.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testssaunit.ap:1963");
}
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nticks = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&trend, 0, _state);
ssaforecastlast(&state, nticks, &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:1972");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=nticks-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],x.ptr.p_double[nlasttracklen-1]), __FILE__, __LINE__, "testssaunit.ap:1976");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
if( windowwidth>2 )
{
datalen = 1+hqrnduniformi(&rs, windowwidth-1, _state);
forecastlen = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&x, datalen, _state);
for(i=0; i<=datalen-1; i++)
{
x.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&trend, 0, _state);
ssaforecastsequence(&state, &x, datalen, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=forecastlen, __FILE__, __LINE__, "testssaunit.ap:1990");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=forecastlen-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],0.0), __FILE__, __LINE__, "testssaunit.ap:1994");
}
}
datalen = windowwidth+hqrnduniformi(&rs, windowwidth, _state);
forecastlen = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&x, datalen, _state);
for(i=0; i<=datalen-1; i++)
{
x.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&trend, 0, _state);
ssaforecastsequence(&state, &x, datalen, forecastlen, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=forecastlen, __FILE__, __LINE__, "testssaunit.ap:2005");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=forecastlen-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],x.ptr.p_double[datalen-1]), __FILE__, __LINE__, "testssaunit.ap:2009");
}
}
}
/*
* Test that for model with
*
* * strictly non-unit window
* * some algo being set to calculate one leading component
* * a few tracks which have at least window length ticks
* * and last track which has LESS than window length minus 1 ticks
*
* we have:
*
* * SSAAnalyzeLastWindow() returns zero trend and sequence as noise,
* correctly padded by zeros
* * SSAAnalyzeLast() returns zero trend and sequence as noise,
* correctly padded by zeros
* * SSAForecastLast() returns zero trend
*
* This test checks correct handling of the situatuon when last sequence
* stored in the dataset is too short.
*/
for(pass=1; pass<=passcount; pass++)
{
/*
* Generate task; last track is stored in X, its length in NLastTrackLen
*/
windowwidth = 3+hqrnduniformi(&rs, 5, _state);
ntracks = 1+hqrnduniformi(&rs, 3, _state);
mintracklen = windowwidth;
maxtracklen = mintracklen+2*windowwidth;
ssacreate(&state, _state);
ssasetwindow(&state, windowwidth, _state);
for(k=0; k<=ntracks-1; k++)
{
nlasttracklen = mintracklen+hqrnduniformi(&rs, maxtracklen-mintracklen+1, _state);
ae_vector_set_length(&x, nlasttracklen, _state);
for(i=0; i<=nlasttracklen-1; i++)
{
x.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ssaaddsequence(&state, &x, nlasttracklen, _state);
}
nlasttracklen = windowwidth-2;
ae_vector_set_length(&x, nlasttracklen, _state);
for(i=0; i<=nlasttracklen-1; i++)
{
x.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ssaaddsequence(&state, &x, nlasttracklen, _state);
if( algotype==1 )
{
rmatrixrndorthogonal(windowwidth, &b, _state);
ssasetalgoprecomputed(&state, &b, windowwidth, 1, _state);
}
else
{
if( algotype==2 )
{
ssasetalgotopkdirect(&state, 1, _state);
}
else
{
if( algotype==3 )
{
ssasetalgotopkrealtime(&state, 1, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
/*
* Test
*/
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
windowwidth2 = -1;
ae_vector_set_length(&trend, 0, _state);
ae_vector_set_length(&noise, 0, _state);
ssaanalyzelastwindow(&state, &trend, &noise, &windowwidth2, _state);
ae_set_error_flag(errorflag, windowwidth2!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:2078");
ae_set_error_flag(errorflag, trend.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:2079");
ae_set_error_flag(errorflag, noise.cnt!=windowwidth, __FILE__, __LINE__, "testssaunit.ap:2080");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=windowwidth-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],0.0), __FILE__, __LINE__, "testssaunit.ap:2085");
j = nlasttracklen+(i-windowwidth);
if( j>=0 )
{
ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],x.ptr.p_double[j]), __FILE__, __LINE__, "testssaunit.ap:2088");
}
else
{
ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],0.0), __FILE__, __LINE__, "testssaunit.ap:2090");
}
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nanalyzed = 1+hqrnduniformi(&rs, 2*windowwidth, _state);
ae_vector_set_length(&trend, 0, _state);
ae_vector_set_length(&noise, 0, _state);
ssaanalyzelast(&state, nanalyzed, &trend, &noise, _state);
ae_set_error_flag(errorflag, trend.cnt!=nanalyzed, __FILE__, __LINE__, "testssaunit.ap:2099");
ae_set_error_flag(errorflag, noise.cnt!=nanalyzed, __FILE__, __LINE__, "testssaunit.ap:2100");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=ae_maxint(nanalyzed-nlasttracklen, 0, _state)-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:2105");
ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:2106");
}
for(i=ae_maxint(nanalyzed-nlasttracklen, 0, _state); i<=nanalyzed-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testssaunit.ap:2110");
ae_set_error_flag(errorflag, ae_fp_neq(noise.ptr.p_double[i],x.ptr.p_double[nlasttracklen+(i-nanalyzed)]), __FILE__, __LINE__, "testssaunit.ap:2111");
}
}
if( ae_fp_greater(hqrnduniformr(&rs, _state),skipprob) )
{
nticks = 1+hqrnduniformi(&rs, 10, _state);
ae_vector_set_length(&trend, 0, _state);
ssaforecastlast(&state, nticks, &trend, _state);
ae_set_error_flag(errorflag, trend.cnt!=nticks, __FILE__, __LINE__, "testssaunit.ap:2119");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=nticks-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_neq(trend.ptr.p_double[i],0.0), __FILE__, __LINE__, "testssaunit.ap:2123");
}
}
}
}
ae_frame_leave(_state);
}
ae_bool testgammafunc(ae_bool silent, ae_state *_state)
{
double threshold;
double v;
double s;
ae_bool waserrors;
ae_bool gammaerrors;
ae_bool lngammaerrors;
ae_bool result;
gammaerrors = ae_false;
lngammaerrors = ae_false;
waserrors = ae_false;
threshold = 100*ae_machineepsilon;
/*
*
*/
gammaerrors = gammaerrors||ae_fp_greater(ae_fabs(gammafunction(0.5, _state)-ae_sqrt(ae_pi, _state), _state),threshold);
gammaerrors = gammaerrors||ae_fp_greater(ae_fabs(gammafunction(1.5, _state)-0.5*ae_sqrt(ae_pi, _state), _state),threshold);
v = lngamma(0.5, &s, _state);
lngammaerrors = (lngammaerrors||ae_fp_greater(ae_fabs(v-ae_log(ae_sqrt(ae_pi, _state), _state), _state),threshold))||ae_fp_neq(s,(double)(1));
v = lngamma(1.5, &s, _state);
lngammaerrors = (lngammaerrors||ae_fp_greater(ae_fabs(v-ae_log(0.5*ae_sqrt(ae_pi, _state), _state), _state),threshold))||ae_fp_neq(s,(double)(1));
/*
* report
*/
waserrors = gammaerrors||lngammaerrors;
if( !silent )
{
printf("TESTING GAMMA FUNCTION\n");
printf("GAMMA: ");
if( gammaerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("LN GAMMA: ");
if( lngammaerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
/*
* end
*/
result = !waserrors;
return result;
}
static void testnormaldistrunit_testnormal(ae_bool* errorflag,
ae_state *_state);
static void testnormaldistrunit_testbvn(ae_bool* errorflag,
ae_state *_state);
ae_bool testnormaldistr(ae_bool silent, ae_state *_state)
{
ae_bool nrmerr;
ae_bool bvnerr;
ae_bool wereerrors;
ae_bool result;
nrmerr = ae_false;
bvnerr = ae_false;
testnormaldistrunit_testnormal(&nrmerr, _state);
testnormaldistrunit_testbvn(&bvnerr, _state);
/*
* report
*/
wereerrors = bvnerr||nrmerr;
if( !silent )
{
printf("TESTING NORMAL DISTRIBUTION\n");
printf("NORMAL DISTRIBUTION: ");
if( nrmerr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("BIVARIATE NORMALS: ");
if( bvnerr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( wereerrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
/*
* end
*/
result = !wereerrors;
return result;
}
/*************************************************************************
Normal test
-- ALGLIB --
Copyright 15.11.2019 by Bochkanov Sergey
*************************************************************************/
static void testnormaldistrunit_testnormal(ae_bool* errorflag,
ae_state *_state)
{
ae_frame _frame_block;
double v0;
double v1;
double x;
double h;
hqrndstate rs;
ae_int_t k;
ae_frame_make(_state, &_frame_block);
memset(&rs, 0, sizeof(rs));
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Test that PDF is roughly equal to derivative of CDF
*/
for(k=0; k<=999; k++)
{
x = hqrndnormal(&rs, _state);
h = 1.0E-5;
v0 = normalpdf(x, _state);
v1 = (normalcdf(x+h, _state)-normalcdf(x-h, _state))/(2*h);
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v0-v1, _state),1.0E-4), __FILE__, __LINE__, "testnormaldistrunit.ap:75");
}
ae_frame_leave(_state);
}
/*************************************************************************
Bivariate normal test
-- ALGLIB --
Copyright 15.11.2019 by Bochkanov Sergey
*************************************************************************/
static void testnormaldistrunit_testbvn(ae_bool* errorflag,
ae_state *_state)
{
ae_frame _frame_block;
double v0;
double v1;
double err;
double x;
double y;
double rho;
double h;
hqrndstate rs;
ae_int_t k;
ae_frame_make(_state, &_frame_block);
memset(&rs, 0, sizeof(rs));
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Test bivariate normal CDF values (small Rho and hard Rho)
*/
err = (double)(0);
err = ae_maxreal(err, ae_fabs(0.142221121370770000-bivariatenormalcdf(-1.060937077356340000, 1.523763953950230000, 0.344134938671007000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.001090824383322160-bivariatenormalcdf(-3.034280037001620000, 0.633583566571867000, 0.196737644948391000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000063428666799461-bivariatenormalcdf(-3.577198111015300000, -2.584892928002350000, 0.603284544092224000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000019144648137-bivariatenormalcdf(-1.053171728048290000, -2.987017621703680000, -0.659498170394145000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.972551066792029000-bivariatenormalcdf(4.785178416287600000, 1.919693671247900000, 0.261346800934746000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000608605272790-bivariatenormalcdf(-4.852815283224590000, 2.398320119295830000, 0.662485812586403000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.576135824931800000-bivariatenormalcdf(0.192020298597275000, 4.695461487450740000, -0.110028699320946000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.876357061322732000-bivariatenormalcdf(2.095780141251770000, 1.211768206209080000, 0.397007061864995000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.002969212104812400-bivariatenormalcdf(-2.654007687508430000, 1.340051767837440000, -0.233916559318503000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000377048151161364-bivariatenormalcdf(1.128363097510700000, -2.781006578069910000, -0.642877478801918000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.995657061734790000-bivariatenormalcdf(3.966506850977000000, 2.626841258388710000, 0.291409185863929000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.003282876365551870-bivariatenormalcdf(-2.717530641700190000, 3.217920162027340000, -0.101773464540366000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.002099371685469470-bivariatenormalcdf(-1.811681729272450000, -2.262911120125770000, 0.361735313431128000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.648944114852307000-bivariatenormalcdf(1.861468373436860000, 0.432740073549983000, 0.092845182466246300, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000094851728-bivariatenormalcdf(-4.898527851968480000, -3.491204153631050000, -0.010492822687090300, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000416778593465223-bivariatenormalcdf(-3.341356669094100000, 1.862802982022170000, 0.398642687655347000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.741640376816388000-bivariatenormalcdf(4.687494092358740000, 0.648415139929991000, -0.692925257444683000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.868844042717264000-bivariatenormalcdf(2.369093655782270000, 1.148153167494120000, 0.297877516862745000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.999356215351682000-bivariatenormalcdf(4.352384277131720000, 3.221749932900420000, -0.257163446680127000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.998760969813713000-bivariatenormalcdf(3.422289814750960000, 3.111433954663520000, 0.198012195099628000, _state), _state), _state);
ae_set_error_flag(errorflag, ae_fp_greater(err,1.0E-12), __FILE__, __LINE__, "testnormaldistrunit.ap:121");
err = (double)(0);
err = ae_maxreal(err, ae_fabs(0.080575405379940000-bivariatenormalcdf(-1.060937077356340000, 1.523763953950230000, -0.999999999999000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000000000007-bivariatenormalcdf(-1.060937077356340000, -1.060937077356340000, -0.999999999999000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000000000007-bivariatenormalcdf(-1.060937077356340000, -1.060937077354570000, -0.999999999999000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000000000016-bivariatenormalcdf(-3.034280037001620000, 0.633583566571867000, -0.999999999990000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-3.034280037001620000, -3.034280037001620000, -0.999999999990000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-3.034280037001620000, -3.034280036974940000, -0.999999999990000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-3.577198111015300000, -2.584892928002350000, -0.999999999900000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-3.577198111015300000, -3.577198111015300000, -0.999999999900000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-3.577198111015300000, -3.577198111015280000, -0.999999999900000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-1.053171728048290000, -2.987017621703680000, -0.999999999000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000000000021-bivariatenormalcdf(-1.053171728048290000, -1.053171728048290000, -0.999999999000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000000000014-bivariatenormalcdf(-1.053171728048290000, -1.052982935276290000, -0.999999999000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.972550843757766000-bivariatenormalcdf(4.785178416287600000, 1.919693671247900000, -0.999999990000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.999998291644901000-bivariatenormalcdf(4.785178416287600000, 4.785178416287600000, -0.999999990000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.999998291644901000-bivariatenormalcdf(4.785178416287600000, 4.785178416295720000, -0.999999990000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-4.852815283224590000, 2.398320119295830000, -0.999999900000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-4.852815283224590000, -4.852815283224590000, -0.999999900000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-4.852815283224590000, -4.852815283224590000, -0.999999900000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.576135517318684000-bivariatenormalcdf(0.192020298597275000, 4.695461487450740000, -0.999999000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.152273694692214000-bivariatenormalcdf(0.192020298597275000, 0.192020298597275000, -0.999999000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.152273697664791000-bivariatenormalcdf(0.192020298597275000, 0.192020306187062000, -0.999999000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.869148589647661000-bivariatenormalcdf(2.095780141251770000, 1.211768206209080000, -0.999990000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.963898301217005000-bivariatenormalcdf(2.095780141251770000, 2.095780141251770000, -0.999990000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.963898301217035000-bivariatenormalcdf(2.095780141251770000, 2.095780141252440000, -0.999990000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-2.654007687508430000, 1.340051767837440000, -0.999900000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-2.654007687508430000, -2.654007687508430000, -0.999900000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-2.654007687508430000, -2.654007613149620000, -0.999900000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000000000019-bivariatenormalcdf(1.128363097510700000, -2.781006578069910000, -0.999000000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.740833394117601000-bivariatenormalcdf(1.128363097510700000, 1.128363097510700000, -0.999000000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.740862731628071000-bivariatenormalcdf(1.128363097510700000, 1.128502099120660000, -0.999000000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.995654456762395000-bivariatenormalcdf(3.966506850977000000, 2.626841258388710000, -0.990000000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.999927066319845000-bivariatenormalcdf(3.966506850977000000, 3.966506850977000000, -0.990000000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.999927066319846000-bivariatenormalcdf(3.966506850977000000, 3.966506850981670000, -0.990000000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.002769246133985220-bivariatenormalcdf(-2.717530641700190000, 3.217920162027340000, -0.900000000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-2.717530641700190000, -2.717530641700190000, -0.900000000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000000000000000-bivariatenormalcdf(-2.717530641700190000, -2.717530635181090000, -0.900000000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.010079636581695100-bivariatenormalcdf(-1.811681729272450000, -2.262911120125770000, 0.900000000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.021493462833838000-bivariatenormalcdf(-1.811681729272450000, -1.811681729272450000, 0.900000000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.021493462833871500-bivariatenormalcdf(-1.811681729272450000, -1.811681729271170000, 0.900000000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.667398193291227000-bivariatenormalcdf(1.861468373436860000, 0.432740073549983000, 0.990000000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.964688949692122000-bivariatenormalcdf(1.861468373436860000, 1.861468373436860000, 0.990000000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.964688949699170000-bivariatenormalcdf(1.861468373436860000, 1.861468373617680000, 0.990000000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000482786767864-bivariatenormalcdf(-4.898527851968480000, -3.491204153631050000, 0.999000000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000439041574222-bivariatenormalcdf(-4.898527851968480000, -4.898527851968480000, 0.999000000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000000439041575582-bivariatenormalcdf(-4.898527851968480000, -4.898527850755250000, 0.999000000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000416850246666766-bivariatenormalcdf(-3.341356669094100000, 1.862802982022170000, 0.999900000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000408379488679640-bivariatenormalcdf(-3.341356669094100000, -3.341356669094100000, 0.999900000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000408379488680111-bivariatenormalcdf(-3.341356669094100000, -3.341356669093450000, 0.999900000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.741641759669778000-bivariatenormalcdf(4.687494092358740000, 0.648415139929991000, 0.999990000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.999998605095178000-bivariatenormalcdf(4.687494092358740000, 4.687494092358740000, 0.999990000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.999998606247630000-bivariatenormalcdf(4.687494092358740000, 4.687843556049730000, 0.999990000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.874547330614982000-bivariatenormalcdf(2.369093655782270000, 1.148153167494120000, 0.999999000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.991070530231016000-bivariatenormalcdf(2.369093655782270000, 2.369093655782270000, 0.999999000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.991070530231065000-bivariatenormalcdf(2.369093655782270000, 2.369093655786410000, 0.999999000000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.999362948580782000-bivariatenormalcdf(4.352384277131720000, 3.221749932900420000, 0.999999900000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.999993261271150000-bivariatenormalcdf(4.352384277131720000, 4.352384277131720000, 0.999999900000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.999993261272904000-bivariatenormalcdf(4.352384277131720000, 4.352384391237480000, 0.999999900000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.999069094420465000-bivariatenormalcdf(3.422289814750960000, 3.111433954663520000, 0.999999990000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.999689455134645000-bivariatenormalcdf(3.422289814750960000, 3.422289814750960000, 0.999999990000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.999689455134658000-bivariatenormalcdf(3.422289814750960000, 3.422289814777010000, 0.999999990000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.294719708527162000-bivariatenormalcdf(-0.539648565868907000, 2.177679562057720000, 0.999999999000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.294713555379044000-bivariatenormalcdf(-0.539648565868907000, -0.539648565868907000, 0.999999999000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.294718518285085000-bivariatenormalcdf(-0.539648565868907000, -0.539602058260055000, 0.999999999000000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000002811467986141-bivariatenormalcdf(-4.540093229575050000, 2.436946780486250000, 0.999999999900000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000002811392754616-bivariatenormalcdf(-4.540093229575050000, -4.540093229575050000, 0.999999999900000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000002811467986126-bivariatenormalcdf(-4.540093229575050000, -4.540001786779430000, 0.999999999900000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.565106870340374000-bivariatenormalcdf(0.163929988133744000, 3.995097146641120000, 0.999999999990000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.565106168077456000-bivariatenormalcdf(0.163929988133744000, 0.163929988133744000, 0.999999999990000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.565106168096292000-bivariatenormalcdf(0.163929988133744000, 0.163929988229317000, 0.999999999990000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.000064751025417698-bivariatenormalcdf(3.421155338081630000, -3.827403648909790000, 0.999999999999000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.999688220825439000-bivariatenormalcdf(3.421155338081630000, 3.421155338081630000, 0.999999999999000000, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(0.999688221472430000-bivariatenormalcdf(3.421155338081630000, 3.421174755498880000, 0.999999999999000000, _state), _state), _state);
ae_set_error_flag(errorflag, ae_fp_greater(err,1.0E-12), __FILE__, __LINE__, "testnormaldistrunit.ap:195");
/*
* Test that BVN PDF is roughly equal to derivative of BVN CDF
*/
for(k=0; k<=999; k++)
{
/*
* Generate trial point
*/
x = hqrndnormal(&rs, _state);
y = hqrndnormal(&rs, _state);
rho = (double)(0);
/*
* Compare two values: normal PDF and differentiation of normal CDF with step H
*/
h = 1.0E-5;
v0 = bivariatenormalpdf(x, y, rho, _state);
v1 = (bivariatenormalcdf(x+h, y+h, rho, _state)+bivariatenormalcdf(x-h, y-h, rho, _state)-bivariatenormalcdf(x+h, y-h, rho, _state)-bivariatenormalcdf(x-h, y+h, rho, _state))/ae_sqr(2*h, _state);
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v0-v1, _state),1.0E-4), __FILE__, __LINE__, "testnormaldistrunit.ap:215");
}
ae_frame_leave(_state);
}
static void testlinregunit_generaterandomtask(double xl,
double xr,
ae_bool randomx,
double ymin,
double ymax,
double smin,
double smax,
ae_int_t n,
/* Real */ ae_matrix* xy,
/* Real */ ae_vector* s,
ae_state *_state);
static void testlinregunit_generatetask(double a,
double b,
double xl,
double xr,
ae_bool randomx,
double smin,
double smax,
ae_int_t n,
/* Real */ ae_matrix* xy,
/* Real */ ae_vector* s,
ae_state *_state);
static void testlinregunit_filltaskwithy(double a,
double b,
ae_int_t n,
/* Real */ ae_matrix* xy,
/* Real */ ae_vector* s,
ae_state *_state);
static double testlinregunit_generatenormal(double mean,
double sigma,
ae_state *_state);
static void testlinregunit_calculatemv(/* Real */ ae_vector* x,
ae_int_t n,
double* mean,
double* means,
double* stddev,
double* stddevs,
ae_state *_state);
static void testlinregunit_unsetlr(linearmodel* lr, ae_state *_state);
ae_bool testlinreg(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
double sigmathreshold;
ae_int_t maxn;
ae_int_t passcount;
ae_int_t estpasscount;
double threshold;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t tmpi;
ae_int_t pass;
ae_int_t epass;
ae_int_t m;
ae_int_t tasktype;
ae_int_t modeltype;
ae_int_t m1;
ae_int_t m2;
ae_int_t n1;
ae_int_t n2;
ae_int_t info;
ae_int_t info2;
ae_matrix xy;
ae_matrix xy2;
ae_vector s;
ae_vector s2;
ae_vector w2;
ae_vector x;
ae_vector ta;
ae_vector tb;
ae_vector tc;
ae_vector xy0;
ae_vector tmpweights;
linearmodel w;
linearmodel wt;
linearmodel wt2;
ae_vector x1;
ae_vector x2;
double y1;
double y2;
ae_bool allsame;
double ea;
double eb;
double varatested;
double varbtested;
double a;
double b;
double vara;
double varb;
double a2;
double b2;
double covab;
double corrab;
double p;
ae_int_t qcnt;
ae_vector qtbl;
ae_vector qvals;
ae_vector qsigma;
lrreport ar;
lrreport ar2;
double f;
double fp;
double fm;
double v;
double vv;
double cvrmserror;
double cvavgerror;
double cvavgrelerror;
double rmserror;
double avgerror;
double avgrelerror;
ae_bool nondefect;
double sinshift;
double tasklevel;
double noiselevel;
double hstep;
double sigma;
double mean;
double means;
double stddev;
double stddevs;
ae_bool slcerrors;
ae_bool slerrors;
ae_bool grcoverrors;
ae_bool gropterrors;
ae_bool gresterrors;
ae_bool grothererrors;
ae_bool grconverrors;
ae_bool waserrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
memset(&xy2, 0, sizeof(xy2));
memset(&s, 0, sizeof(s));
memset(&s2, 0, sizeof(s2));
memset(&w2, 0, sizeof(w2));
memset(&x, 0, sizeof(x));
memset(&ta, 0, sizeof(ta));
memset(&tb, 0, sizeof(tb));
memset(&tc, 0, sizeof(tc));
memset(&xy0, 0, sizeof(xy0));
memset(&tmpweights, 0, sizeof(tmpweights));
memset(&w, 0, sizeof(w));
memset(&wt, 0, sizeof(wt));
memset(&wt2, 0, sizeof(wt2));
memset(&x1, 0, sizeof(x1));
memset(&x2, 0, sizeof(x2));
memset(&qtbl, 0, sizeof(qtbl));
memset(&qvals, 0, sizeof(qvals));
memset(&qsigma, 0, sizeof(qsigma));
memset(&ar, 0, sizeof(ar));
memset(&ar2, 0, sizeof(ar2));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ta, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tb, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xy0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmpweights, 0, DT_REAL, _state, ae_true);
_linearmodel_init(&w, _state, ae_true);
_linearmodel_init(&wt, _state, ae_true);
_linearmodel_init(&wt2, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&qtbl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&qvals, 0, DT_REAL, _state, ae_true);
ae_vector_init(&qsigma, 0, DT_REAL, _state, ae_true);
_lrreport_init(&ar, _state, ae_true);
_lrreport_init(&ar2, _state, ae_true);
/*
* Primary settings
*/
maxn = 40;
passcount = 3;
estpasscount = 1000;
sigmathreshold = (double)(7);
threshold = 1000000*ae_machineepsilon;
slerrors = ae_false;
slcerrors = ae_false;
grcoverrors = ae_false;
gropterrors = ae_false;
gresterrors = ae_false;
grothererrors = ae_false;
grconverrors = ae_false;
waserrors = ae_false;
/*
* Quantiles table setup
*/
qcnt = 5;
ae_vector_set_length(&qtbl, qcnt-1+1, _state);
ae_vector_set_length(&qvals, qcnt-1+1, _state);
ae_vector_set_length(&qsigma, qcnt-1+1, _state);
qtbl.ptr.p_double[0] = 0.5;
qtbl.ptr.p_double[1] = 0.25;
qtbl.ptr.p_double[2] = 0.10;
qtbl.ptr.p_double[3] = 0.05;
qtbl.ptr.p_double[4] = 0.025;
for(i=0; i<=qcnt-1; i++)
{
qsigma.ptr.p_double[i] = ae_sqrt(qtbl.ptr.p_double[i]*(1-qtbl.ptr.p_double[i])/estpasscount, _state);
}
/*
* Other setup
*/
ae_vector_set_length(&ta, estpasscount-1+1, _state);
ae_vector_set_length(&tb, estpasscount-1+1, _state);
/*
* Test straight line regression
*/
for(n=2; n<=maxn; n++)
{
/*
* Fail/pass test
*/
testlinregunit_generaterandomtask((double)(-1), (double)(1), ae_false, (double)(-1), (double)(1), (double)(1), (double)(2), n, &xy, &s, _state);
lrlines(&xy, &s, n, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state);
slcerrors = slcerrors||info!=1;
testlinregunit_generaterandomtask((double)(1), (double)(1), ae_false, (double)(-1), (double)(1), (double)(1), (double)(2), n, &xy, &s, _state);
lrlines(&xy, &s, n, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state);
slcerrors = slcerrors||info!=-3;
testlinregunit_generaterandomtask((double)(-1), (double)(1), ae_false, (double)(-1), (double)(1), (double)(-1), (double)(-1), n, &xy, &s, _state);
lrlines(&xy, &s, n, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state);
slcerrors = slcerrors||info!=-2;
testlinregunit_generaterandomtask((double)(-1), (double)(1), ae_false, (double)(-1), (double)(1), (double)(2), (double)(1), 2, &xy, &s, _state);
lrlines(&xy, &s, 1, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state);
slcerrors = slcerrors||info!=-1;
/*
* Multipass tests
*/
for(pass=1; pass<=passcount; pass++)
{
/*
* Test S variant against non-S variant
*/
ea = 2*ae_randomreal(_state)-1;
eb = 2*ae_randomreal(_state)-1;
testlinregunit_generatetask(ea, eb, -5*ae_randomreal(_state), 5*ae_randomreal(_state), ae_fp_greater(ae_randomreal(_state),0.5), (double)(1), (double)(1), n, &xy, &s, _state);
lrlines(&xy, &s, n, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state);
lrline(&xy, n, &info2, &a2, &b2, _state);
if( info!=1||info2!=1 )
{
slcerrors = ae_true;
}
else
{
slerrors = (slerrors||ae_fp_greater(ae_fabs(a-a2, _state),threshold))||ae_fp_greater(ae_fabs(b-b2, _state),threshold);
}
/*
* Test for A/B
*
* Generate task with exact, non-perturbed y[i],
* then make non-zero s[i]
*/
ea = 2*ae_randomreal(_state)-1;
eb = 2*ae_randomreal(_state)-1;
testlinregunit_generatetask(ea, eb, -5*ae_randomreal(_state), 5*ae_randomreal(_state), n>4, 0.0, 0.0, n, &xy, &s, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = 1+ae_randomreal(_state);
}
lrlines(&xy, &s, n, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state);
if( info!=1 )
{
slcerrors = ae_true;
}
else
{
slerrors = (slerrors||ae_fp_greater(ae_fabs(a-ea, _state),0.001))||ae_fp_greater(ae_fabs(b-eb, _state),0.001);
}
/*
* Test for VarA, VarB, P (P is being tested only for N>2)
*/
for(i=0; i<=qcnt-1; i++)
{
qvals.ptr.p_double[i] = (double)(0);
}
ea = 2*ae_randomreal(_state)-1;
eb = 2*ae_randomreal(_state)-1;
testlinregunit_generatetask(ea, eb, -5*ae_randomreal(_state), 5*ae_randomreal(_state), n>4, 1.0, 2.0, n, &xy, &s, _state);
lrlines(&xy, &s, n, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state);
if( info!=1 )
{
slcerrors = ae_true;
continue;
}
varatested = vara;
varbtested = varb;
for(epass=0; epass<=estpasscount-1; epass++)
{
/*
* Generate
*/
testlinregunit_filltaskwithy(ea, eb, n, &xy, &s, _state);
lrlines(&xy, &s, n, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state);
if( info!=1 )
{
slcerrors = ae_true;
continue;
}
/*
* A, B, P
* (P is being tested for uniformity, additional p-tests are below)
*/
ta.ptr.p_double[epass] = a;
tb.ptr.p_double[epass] = b;
for(i=0; i<=qcnt-1; i++)
{
if( ae_fp_less_eq(p,qtbl.ptr.p_double[i]) )
{
qvals.ptr.p_double[i] = qvals.ptr.p_double[i]+(double)1/(double)estpasscount;
}
}
}
testlinregunit_calculatemv(&ta, estpasscount, &mean, &means, &stddev, &stddevs, _state);
slerrors = slerrors||ae_fp_greater_eq(ae_fabs(mean-ea, _state)/means,sigmathreshold);
slerrors = slerrors||ae_fp_greater_eq(ae_fabs(stddev-ae_sqrt(varatested, _state), _state)/stddevs,sigmathreshold);
testlinregunit_calculatemv(&tb, estpasscount, &mean, &means, &stddev, &stddevs, _state);
slerrors = slerrors||ae_fp_greater_eq(ae_fabs(mean-eb, _state)/means,sigmathreshold);
slerrors = slerrors||ae_fp_greater_eq(ae_fabs(stddev-ae_sqrt(varbtested, _state), _state)/stddevs,sigmathreshold);
if( n>2 )
{
for(i=0; i<=qcnt-1; i++)
{
if( ae_fp_greater(ae_fabs(qtbl.ptr.p_double[i]-qvals.ptr.p_double[i], _state)/qsigma.ptr.p_double[i],sigmathreshold) )
{
slerrors = ae_true;
}
}
}
/*
* Additional tests for P: correlation with fit quality
*/
if( n>2 )
{
testlinregunit_generatetask(ea, eb, -5*ae_randomreal(_state), 5*ae_randomreal(_state), ae_false, 0.0, 0.0, n, &xy, &s, _state);
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = 1+ae_randomreal(_state);
}
lrlines(&xy, &s, n, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state);
if( info!=1 )
{
slcerrors = ae_true;
continue;
}
slerrors = slerrors||ae_fp_less(p,0.999);
testlinregunit_generatetask((double)(0), (double)(0), -5*ae_randomreal(_state), 5*ae_randomreal(_state), ae_false, 1.0, 1.0, n, &xy, &s, _state);
for(i=0; i<=n-1; i++)
{
if( i%2==0 )
{
xy.ptr.pp_double[i][1] = 5.0;
}
else
{
xy.ptr.pp_double[i][1] = -5.0;
}
}
if( n%2!=0 )
{
xy.ptr.pp_double[n-1][1] = (double)(0);
}
lrlines(&xy, &s, n, &info, &a, &b, &vara, &varb, &covab, &corrab, &p, _state);
if( info!=1 )
{
slcerrors = ae_true;
continue;
}
slerrors = slerrors||ae_fp_greater(p,0.001);
}
}
}
/*
* General regression tests:
*/
/*
* Simple linear tests (small sample, optimum point, covariance)
*/
for(n=3; n<=maxn; n++)
{
ae_vector_set_length(&s, n-1+1, _state);
/*
* Linear tests:
* a. random points, sigmas
* b. no sigmas
*/
ae_matrix_set_length(&xy, n-1+1, 1+1, _state);
for(i=0; i<=n-1; i++)
{
xy.ptr.pp_double[i][0] = 2*ae_randomreal(_state)-1;
xy.ptr.pp_double[i][1] = 2*ae_randomreal(_state)-1;
s.ptr.p_double[i] = 1+ae_randomreal(_state);
}
lrbuilds(&xy, &s, n, 1, &info, &wt, &ar, _state);
if( info!=1 )
{
grconverrors = ae_true;
continue;
}
lrunpack(&wt, &tmpweights, &tmpi, _state);
lrlines(&xy, &s, n, &info2, &a, &b, &vara, &varb, &covab, &corrab, &p, _state);
gropterrors = gropterrors||ae_fp_greater(ae_fabs(a-tmpweights.ptr.p_double[1], _state),threshold);
gropterrors = gropterrors||ae_fp_greater(ae_fabs(b-tmpweights.ptr.p_double[0], _state),threshold);
grcoverrors = grcoverrors||ae_fp_greater(ae_fabs(vara-ar.c.ptr.pp_double[1][1], _state),threshold);
grcoverrors = grcoverrors||ae_fp_greater(ae_fabs(varb-ar.c.ptr.pp_double[0][0], _state),threshold);
grcoverrors = grcoverrors||ae_fp_greater(ae_fabs(covab-ar.c.ptr.pp_double[1][0], _state),threshold);
grcoverrors = grcoverrors||ae_fp_greater(ae_fabs(covab-ar.c.ptr.pp_double[0][1], _state),threshold);
lrbuild(&xy, n, 1, &info, &wt, &ar, _state);
if( info!=1 )
{
grconverrors = ae_true;
continue;
}
lrunpack(&wt, &tmpweights, &tmpi, _state);
lrline(&xy, n, &info2, &a, &b, _state);
gropterrors = gropterrors||ae_fp_greater(ae_fabs(a-tmpweights.ptr.p_double[1], _state),threshold);
gropterrors = gropterrors||ae_fp_greater(ae_fabs(b-tmpweights.ptr.p_double[0], _state),threshold);
}
/*
* S covariance versus S-less covariance.
* Slightly skewed task, large sample size.
* Will S-less subroutine estimate covariance matrix good enough?
*/
n = 1000+ae_randominteger(3000, _state);
sigma = 0.1+ae_randomreal(_state)*1.9;
ae_matrix_set_length(&xy, n-1+1, 1+1, _state);
ae_vector_set_length(&s, n-1+1, _state);
for(i=0; i<=n-1; i++)
{
xy.ptr.pp_double[i][0] = 1.5*ae_randomreal(_state)-0.5;
xy.ptr.pp_double[i][1] = 1.2*xy.ptr.pp_double[i][0]-0.3+testlinregunit_generatenormal((double)(0), sigma, _state);
s.ptr.p_double[i] = sigma;
}
lrbuild(&xy, n, 1, &info, &wt, &ar, _state);
lrlines(&xy, &s, n, &info2, &a, &b, &vara, &varb, &covab, &corrab, &p, _state);
if( info!=1||info2!=1 )
{
grconverrors = ae_true;
}
else
{
grcoverrors = grcoverrors||ae_fp_greater(ae_fabs(ae_log(ar.c.ptr.pp_double[0][0]/varb, _state), _state),ae_log(1.2, _state));
grcoverrors = grcoverrors||ae_fp_greater(ae_fabs(ae_log(ar.c.ptr.pp_double[1][1]/vara, _state), _state),ae_log(1.2, _state));
grcoverrors = grcoverrors||ae_fp_greater(ae_fabs(ae_log(ar.c.ptr.pp_double[0][1]/covab, _state), _state),ae_log(1.2, _state));
grcoverrors = grcoverrors||ae_fp_greater(ae_fabs(ae_log(ar.c.ptr.pp_double[1][0]/covab, _state), _state),ae_log(1.2, _state));
}
/*
* General tests:
* * basis functions - up to cubic
* * task types:
* * data set is noisy sine half-period with random shift
* * tests:
* unpacking/packing
* optimality
* error estimates
* * tasks:
* 0 = noised sine
* 1 = degenerate task with 1-of-n encoded categorical variables
* 2 = random task with large variation (for 1-type models)
* 3 = random task with small variation (for 1-type models)
*
* Additional tasks TODO
* specially designed task with defective vectors which leads to
* the failure of the fast CV formula.
*
*/
m1 = 0;
m2 = -1;
n1 = 0;
n2 = -1;
for(modeltype=0; modeltype<=1; modeltype++)
{
for(tasktype=0; tasktype<=3; tasktype++)
{
if( tasktype==0 )
{
m1 = 1;
m2 = 3;
}
if( tasktype==1 )
{
m1 = 9;
m2 = 9;
}
if( tasktype==2||tasktype==3 )
{
m1 = 9;
m2 = 9;
}
for(m=m1; m<=m2; m++)
{
if( tasktype==0 )
{
n1 = m+3;
n2 = m+20;
}
if( tasktype==1 )
{
n1 = 70+ae_randominteger(70, _state);
n2 = n1;
}
if( tasktype==2||tasktype==3 )
{
n1 = 100;
n2 = n1;
}
for(n=n1; n<=n2; n++)
{
ae_matrix_set_length(&xy, n-1+1, m+1, _state);
ae_vector_set_length(&xy0, n-1+1, _state);
ae_vector_set_length(&s, n-1+1, _state);
hstep = 0.001;
noiselevel = 0.2;
/*
* Prepare task
*/
if( tasktype==0 )
{
for(i=0; i<=n-1; i++)
{
xy.ptr.pp_double[i][0] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=n-1; i++)
{
for(j=1; j<=m-1; j++)
{
xy.ptr.pp_double[i][j] = xy.ptr.pp_double[i][0]*xy.ptr.pp_double[i][j-1];
}
}
sinshift = ae_randomreal(_state)*ae_pi;
for(i=0; i<=n-1; i++)
{
xy0.ptr.p_double[i] = ae_sin(sinshift+ae_pi*0.5*(xy.ptr.pp_double[i][0]+1), _state);
xy.ptr.pp_double[i][m] = xy0.ptr.p_double[i]+noiselevel*testlinregunit_generatenormal((double)(0), (double)(1), _state);
}
}
if( tasktype==1 )
{
ae_assert(m==9, "Assertion failed", _state);
ae_vector_set_length(&ta, 8+1, _state);
ta.ptr.p_double[0] = (double)(1);
ta.ptr.p_double[1] = (double)(2);
ta.ptr.p_double[2] = (double)(3);
ta.ptr.p_double[3] = 0.25;
ta.ptr.p_double[4] = 0.5;
ta.ptr.p_double[5] = 0.75;
ta.ptr.p_double[6] = 0.06;
ta.ptr.p_double[7] = 0.12;
ta.ptr.p_double[8] = 0.18;
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
xy.ptr.pp_double[i][j] = (double)(0);
}
xy.ptr.pp_double[i][0+i%3] = (double)(1);
xy.ptr.pp_double[i][3+i/3%3] = (double)(1);
xy.ptr.pp_double[i][6+i/9%3] = (double)(1);
v = ae_v_dotproduct(&xy.ptr.pp_double[i][0], 1, &ta.ptr.p_double[0], 1, ae_v_len(0,8));
xy0.ptr.p_double[i] = v;
xy.ptr.pp_double[i][m] = v+noiselevel*testlinregunit_generatenormal((double)(0), (double)(1), _state);
}
}
if( tasktype==2||tasktype==3 )
{
ae_assert(m==9, "Assertion failed", _state);
ae_vector_set_length(&ta, 8+1, _state);
ta.ptr.p_double[0] = (double)(1);
ta.ptr.p_double[1] = (double)(-2);
ta.ptr.p_double[2] = (double)(3);
ta.ptr.p_double[3] = 0.25;
ta.ptr.p_double[4] = -0.5;
ta.ptr.p_double[5] = 0.75;
ta.ptr.p_double[6] = -0.06;
ta.ptr.p_double[7] = 0.12;
ta.ptr.p_double[8] = -0.18;
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
if( tasktype==2 )
{
xy.ptr.pp_double[i][j] = 1+testlinregunit_generatenormal((double)(0), (double)(3), _state);
}
else
{
xy.ptr.pp_double[i][j] = 1+testlinregunit_generatenormal((double)(0), 0.05, _state);
}
}
v = ae_v_dotproduct(&xy.ptr.pp_double[i][0], 1, &ta.ptr.p_double[0], 1, ae_v_len(0,8));
xy0.ptr.p_double[i] = v;
xy.ptr.pp_double[i][m] = v+noiselevel*testlinregunit_generatenormal((double)(0), (double)(1), _state);
}
}
for(i=0; i<=n-1; i++)
{
s.ptr.p_double[i] = 1+ae_randomreal(_state);
}
/*
* Solve (using S-variant, non-S-variant is not tested)
*/
if( modeltype==0 )
{
lrbuilds(&xy, &s, n, m, &info, &wt, &ar, _state);
}
else
{
lrbuildzs(&xy, &s, n, m, &info, &wt, &ar, _state);
}
if( info!=1 )
{
grconverrors = ae_true;
continue;
}
lrunpack(&wt, &tmpweights, &tmpi, _state);
/*
* LRProcess test
*/
ae_vector_set_length(&x, m-1+1, _state);
v = tmpweights.ptr.p_double[m];
for(i=0; i<=m-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
v = v+tmpweights.ptr.p_double[i]*x.ptr.p_double[i];
}
grothererrors = grothererrors||ae_fp_greater(ae_fabs(v-lrprocess(&wt, &x, _state), _state)/ae_maxreal(ae_fabs(v, _state), (double)(1), _state),threshold);
/*
* LRPack test
*/
lrpack(&tmpweights, m, &wt2, _state);
ae_vector_set_length(&x, m-1+1, _state);
for(i=0; i<=m-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
v = lrprocess(&wt, &x, _state);
grothererrors = grothererrors||ae_fp_greater(ae_fabs(v-lrprocess(&wt2, &x, _state), _state)/ae_fabs(v, _state),threshold);
/*
* Optimality test
*/
for(k=0; k<=m; k++)
{
if( modeltype==1&&k==m )
{
/*
* 0-type models (with non-zero constant term)
* are tested for optimality of all coefficients.
*
* 1-type models (with zero constant term)
* are tested for optimality of non-constant terms only.
*/
continue;
}
f = (double)(0);
fp = (double)(0);
fm = (double)(0);
for(i=0; i<=n-1; i++)
{
v = tmpweights.ptr.p_double[m];
for(j=0; j<=m-1; j++)
{
v = v+xy.ptr.pp_double[i][j]*tmpweights.ptr.p_double[j];
}
f = f+ae_sqr((v-xy.ptr.pp_double[i][m])/s.ptr.p_double[i], _state);
if( kptr.pp_double[i][0] = xl+(xr-xl)*ae_randomreal(_state);
}
else
{
xy->ptr.pp_double[i][0] = xl+(xr-xl)*i/(n-1);
}
xy->ptr.pp_double[i][1] = ymin+(ymax-ymin)*ae_randomreal(_state);
s->ptr.p_double[i] = smin+(smax-smin)*ae_randomreal(_state);
}
}
/*************************************************************************
Task generation.
*************************************************************************/
static void testlinregunit_generatetask(double a,
double b,
double xl,
double xr,
ae_bool randomx,
double smin,
double smax,
ae_int_t n,
/* Real */ ae_matrix* xy,
/* Real */ ae_vector* s,
ae_state *_state)
{
ae_int_t i;
ae_matrix_set_length(xy, n-1+1, 1+1, _state);
ae_vector_set_length(s, n-1+1, _state);
for(i=0; i<=n-1; i++)
{
if( randomx )
{
xy->ptr.pp_double[i][0] = xl+(xr-xl)*ae_randomreal(_state);
}
else
{
xy->ptr.pp_double[i][0] = xl+(xr-xl)*i/(n-1);
}
s->ptr.p_double[i] = smin+(smax-smin)*ae_randomreal(_state);
xy->ptr.pp_double[i][1] = a+b*xy->ptr.pp_double[i][0]+testlinregunit_generatenormal((double)(0), s->ptr.p_double[i], _state);
}
}
/*************************************************************************
Task generation.
y[i] are filled based on A, B, X[I], S[I]
*************************************************************************/
static void testlinregunit_filltaskwithy(double a,
double b,
ae_int_t n,
/* Real */ ae_matrix* xy,
/* Real */ ae_vector* s,
ae_state *_state)
{
ae_int_t i;
for(i=0; i<=n-1; i++)
{
xy->ptr.pp_double[i][1] = a+b*xy->ptr.pp_double[i][0]+testlinregunit_generatenormal((double)(0), s->ptr.p_double[i], _state);
}
}
/*************************************************************************
Normal random numbers
*************************************************************************/
static double testlinregunit_generatenormal(double mean,
double sigma,
ae_state *_state)
{
double u;
double v;
double sum;
double result;
result = mean;
for(;;)
{
u = (2*ae_randominteger(2, _state)-1)*ae_randomreal(_state);
v = (2*ae_randominteger(2, _state)-1)*ae_randomreal(_state);
sum = u*u+v*v;
if( ae_fp_less(sum,(double)(1))&&ae_fp_greater(sum,(double)(0)) )
{
sum = ae_sqrt(-2*ae_log(sum, _state)/sum, _state);
result = sigma*u*sum+mean;
break;
}
}
return result;
}
/*************************************************************************
Moments estimates and their errors
*************************************************************************/
static void testlinregunit_calculatemv(/* Real */ ae_vector* x,
ae_int_t n,
double* mean,
double* means,
double* stddev,
double* stddevs,
ae_state *_state)
{
ae_int_t i;
double v1;
double v2;
double variance;
*mean = 0;
*means = 0;
*stddev = 0;
*stddevs = 0;
*mean = (double)(0);
*means = (double)(1);
*stddev = (double)(0);
*stddevs = (double)(1);
variance = (double)(0);
if( n<=1 )
{
return;
}
/*
* Mean
*/
for(i=0; i<=n-1; i++)
{
*mean = *mean+x->ptr.p_double[i];
}
*mean = *mean/n;
/*
* Variance (using corrected two-pass algorithm)
*/
if( n!=1 )
{
v1 = (double)(0);
for(i=0; i<=n-1; i++)
{
v1 = v1+ae_sqr(x->ptr.p_double[i]-(*mean), _state);
}
v2 = (double)(0);
for(i=0; i<=n-1; i++)
{
v2 = v2+(x->ptr.p_double[i]-(*mean));
}
v2 = ae_sqr(v2, _state)/n;
variance = (v1-v2)/(n-1);
if( ae_fp_less(variance,(double)(0)) )
{
variance = (double)(0);
}
*stddev = ae_sqrt(variance, _state);
}
/*
* Errors
*/
*means = *stddev/ae_sqrt((double)(n), _state);
*stddevs = *stddev*ae_sqrt((double)(2), _state)/ae_sqrt((double)(n-1), _state);
}
/*************************************************************************
Unsets LR
*************************************************************************/
static void testlinregunit_unsetlr(linearmodel* lr, ae_state *_state)
{
ae_frame _frame_block;
ae_matrix xy;
ae_int_t info;
lrreport rep;
ae_int_t i;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
memset(&rep, 0, sizeof(rep));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_lrreport_init(&rep, _state, ae_true);
ae_matrix_set_length(&xy, 5+1, 1+1, _state);
for(i=0; i<=5; i++)
{
xy.ptr.pp_double[i][0] = (double)(0);
xy.ptr.pp_double[i][1] = (double)(0);
}
lrbuild(&xy, 6, 1, &info, lr, &rep, _state);
ae_assert(info>0, "Assertion failed", _state);
ae_frame_leave(_state);
}
ae_bool testfilters(ae_bool silent, ae_state *_state)
{
ae_bool waserrors;
ae_bool smaerrors;
ae_bool emaerrors;
ae_bool lrmaerrors;
ae_bool result;
smaerrors = testsma(ae_true, _state);
emaerrors = testema(ae_true, _state);
lrmaerrors = testlrma(ae_true, _state);
/*
* Final report
*/
waserrors = (smaerrors||emaerrors)||lrmaerrors;
if( !silent )
{
printf("FILTERS TEST\n");
printf("* SMA: ");
if( !smaerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* EMA: ");
if( !emaerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* LRMA: ");
if( !lrmaerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST SUMMARY: FAILED\n");
}
else
{
printf("TEST SUMMARY: PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
return result;
}
/*************************************************************************
This function tests SMA(k) filter. It returns True on error.
Additional IsSilent parameter controls detailed error reporting.
*************************************************************************/
ae_bool testsma(ae_bool issilent, ae_state *_state)
{
ae_frame _frame_block;
ae_vector x;
ae_bool precomputederrors;
ae_bool zerohandlingerrors;
double threshold;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
threshold = 1000*ae_machineepsilon;
if( !issilent )
{
printf("SMA(K) TEST\n");
}
/*
* Test several pre-computed problems.
*
* NOTE: tests below rely on the fact that floating point
* additions and subtractions are exact when dealing
* with integer values.
*/
precomputederrors = ae_false;
ae_vector_set_length(&x, 1, _state);
x.ptr.p_double[0] = (double)(7);
filtersma(&x, 1, 1, _state);
precomputederrors = precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7));
ae_vector_set_length(&x, 3, _state);
x.ptr.p_double[0] = (double)(7);
x.ptr.p_double[1] = (double)(8);
x.ptr.p_double[2] = (double)(9);
filtersma(&x, 3, 1, _state);
precomputederrors = ((precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7)))||ae_fp_neq(x.ptr.p_double[1],(double)(8)))||ae_fp_neq(x.ptr.p_double[2],(double)(9));
filtersma(&x, 3, 2, _state);
precomputederrors = ((precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7)))||ae_fp_neq(x.ptr.p_double[1],7.5))||ae_fp_neq(x.ptr.p_double[2],8.5);
ae_vector_set_length(&x, 3, _state);
x.ptr.p_double[0] = (double)(7);
x.ptr.p_double[1] = (double)(8);
x.ptr.p_double[2] = (double)(9);
filtersma(&x, 3, 4, _state);
precomputederrors = ((precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7)))||ae_fp_neq(x.ptr.p_double[1],7.5))||ae_fp_neq(x.ptr.p_double[2],(double)(8));
/*
* Test zero-handling:
* a) when we have non-zero sequence (N1 elements) followed by zero sequence
* (N2 elements), then first N1+K-1 elements of the processed sequence are
* non-zero, but elements since (N1+K)th must be exactly zero.
* b) similar property holds for zero sequence followed by non-zero one
*
* Naive implementation of SMA does not have such property.
*
* NOTE: it is important to initialize X with non-integer elements with long
* binary mantissas, because this test tries to test behaviour in the presence
* of roundoff errors, and it will be useless when used with integer inputs.
*/
zerohandlingerrors = ae_false;
ae_vector_set_length(&x, 10, _state);
x.ptr.p_double[0] = ae_sqrt((double)(2), _state);
x.ptr.p_double[1] = ae_sqrt((double)(3), _state);
x.ptr.p_double[2] = ae_sqrt((double)(5), _state);
x.ptr.p_double[3] = ae_sqrt((double)(6), _state);
x.ptr.p_double[4] = ae_sqrt((double)(7), _state);
x.ptr.p_double[5] = (double)(0);
x.ptr.p_double[6] = (double)(0);
x.ptr.p_double[7] = (double)(0);
x.ptr.p_double[8] = (double)(0);
x.ptr.p_double[9] = (double)(0);
filtersma(&x, 10, 3, _state);
zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[0]-ae_sqrt((double)(2), _state), _state),threshold);
zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[1]-(ae_sqrt((double)(2), _state)+ae_sqrt((double)(3), _state))/2, _state),threshold);
zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[2]-(ae_sqrt((double)(2), _state)+ae_sqrt((double)(3), _state)+ae_sqrt((double)(5), _state))/3, _state),threshold);
zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[3]-(ae_sqrt((double)(3), _state)+ae_sqrt((double)(5), _state)+ae_sqrt((double)(6), _state))/3, _state),threshold);
zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[4]-(ae_sqrt((double)(5), _state)+ae_sqrt((double)(6), _state)+ae_sqrt((double)(7), _state))/3, _state),threshold);
zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[5]-(ae_sqrt((double)(6), _state)+ae_sqrt((double)(7), _state))/3, _state),threshold);
zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[6]-ae_sqrt((double)(7), _state)/3, _state),threshold);
zerohandlingerrors = zerohandlingerrors||ae_fp_neq(x.ptr.p_double[7],(double)(0));
zerohandlingerrors = zerohandlingerrors||ae_fp_neq(x.ptr.p_double[8],(double)(0));
zerohandlingerrors = zerohandlingerrors||ae_fp_neq(x.ptr.p_double[9],(double)(0));
x.ptr.p_double[0] = (double)(0);
x.ptr.p_double[1] = (double)(0);
x.ptr.p_double[2] = (double)(0);
x.ptr.p_double[3] = (double)(0);
x.ptr.p_double[4] = (double)(0);
x.ptr.p_double[5] = ae_sqrt((double)(2), _state);
x.ptr.p_double[6] = ae_sqrt((double)(3), _state);
x.ptr.p_double[7] = ae_sqrt((double)(5), _state);
x.ptr.p_double[8] = ae_sqrt((double)(6), _state);
x.ptr.p_double[9] = ae_sqrt((double)(7), _state);
filtersma(&x, 10, 3, _state);
zerohandlingerrors = zerohandlingerrors||ae_fp_neq(x.ptr.p_double[0],(double)(0));
zerohandlingerrors = zerohandlingerrors||ae_fp_neq(x.ptr.p_double[1],(double)(0));
zerohandlingerrors = zerohandlingerrors||ae_fp_neq(x.ptr.p_double[2],(double)(0));
zerohandlingerrors = zerohandlingerrors||ae_fp_neq(x.ptr.p_double[3],(double)(0));
zerohandlingerrors = zerohandlingerrors||ae_fp_neq(x.ptr.p_double[4],(double)(0));
zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[5]-ae_sqrt((double)(2), _state)/3, _state),threshold);
zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[6]-(ae_sqrt((double)(2), _state)+ae_sqrt((double)(3), _state))/3, _state),threshold);
zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[7]-(ae_sqrt((double)(2), _state)+ae_sqrt((double)(3), _state)+ae_sqrt((double)(5), _state))/3, _state),threshold);
zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[8]-(ae_sqrt((double)(3), _state)+ae_sqrt((double)(5), _state)+ae_sqrt((double)(6), _state))/3, _state),threshold);
zerohandlingerrors = zerohandlingerrors||ae_fp_greater(ae_fabs(x.ptr.p_double[9]-(ae_sqrt((double)(5), _state)+ae_sqrt((double)(6), _state)+ae_sqrt((double)(7), _state))/3, _state),threshold);
/*
* Final result
*/
result = precomputederrors||zerohandlingerrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function tests EMA(alpha) filter. It returns True on error.
Additional IsSilent parameter controls detailed error reporting.
*************************************************************************/
ae_bool testema(ae_bool issilent, ae_state *_state)
{
ae_frame _frame_block;
ae_vector x;
ae_bool precomputederrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
if( !issilent )
{
printf("EMA(alpha) TEST\n");
}
/*
* Test several pre-computed problems.
*
* NOTE: tests below rely on the fact that floating point
* additions and subtractions are exact when dealing
* with integer values.
*/
precomputederrors = ae_false;
ae_vector_set_length(&x, 1, _state);
x.ptr.p_double[0] = (double)(7);
filterema(&x, 1, 1.0, _state);
precomputederrors = precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7));
filterema(&x, 1, 0.5, _state);
precomputederrors = precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7));
ae_vector_set_length(&x, 3, _state);
x.ptr.p_double[0] = (double)(7);
x.ptr.p_double[1] = (double)(8);
x.ptr.p_double[2] = (double)(9);
filterema(&x, 3, 1.0, _state);
precomputederrors = ((precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7)))||ae_fp_neq(x.ptr.p_double[1],(double)(8)))||ae_fp_neq(x.ptr.p_double[2],(double)(9));
filterema(&x, 3, 0.5, _state);
precomputederrors = ((precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7)))||ae_fp_neq(x.ptr.p_double[1],7.5))||ae_fp_neq(x.ptr.p_double[2],8.25);
/*
* Final result
*/
result = precomputederrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function tests LRMA(k) filter. It returns True on error.
Additional IsSilent parameter controls detailed error reporting.
*************************************************************************/
ae_bool testlrma(ae_bool issilent, ae_state *_state)
{
ae_frame _frame_block;
ae_vector x;
ae_bool precomputederrors;
double threshold;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
threshold = 1000*ae_machineepsilon;
if( !issilent )
{
printf("LRMA(K) TEST\n");
}
precomputederrors = ae_false;
/*
* First, check that filter does not changes points for K=1 or K=2
*/
ae_vector_set_length(&x, 1, _state);
x.ptr.p_double[0] = (double)(7);
filterlrma(&x, 1, 1, _state);
precomputederrors = precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7));
ae_vector_set_length(&x, 6, _state);
x.ptr.p_double[0] = (double)(7);
x.ptr.p_double[1] = (double)(8);
x.ptr.p_double[2] = (double)(9);
x.ptr.p_double[3] = (double)(10);
x.ptr.p_double[4] = (double)(11);
x.ptr.p_double[5] = (double)(12);
filterlrma(&x, 6, 1, _state);
precomputederrors = (((((precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7)))||ae_fp_neq(x.ptr.p_double[1],(double)(8)))||ae_fp_neq(x.ptr.p_double[2],(double)(9)))||ae_fp_neq(x.ptr.p_double[3],(double)(10)))||ae_fp_neq(x.ptr.p_double[4],(double)(11)))||ae_fp_neq(x.ptr.p_double[5],(double)(12));
filterlrma(&x, 6, 2, _state);
precomputederrors = (((((precomputederrors||ae_fp_neq(x.ptr.p_double[0],(double)(7)))||ae_fp_neq(x.ptr.p_double[1],(double)(8)))||ae_fp_neq(x.ptr.p_double[2],(double)(9)))||ae_fp_neq(x.ptr.p_double[3],(double)(10)))||ae_fp_neq(x.ptr.p_double[4],(double)(11)))||ae_fp_neq(x.ptr.p_double[5],(double)(12));
/*
* Check several precomputed problems
*/
ae_vector_set_length(&x, 6, _state);
x.ptr.p_double[0] = (double)(7);
x.ptr.p_double[1] = (double)(8);
x.ptr.p_double[2] = (double)(9);
x.ptr.p_double[3] = (double)(10);
x.ptr.p_double[4] = (double)(11);
x.ptr.p_double[5] = (double)(12);
filterlrma(&x, 6, 3, _state);
precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[0]-7, _state),threshold);
precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[1]-8, _state),threshold);
precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[2]-9, _state),threshold);
precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[3]-10, _state),threshold);
precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[4]-11, _state),threshold);
precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[5]-12, _state),threshold);
ae_vector_set_length(&x, 6, _state);
x.ptr.p_double[0] = (double)(7);
x.ptr.p_double[1] = (double)(8);
x.ptr.p_double[2] = (double)(8);
x.ptr.p_double[3] = (double)(9);
x.ptr.p_double[4] = (double)(12);
x.ptr.p_double[5] = (double)(12);
filterlrma(&x, 6, 3, _state);
precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[0]-7.0000000000, _state),1.0E-5);
precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[1]-8.0000000000, _state),1.0E-5);
precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[2]-8.1666666667, _state),1.0E-5);
precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[3]-8.8333333333, _state),1.0E-5);
precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[4]-11.6666666667, _state),1.0E-5);
precomputederrors = precomputederrors||ae_fp_greater(ae_fabs(x.ptr.p_double[5]-12.5000000000, _state),1.0E-5);
/*
* Final result
*/
result = precomputederrors;
ae_frame_leave(_state);
return result;
}
static void testmcpdunit_testsimple(ae_bool* err, ae_state *_state);
static void testmcpdunit_testentryexit(ae_bool* err, ae_state *_state);
static void testmcpdunit_testec(ae_bool* err, ae_state *_state);
static void testmcpdunit_testbc(ae_bool* err, ae_state *_state);
static void testmcpdunit_testlc(ae_bool* err, ae_state *_state);
static void testmcpdunit_createee(ae_int_t n,
ae_int_t entrystate,
ae_int_t exitstate,
mcpdstate* s,
ae_state *_state);
ae_bool testmcpd(ae_bool silent, ae_state *_state)
{
ae_bool waserrors;
ae_bool simpleerrors;
ae_bool entryexiterrors;
ae_bool ecerrors;
ae_bool bcerrors;
ae_bool lcerrors;
ae_bool othererrors;
ae_bool result;
/*
* Init
*/
waserrors = ae_false;
othererrors = ae_false;
simpleerrors = ae_false;
entryexiterrors = ae_false;
ecerrors = ae_false;
bcerrors = ae_false;
lcerrors = ae_false;
/*
* Test
*/
testmcpdunit_testsimple(&simpleerrors, _state);
testmcpdunit_testentryexit(&entryexiterrors, _state);
testmcpdunit_testec(&ecerrors, _state);
testmcpdunit_testbc(&bcerrors, _state);
testmcpdunit_testlc(&lcerrors, _state);
/*
* Final report
*/
waserrors = ((((othererrors||simpleerrors)||entryexiterrors)||ecerrors)||bcerrors)||lcerrors;
if( !silent )
{
printf("MCPD TEST\n");
printf("TOTAL RESULTS: ");
if( !waserrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* SIMPLE: ");
if( !simpleerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* ENTRY/EXIT: ");
if( !entryexiterrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* EQUALITY CONSTRAINTS: ");
if( !ecerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* BOUND CONSTRAINTS: ");
if( !bcerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* LINEAR CONSTRAINTS: ");
if( !lcerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* OTHER PROPERTIES: ");
if( !othererrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST SUMMARY: FAILED\n");
}
else
{
printf("TEST SUMMARY: PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
return result;
}
/*************************************************************************
Simple test with no "entry"/"exit" states
On failure sets Err to True (leaves it unchanged otherwise)
*************************************************************************/
static void testmcpdunit_testsimple(ae_bool* err, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_matrix pexact;
ae_matrix xy;
double threshold;
ae_int_t i;
ae_int_t j;
double v;
double v0;
ae_matrix p;
mcpdstate s;
mcpdreport rep;
double offdiagonal;
ae_frame_make(_state, &_frame_block);
memset(&pexact, 0, sizeof(pexact));
memset(&xy, 0, sizeof(xy));
memset(&p, 0, sizeof(p));
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
ae_matrix_init(&pexact, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&p, 0, 0, DT_REAL, _state, ae_true);
_mcpdstate_init(&s, _state, ae_true);
_mcpdreport_init(&rep, _state, ae_true);
threshold = 1.0E-2;
/*
* First test:
* * N-dimensional problem
* * proportional data
* * no "entry"/"exit" states
* * N tracks, each includes only two states
* * first record in I-th track is [0 ... 1 ... 0] with 1 is in I-th position
* * all tracks are modelled using randomly generated transition matrix P
*/
for(n=1; n<=5; n++)
{
/*
* Initialize "exact" P:
* * fill by random values
* * make sure that each column sums to non-zero value
* * normalize
*/
ae_matrix_set_length(&pexact, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
pexact.ptr.pp_double[i][j] = ae_randomreal(_state);
}
}
for(j=0; j<=n-1; j++)
{
i = ae_randominteger(n, _state);
pexact.ptr.pp_double[i][j] = pexact.ptr.pp_double[i][j]+0.1;
}
for(j=0; j<=n-1; j++)
{
v = (double)(0);
for(i=0; i<=n-1; i++)
{
v = v+pexact.ptr.pp_double[i][j];
}
for(i=0; i<=n-1; i++)
{
pexact.ptr.pp_double[i][j] = pexact.ptr.pp_double[i][j]/v;
}
}
/*
* Initialize solver:
* * create object
* * add tracks
*/
mcpdcreate(n, &s, _state);
for(i=0; i<=n-1; i++)
{
ae_matrix_set_length(&xy, 2, n, _state);
for(j=0; j<=n-1; j++)
{
xy.ptr.pp_double[0][j] = (double)(0);
}
xy.ptr.pp_double[0][i] = (double)(1);
for(j=0; j<=n-1; j++)
{
xy.ptr.pp_double[1][j] = pexact.ptr.pp_double[j][i];
}
mcpdaddtrack(&s, &xy, 2, _state);
}
/*
* Solve and test
*/
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
if( rep.terminationtype>0 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
*err = *err||ae_fp_greater(ae_fabs(p.ptr.pp_double[i][j]-pexact.ptr.pp_double[i][j], _state),threshold);
}
}
}
else
{
*err = ae_true;
}
}
/*
* Second test:
* * N-dimensional problem
* * proportional data
* * no "entry"/"exit" states
* * N tracks, each includes only two states
* * first record in I-th track is [0 ...0.1 0.8 0.1 ... 0] with 0.8 is in I-th position
* * all tracks are modelled using randomly generated transition matrix P
*/
offdiagonal = 0.1;
for(n=1; n<=5; n++)
{
/*
* Initialize "exact" P:
* * fill by random values
* * make sure that each column sums to non-zero value
* * normalize
*/
ae_matrix_set_length(&pexact, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
pexact.ptr.pp_double[i][j] = ae_randomreal(_state);
}
}
for(j=0; j<=n-1; j++)
{
i = ae_randominteger(n, _state);
pexact.ptr.pp_double[i][j] = pexact.ptr.pp_double[i][j]+0.1;
}
for(j=0; j<=n-1; j++)
{
v = (double)(0);
for(i=0; i<=n-1; i++)
{
v = v+pexact.ptr.pp_double[i][j];
}
for(i=0; i<=n-1; i++)
{
pexact.ptr.pp_double[i][j] = pexact.ptr.pp_double[i][j]/v;
}
}
/*
* Initialize solver:
* * create object
* * add tracks
*/
mcpdcreate(n, &s, _state);
for(i=0; i<=n-1; i++)
{
ae_matrix_set_length(&xy, 2, n, _state);
for(j=0; j<=n-1; j++)
{
xy.ptr.pp_double[0][j] = (double)(0);
}
/*
* "main" element
*/
xy.ptr.pp_double[0][i] = 1.0-2*offdiagonal;
for(j=0; j<=n-1; j++)
{
xy.ptr.pp_double[1][j] = (1.0-2*offdiagonal)*pexact.ptr.pp_double[j][i];
}
/*
* off-diagonal ones
*/
if( i>0 )
{
xy.ptr.pp_double[0][i-1] = offdiagonal;
for(j=0; j<=n-1; j++)
{
xy.ptr.pp_double[1][j] = xy.ptr.pp_double[1][j]+offdiagonal*pexact.ptr.pp_double[j][i-1];
}
}
if( i0 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
*err = *err||ae_fp_greater(ae_fabs(p.ptr.pp_double[i][j]-pexact.ptr.pp_double[i][j], _state),threshold);
}
}
}
else
{
*err = ae_true;
}
}
/*
* Third test:
* * N-dimensional problem
* * population data
* * no "entry"/"exit" states
* * N tracks, each includes only two states
* * first record in I-th track is V*[0 ...0.1 0.8 0.1 ... 0] with 0.8 is in I-th position, V in [1,10]
* * all tracks are modelled using randomly generated transition matrix P
*/
offdiagonal = 0.1;
for(n=1; n<=5; n++)
{
/*
* Initialize "exact" P:
* * fill by random values
* * make sure that each column sums to non-zero value
* * normalize
*/
ae_matrix_set_length(&pexact, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
pexact.ptr.pp_double[i][j] = ae_randomreal(_state);
}
}
for(j=0; j<=n-1; j++)
{
i = ae_randominteger(n, _state);
pexact.ptr.pp_double[i][j] = pexact.ptr.pp_double[i][j]+0.1;
}
for(j=0; j<=n-1; j++)
{
v = (double)(0);
for(i=0; i<=n-1; i++)
{
v = v+pexact.ptr.pp_double[i][j];
}
for(i=0; i<=n-1; i++)
{
pexact.ptr.pp_double[i][j] = pexact.ptr.pp_double[i][j]/v;
}
}
/*
* Initialize solver:
* * create object
* * add tracks
*/
mcpdcreate(n, &s, _state);
for(i=0; i<=n-1; i++)
{
ae_matrix_set_length(&xy, 2, n, _state);
for(j=0; j<=n-1; j++)
{
xy.ptr.pp_double[0][j] = (double)(0);
}
/*
* "main" element
*/
v0 = 9*ae_randomreal(_state)+1;
xy.ptr.pp_double[0][i] = v0*(1.0-2*offdiagonal);
for(j=0; j<=n-1; j++)
{
xy.ptr.pp_double[1][j] = v0*(1.0-2*offdiagonal)*pexact.ptr.pp_double[j][i];
}
/*
* off-diagonal ones
*/
if( i>0 )
{
xy.ptr.pp_double[0][i-1] = v0*offdiagonal;
for(j=0; j<=n-1; j++)
{
xy.ptr.pp_double[1][j] = xy.ptr.pp_double[1][j]+v0*offdiagonal*pexact.ptr.pp_double[j][i-1];
}
}
if( i0 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
*err = *err||ae_fp_greater(ae_fabs(p.ptr.pp_double[i][j]-pexact.ptr.pp_double[i][j], _state),threshold);
}
}
}
else
{
*err = ae_true;
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Test for different combinations of "entry"/"exit" models
On failure sets Err to True (leaves it unchanged otherwise)
*************************************************************************/
static void testmcpdunit_testentryexit(ae_bool* err, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_matrix p;
ae_matrix pexact;
ae_matrix xy;
double threshold;
ae_int_t entrystate;
ae_int_t exitstate;
ae_int_t entrykind;
ae_int_t exitkind;
ae_int_t popkind;
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
mcpdstate s;
mcpdreport rep;
ae_frame_make(_state, &_frame_block);
memset(&p, 0, sizeof(p));
memset(&pexact, 0, sizeof(pexact));
memset(&xy, 0, sizeof(xy));
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
ae_matrix_init(&p, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&pexact, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_mcpdstate_init(&s, _state, ae_true);
_mcpdreport_init(&rep, _state, ae_true);
threshold = 1.0E-3;
/*
*
*/
for(n=2; n<=5; n++)
{
for(entrykind=0; entrykind<=1; entrykind++)
{
for(exitkind=0; exitkind<=1; exitkind++)
{
for(popkind=0; popkind<=1; popkind++)
{
/*
* Generate EntryState/ExitState such that one of the following is True:
* * EntryState<>ExitState
* * EntryState=-1 or ExitState=-1
*/
do
{
if( entrykind==0 )
{
entrystate = -1;
}
else
{
entrystate = ae_randominteger(n, _state);
}
if( exitkind==0 )
{
exitstate = -1;
}
else
{
exitstate = ae_randominteger(n, _state);
}
}
while(!((entrystate==-1||exitstate==-1)||entrystate!=exitstate));
/*
* Generate transition matrix P such that:
* * columns corresponding to non-exit states sums to 1.0
* * columns corresponding to exit states sums to 0.0
* * rows corresponding to entry states are zero
*/
ae_matrix_set_length(&pexact, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
pexact.ptr.pp_double[i][j] = (double)(1+ae_randominteger(5, _state));
if( i==entrystate )
{
pexact.ptr.pp_double[i][j] = 0.0;
}
if( j==exitstate )
{
pexact.ptr.pp_double[i][j] = 0.0;
}
}
}
for(j=0; j<=n-1; j++)
{
v = 0.0;
for(i=0; i<=n-1; i++)
{
v = v+pexact.ptr.pp_double[i][j];
}
if( ae_fp_neq(v,(double)(0)) )
{
for(i=0; i<=n-1; i++)
{
pexact.ptr.pp_double[i][j] = pexact.ptr.pp_double[i][j]/v;
}
}
}
/*
* Create MCPD solver
*/
if( entrystate<0&&exitstate<0 )
{
mcpdcreate(n, &s, _state);
}
if( entrystate>=0&&exitstate<0 )
{
mcpdcreateentry(n, entrystate, &s, _state);
}
if( entrystate<0&&exitstate>=0 )
{
mcpdcreateexit(n, exitstate, &s, _state);
}
if( entrystate>=0&&exitstate>=0 )
{
mcpdcreateentryexit(n, entrystate, exitstate, &s, _state);
}
/*
* Add N tracks.
*
* K-th track starts from vector with large value of
* K-th component and small random noise in other components.
*
* Track contains from 2 to 4 elements.
*
* Tracks contain proportional (normalized) or
* population data, depending on PopKind variable.
*/
for(k=0; k<=n-1; k++)
{
/*
* Generate track whose length is in 2..4
*/
ae_matrix_set_length(&xy, 2+ae_randominteger(3, _state), n, _state);
for(j=0; j<=n-1; j++)
{
xy.ptr.pp_double[0][j] = 0.05*ae_randomreal(_state);
}
xy.ptr.pp_double[0][k] = 1+ae_randomreal(_state);
for(i=1; i<=xy.rows-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( j!=entrystate )
{
v = ae_v_dotproduct(&pexact.ptr.pp_double[j][0], 1, &xy.ptr.pp_double[i-1][0], 1, ae_v_len(0,n-1));
xy.ptr.pp_double[i][j] = v;
}
else
{
xy.ptr.pp_double[i][j] = ae_randomreal(_state);
}
}
}
/*
* Normalize, if needed
*/
if( popkind==1 )
{
for(i=0; i<=xy.rows-1; i++)
{
v = 0.0;
for(j=0; j<=n-1; j++)
{
v = v+xy.ptr.pp_double[i][j];
}
if( ae_fp_greater(v,(double)(0)) )
{
for(j=0; j<=n-1; j++)
{
xy.ptr.pp_double[i][j] = xy.ptr.pp_double[i][j]/v;
}
}
}
}
/*
* Add track
*/
mcpdaddtrack(&s, &xy, xy.rows, _state);
}
/*
* Solve and test
*/
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
if( rep.terminationtype>0 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
*err = *err||ae_fp_greater(ae_fabs(p.ptr.pp_double[i][j]-pexact.ptr.pp_double[i][j], _state),threshold);
}
}
}
else
{
*err = ae_true;
}
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Test equality constraints.
On failure sets Err to True (leaves it unchanged otherwise)
*************************************************************************/
static void testmcpdunit_testec(ae_bool* err, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_matrix p;
ae_matrix ec;
ae_matrix xy;
ae_int_t entrystate;
ae_int_t exitstate;
ae_int_t entrykind;
ae_int_t exitkind;
ae_int_t i;
ae_int_t j;
ae_int_t ic;
ae_int_t jc;
double vc;
mcpdstate s;
mcpdreport rep;
ae_frame_make(_state, &_frame_block);
memset(&p, 0, sizeof(p));
memset(&ec, 0, sizeof(ec));
memset(&xy, 0, sizeof(xy));
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
ae_matrix_init(&p, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ec, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_mcpdstate_init(&s, _state, ae_true);
_mcpdreport_init(&rep, _state, ae_true);
/*
* We try different problems with following properties:
* * N is large enough - we won't have problems with inconsistent constraints
* * first state is either "entry" or "normal"
* * last state is either "exit" or "normal"
* * we have one long random track
*
* We test several properties which are described in comments below
*/
for(n=4; n<=6; n++)
{
for(entrykind=0; entrykind<=1; entrykind++)
{
for(exitkind=0; exitkind<=1; exitkind++)
{
/*
* Prepare problem
*/
if( entrykind==0 )
{
entrystate = -1;
}
else
{
entrystate = 0;
}
if( exitkind==0 )
{
exitstate = -1;
}
else
{
exitstate = n-1;
}
ae_matrix_set_length(&xy, 2*n, n, _state);
for(i=0; i<=xy.rows-1; i++)
{
for(j=0; j<=xy.cols-1; j++)
{
xy.ptr.pp_double[i][j] = ae_randomreal(_state);
}
}
/*
* Test that single equality constraint on non-entry
* non-exit elements of P is satisfied.
*
* NOTE: this test needs N>=4 because smaller values
* can give us inconsistent constraints
*/
ae_assert(n>=4, "TestEC: expectation failed", _state);
ic = 1+ae_randominteger(n-2, _state);
jc = 1+ae_randominteger(n-2, _state);
vc = ae_randomreal(_state);
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
mcpdaddec(&s, ic, jc, vc, _state);
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
if( rep.terminationtype>0 )
{
*err = *err||ae_fp_neq(p.ptr.pp_double[ic][jc],vc);
}
else
{
*err = ae_true;
}
/*
* Test interaction with default "sum-to-one" constraint
* on columns of P.
*
* We set N-1 equality constraints on random non-exit column
* of P, which are inconsistent with this default constraint
* (sum will be greater that 1.0).
*
* Algorithm must detect inconsistency.
*
* NOTE:
* 1. we do not set constraints for the first element of
* the column, because this element may be constrained by
* "exit state" constraint.
* 2. this test needs N>=3
*/
ae_assert(n>=3, "TestEC: expectation failed", _state);
jc = ae_randominteger(n-1, _state);
vc = 0.95;
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
for(i=1; i<=n-1; i++)
{
mcpdaddec(&s, i, jc, vc, _state);
}
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
*err = *err||rep.terminationtype!=-3;
/*
* Test interaction with constrains on entry states.
*
* When model has entry state, corresponding row of P
* must be zero. We try to set two kinds of constraints
* on random element of this row:
* * zero equality constraint, which must be consistent
* * non-zero equality constraint, which must be inconsistent
*/
if( entrystate>=0 )
{
jc = ae_randominteger(n, _state);
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
mcpdaddec(&s, entrystate, jc, 0.0, _state);
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
*err = *err||rep.terminationtype<=0;
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
mcpdaddec(&s, entrystate, jc, 0.5, _state);
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
*err = *err||rep.terminationtype!=-3;
}
/*
* Test interaction with constrains on exit states.
*
* When model has exit state, corresponding column of P
* must be zero. We try to set two kinds of constraints
* on random element of this column:
* * zero equality constraint, which must be consistent
* * non-zero equality constraint, which must be inconsistent
*/
if( exitstate>=0 )
{
ic = ae_randominteger(n, _state);
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
mcpdaddec(&s, ic, exitstate, 0.0, _state);
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
*err = *err||rep.terminationtype<=0;
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
mcpdaddec(&s, ic, exitstate, 0.5, _state);
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
*err = *err||rep.terminationtype!=-3;
}
/*
* Test SetEC() call - we constrain subset of non-entry
* non-exit elements and test it.
*/
ae_assert(n>=4, "TestEC: expectation failed", _state);
ae_matrix_set_length(&ec, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
ec.ptr.pp_double[i][j] = _state->v_nan;
}
}
for(j=1; j<=n-2; j++)
{
ec.ptr.pp_double[1+ae_randominteger(n-2, _state)][j] = 0.1+0.1*ae_randomreal(_state);
}
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
mcpdsetec(&s, &ec, _state);
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
if( rep.terminationtype>0 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_isfinite(ec.ptr.pp_double[i][j], _state) )
{
*err = *err||ae_fp_neq(p.ptr.pp_double[i][j],ec.ptr.pp_double[i][j]);
}
}
}
}
else
{
*err = ae_true;
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Test bound constraints.
On failure sets Err to True (leaves it unchanged otherwise)
*************************************************************************/
static void testmcpdunit_testbc(ae_bool* err, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_matrix p;
ae_matrix bndl;
ae_matrix bndu;
ae_matrix xy;
ae_int_t entrystate;
ae_int_t exitstate;
ae_int_t entrykind;
ae_int_t exitkind;
ae_int_t i;
ae_int_t j;
ae_int_t ic;
ae_int_t jc;
double vl;
double vu;
mcpdstate s;
mcpdreport rep;
ae_frame_make(_state, &_frame_block);
memset(&p, 0, sizeof(p));
memset(&bndl, 0, sizeof(bndl));
memset(&bndu, 0, sizeof(bndu));
memset(&xy, 0, sizeof(xy));
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
ae_matrix_init(&p, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&bndl, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&bndu, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_mcpdstate_init(&s, _state, ae_true);
_mcpdreport_init(&rep, _state, ae_true);
/*
* We try different problems with following properties:
* * N is large enough - we won't have problems with inconsistent constraints
* * first state is either "entry" or "normal"
* * last state is either "exit" or "normal"
* * we have one long random track
*
* We test several properties which are described in comments below
*/
for(n=4; n<=6; n++)
{
for(entrykind=0; entrykind<=1; entrykind++)
{
for(exitkind=0; exitkind<=1; exitkind++)
{
/*
* Prepare problem
*/
if( entrykind==0 )
{
entrystate = -1;
}
else
{
entrystate = 0;
}
if( exitkind==0 )
{
exitstate = -1;
}
else
{
exitstate = n-1;
}
ae_matrix_set_length(&xy, 2*n, n, _state);
for(i=0; i<=xy.rows-1; i++)
{
for(j=0; j<=xy.cols-1; j++)
{
xy.ptr.pp_double[i][j] = ae_randomreal(_state);
}
}
/*
* Test that single bound constraint on non-entry
* non-exit elements of P is satisfied.
*
* NOTE 1: this test needs N>=4 because smaller values
* can give us inconsistent constraints
*/
ae_assert(n>=4, "TestBC: expectation failed", _state);
ic = 1+ae_randominteger(n-2, _state);
jc = 1+ae_randominteger(n-2, _state);
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
vl = 0.3*ae_randomreal(_state);
}
else
{
vl = _state->v_neginf;
}
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
vu = 0.5+0.3*ae_randomreal(_state);
}
else
{
vu = _state->v_posinf;
}
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
mcpdaddbc(&s, ic, jc, vl, vu, _state);
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
if( rep.terminationtype>0 )
{
*err = *err||ae_fp_less(p.ptr.pp_double[ic][jc],vl);
*err = *err||ae_fp_greater(p.ptr.pp_double[ic][jc],vu);
}
else
{
*err = ae_true;
}
/*
* Test interaction with default "sum-to-one" constraint
* on columns of P.
*
* We set N-1 bound constraints on random non-exit column
* of P, which are inconsistent with this default constraint
* (sum will be greater that 1.0).
*
* Algorithm must detect inconsistency.
*
* NOTE:
* 1. we do not set constraints for the first element of
* the column, because this element may be constrained by
* "exit state" constraint.
* 2. this test needs N>=3
*/
ae_assert(n>=3, "TestEC: expectation failed", _state);
jc = ae_randominteger(n-1, _state);
vl = 0.85;
vu = 0.95;
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
for(i=1; i<=n-1; i++)
{
mcpdaddbc(&s, i, jc, vl, vu, _state);
}
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
*err = *err||rep.terminationtype!=-3;
/*
* Test interaction with constrains on entry states.
*
* When model has entry state, corresponding row of P
* must be zero. We try to set two kinds of constraints
* on random element of this row:
* * bound constraint with zero lower bound, which must be consistent
* * bound constraint with non-zero lower bound, which must be inconsistent
*/
if( entrystate>=0 )
{
jc = ae_randominteger(n, _state);
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
mcpdaddbc(&s, entrystate, jc, 0.0, 1.0, _state);
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
*err = *err||rep.terminationtype<=0;
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
mcpdaddbc(&s, entrystate, jc, 0.5, 1.0, _state);
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
*err = *err||rep.terminationtype!=-3;
}
/*
* Test interaction with constrains on exit states.
*
* When model has exit state, corresponding column of P
* must be zero. We try to set two kinds of constraints
* on random element of this column:
* * bound constraint with zero lower bound, which must be consistent
* * bound constraint with non-zero lower bound, which must be inconsistent
*/
if( exitstate>=0 )
{
ic = ae_randominteger(n, _state);
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
mcpdaddbc(&s, ic, exitstate, 0.0, 1.0, _state);
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
*err = *err||rep.terminationtype<=0;
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
mcpdaddbc(&s, ic, exitstate, 0.5, 1.0, _state);
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
*err = *err||rep.terminationtype!=-3;
}
/*
* Test SetBC() call - we constrain subset of non-entry
* non-exit elements and test it.
*/
ae_assert(n>=4, "TestBC: expectation failed", _state);
ae_matrix_set_length(&bndl, n, n, _state);
ae_matrix_set_length(&bndu, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
bndl.ptr.pp_double[i][j] = _state->v_neginf;
bndu.ptr.pp_double[i][j] = _state->v_posinf;
}
}
for(j=1; j<=n-2; j++)
{
i = 1+ae_randominteger(n-2, _state);
bndl.ptr.pp_double[i][j] = 0.5-0.1*ae_randomreal(_state);
bndu.ptr.pp_double[i][j] = 0.5+0.1*ae_randomreal(_state);
}
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
mcpdsetbc(&s, &bndl, &bndu, _state);
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
if( rep.terminationtype>0 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
*err = *err||ae_fp_less(p.ptr.pp_double[i][j],bndl.ptr.pp_double[i][j]);
*err = *err||ae_fp_greater(p.ptr.pp_double[i][j],bndu.ptr.pp_double[i][j]);
}
}
}
else
{
*err = ae_true;
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Test bound constraints.
On failure sets Err to True (leaves it unchanged otherwise)
*************************************************************************/
static void testmcpdunit_testlc(ae_bool* err, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_matrix p;
ae_matrix c;
ae_matrix xy;
ae_vector ct;
ae_int_t entrystate;
ae_int_t exitstate;
ae_int_t entrykind;
ae_int_t exitkind;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t t;
ae_int_t jc;
double v;
double threshold;
mcpdstate s;
mcpdreport rep;
ae_frame_make(_state, &_frame_block);
memset(&p, 0, sizeof(p));
memset(&c, 0, sizeof(c));
memset(&xy, 0, sizeof(xy));
memset(&ct, 0, sizeof(ct));
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
ae_matrix_init(&p, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ct, 0, DT_INT, _state, ae_true);
_mcpdstate_init(&s, _state, ae_true);
_mcpdreport_init(&rep, _state, ae_true);
threshold = 1.0E5*ae_machineepsilon;
/*
* We try different problems with following properties:
* * N is large enough - we won't have problems with inconsistent constraints
* * first state is either "entry" or "normal"
* * last state is either "exit" or "normal"
* * we have one long random track
*
* We test several properties which are described in comments below
*/
for(n=4; n<=6; n++)
{
for(entrykind=0; entrykind<=1; entrykind++)
{
for(exitkind=0; exitkind<=1; exitkind++)
{
/*
* Prepare problem
*/
if( entrykind==0 )
{
entrystate = -1;
}
else
{
entrystate = 0;
}
if( exitkind==0 )
{
exitstate = -1;
}
else
{
exitstate = n-1;
}
ae_matrix_set_length(&xy, 2*n, n, _state);
for(i=0; i<=xy.rows-1; i++)
{
for(j=0; j<=xy.cols-1; j++)
{
xy.ptr.pp_double[i][j] = ae_randomreal(_state);
}
}
/*
* Test that single linear equality/inequality constraint
* on non-entry non-exit elements of P is satisfied.
*
* NOTE 1: this test needs N>=4 because smaller values
* can give us inconsistent constraints
* NOTE 2: Constraints are generated is such a way that P=(1/N ... 1/N)
* is always feasible. It guarantees that there always exists
* at least one feasible point
* NOTE 3: If we have inequality constraint, we "shift" right part
* in order to make feasible some neighborhood of P=(1/N ... 1/N).
*/
ae_assert(n>=4, "TestLC: expectation failed", _state);
ae_matrix_set_length(&c, 1, n*n+1, _state);
ae_vector_set_length(&ct, 1, _state);
v = (double)(0);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ((i==0||i==n-1)||j==0)||j==n-1 )
{
c.ptr.pp_double[0][i*n+j] = (double)(0);
}
else
{
c.ptr.pp_double[0][i*n+j] = ae_randomreal(_state);
v = v+c.ptr.pp_double[0][i*n+j]*((double)1/(double)n);
}
}
}
c.ptr.pp_double[0][n*n] = v;
ct.ptr.p_int[0] = ae_randominteger(3, _state)-1;
if( ct.ptr.p_int[0]<0 )
{
c.ptr.pp_double[0][n*n] = c.ptr.pp_double[0][n*n]+0.1;
}
if( ct.ptr.p_int[0]>0 )
{
c.ptr.pp_double[0][n*n] = c.ptr.pp_double[0][n*n]-0.1;
}
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
mcpdsetlc(&s, &c, &ct, 1, _state);
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
if( rep.terminationtype>0 )
{
v = (double)(0);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = v+p.ptr.pp_double[i][j]*c.ptr.pp_double[0][i*n+j];
}
}
if( ct.ptr.p_int[0]<0 )
{
*err = *err||ae_fp_greater_eq(v,c.ptr.pp_double[0][n*n]+threshold);
}
if( ct.ptr.p_int[0]==0 )
{
*err = *err||ae_fp_greater_eq(ae_fabs(v-c.ptr.pp_double[0][n*n], _state),threshold);
}
if( ct.ptr.p_int[0]>0 )
{
*err = *err||ae_fp_less_eq(v,c.ptr.pp_double[0][n*n]-threshold);
}
}
else
{
*err = ae_true;
}
/*
* Test interaction with default "sum-to-one" constraint
* on columns of P.
*
* We set linear constraint which has for "sum-to-X" on
* on random non-exit column of P. This constraint can be
* either consistent (X=1.0) or inconsistent (X<>1.0) with
* this default constraint.
*
* Algorithm must detect inconsistency.
*
* NOTE:
* 1. this test needs N>=2
*/
ae_assert(n>=2, "TestLC: expectation failed", _state);
jc = ae_randominteger(n-1, _state);
ae_matrix_set_length(&c, 1, n*n+1, _state);
ae_vector_set_length(&ct, 1, _state);
for(i=0; i<=n*n-1; i++)
{
c.ptr.pp_double[0][i] = 0.0;
}
for(i=0; i<=n-1; i++)
{
c.ptr.pp_double[0][n*i+jc] = 1.0;
}
c.ptr.pp_double[0][n*n] = 1.0;
ct.ptr.p_int[0] = 0;
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
mcpdsetlc(&s, &c, &ct, 1, _state);
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
*err = *err||rep.terminationtype<=0;
c.ptr.pp_double[0][n*n] = 2.0;
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
mcpdsetlc(&s, &c, &ct, 1, _state);
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
*err = *err||rep.terminationtype!=-3;
/*
* Test interaction with constrains on entry states.
*
* When model has entry state, corresponding row of P
* must be zero. We try to set two kinds of constraints
* on elements of this row:
* * sums-to-zero constraint, which must be consistent
* * sums-to-one constraint, which must be inconsistent
*/
if( entrystate>=0 )
{
ae_matrix_set_length(&c, 1, n*n+1, _state);
ae_vector_set_length(&ct, 1, _state);
for(i=0; i<=n*n-1; i++)
{
c.ptr.pp_double[0][i] = 0.0;
}
for(j=0; j<=n-1; j++)
{
c.ptr.pp_double[0][n*entrystate+j] = 1.0;
}
ct.ptr.p_int[0] = 0;
c.ptr.pp_double[0][n*n] = 0.0;
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
mcpdsetlc(&s, &c, &ct, 1, _state);
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
*err = *err||rep.terminationtype<=0;
c.ptr.pp_double[0][n*n] = 1.0;
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
mcpdsetlc(&s, &c, &ct, 1, _state);
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
*err = *err||rep.terminationtype!=-3;
}
/*
* Test interaction with constrains on exit states.
*
* When model has exit state, corresponding column of P
* must be zero. We try to set two kinds of constraints
* on elements of this column:
* * sums-to-zero constraint, which must be consistent
* * sums-to-one constraint, which must be inconsistent
*/
if( exitstate>=0 )
{
ae_matrix_set_length(&c, 1, n*n+1, _state);
ae_vector_set_length(&ct, 1, _state);
for(i=0; i<=n*n-1; i++)
{
c.ptr.pp_double[0][i] = 0.0;
}
for(i=0; i<=n-1; i++)
{
c.ptr.pp_double[0][n*i+exitstate] = 1.0;
}
ct.ptr.p_int[0] = 0;
c.ptr.pp_double[0][n*n] = 0.0;
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
mcpdsetlc(&s, &c, &ct, 1, _state);
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
*err = *err||rep.terminationtype<=0;
c.ptr.pp_double[0][n*n] = 1.0;
testmcpdunit_createee(n, entrystate, exitstate, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
mcpdsetlc(&s, &c, &ct, 1, _state);
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
*err = *err||rep.terminationtype!=-3;
}
}
}
}
/*
* Final test - we generate several random constraints and
* test SetLC() function.
*
* NOTES:
*
* 1. Constraints are generated is such a way that P=(1/N ... 1/N)
* is always feasible. It guarantees that there always exists
* at least one feasible point
* 2. For simplicity of the test we do not use entry/exit states
* in our model
*/
for(n=1; n<=4; n++)
{
for(k=1; k<=2*n; k++)
{
/*
* Generate track
*/
ae_matrix_set_length(&xy, 2*n, n, _state);
for(i=0; i<=xy.rows-1; i++)
{
for(j=0; j<=xy.cols-1; j++)
{
xy.ptr.pp_double[i][j] = ae_randomreal(_state);
}
}
/*
* Generate random constraints
*/
ae_matrix_set_length(&c, k, n*n+1, _state);
ae_vector_set_length(&ct, k, _state);
for(i=0; i<=k-1; i++)
{
/*
* Generate constraint and its right part
*/
c.ptr.pp_double[i][n*n] = (double)(0);
for(j=0; j<=n*n-1; j++)
{
c.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
c.ptr.pp_double[i][n*n] = c.ptr.pp_double[i][n*n]+c.ptr.pp_double[i][j]*((double)1/(double)n);
}
ct.ptr.p_int[i] = ae_randominteger(3, _state)-1;
/*
* If we have inequality constraint, we "shift" right part
* in order to make feasible some neighborhood of P=(1/N ... 1/N).
*/
if( ct.ptr.p_int[i]<0 )
{
c.ptr.pp_double[i][n*n] = c.ptr.pp_double[i][n*n]+0.1;
}
if( ct.ptr.p_int[i]>0 )
{
c.ptr.pp_double[i][n*n] = c.ptr.pp_double[i][n*n]-0.1;
}
}
/*
* Test
*/
testmcpdunit_createee(n, -1, -1, &s, _state);
mcpdaddtrack(&s, &xy, xy.rows, _state);
mcpdsetlc(&s, &c, &ct, k, _state);
mcpdsolve(&s, _state);
mcpdresults(&s, &p, &rep, _state);
if( rep.terminationtype>0 )
{
for(t=0; t<=k-1; t++)
{
v = (double)(0);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = v+p.ptr.pp_double[i][j]*c.ptr.pp_double[t][i*n+j];
}
}
if( ct.ptr.p_int[t]<0 )
{
*err = *err||ae_fp_greater_eq(v,c.ptr.pp_double[t][n*n]+threshold);
}
if( ct.ptr.p_int[t]==0 )
{
*err = *err||ae_fp_greater_eq(ae_fabs(v-c.ptr.pp_double[t][n*n], _state),threshold);
}
if( ct.ptr.p_int[t]>0 )
{
*err = *err||ae_fp_less_eq(v,c.ptr.pp_double[t][n*n]-threshold);
}
}
}
else
{
*err = ae_true;
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
This function is used to create MCPD object with arbitrary combination of
entry and exit states
*************************************************************************/
static void testmcpdunit_createee(ae_int_t n,
ae_int_t entrystate,
ae_int_t exitstate,
mcpdstate* s,
ae_state *_state)
{
_mcpdstate_clear(s);
if( entrystate<0&&exitstate<0 )
{
mcpdcreate(n, s, _state);
}
if( entrystate>=0&&exitstate<0 )
{
mcpdcreateentry(n, entrystate, s, _state);
}
if( entrystate<0&&exitstate>=0 )
{
mcpdcreateexit(n, exitstate, s, _state);
}
if( entrystate>=0&&exitstate>=0 )
{
mcpdcreateentryexit(n, entrystate, exitstate, s, _state);
}
}
static void testmlpeunit_createensemble(mlpensemble* ensemble,
ae_int_t nkind,
double a1,
double a2,
ae_int_t nin,
ae_int_t nhid1,
ae_int_t nhid2,
ae_int_t nout,
ae_int_t ec,
ae_state *_state);
static void testmlpeunit_unsetensemble(mlpensemble* ensemble,
ae_state *_state);
static void testmlpeunit_testinformational(ae_int_t nkind,
ae_int_t nin,
ae_int_t nhid1,
ae_int_t nhid2,
ae_int_t nout,
ae_int_t ec,
ae_int_t passcount,
ae_bool* err,
ae_state *_state);
static void testmlpeunit_testprocessing(ae_int_t nkind,
ae_int_t nin,
ae_int_t nhid1,
ae_int_t nhid2,
ae_int_t nout,
ae_int_t ec,
ae_int_t passcount,
ae_bool* err,
ae_state *_state);
static void testmlpeunit_testerr(ae_int_t nkind,
ae_int_t nin,
ae_int_t nhid1,
ae_int_t nhid2,
ae_int_t nout,
ae_int_t ec,
ae_int_t passcount,
ae_int_t sizemin,
ae_int_t sizemax,
ae_bool* err,
ae_state *_state);
ae_bool testmlpe(ae_bool silent, ae_state *_state)
{
ae_bool waserrors;
ae_bool inferrors;
ae_bool procerrors;
ae_bool errerrors;
ae_int_t passcount;
ae_int_t maxn;
ae_int_t maxhid;
ae_int_t nf;
ae_int_t nl;
ae_int_t nhid1;
ae_int_t nhid2;
ae_int_t ec;
ae_int_t nkind;
ae_int_t sizemin;
ae_int_t sizemax;
ae_bool result;
waserrors = ae_false;
inferrors = ae_false;
procerrors = ae_false;
errerrors = ae_false;
passcount = 5;
maxn = 3;
maxhid = 3;
/*
* General MLP ensembles tests
* These tests are performed with small dataset, whose size is in [0,10].
* We test correctness of functions on small sets, but do not test code
* which splits large dataset into smaller chunks.
*/
sizemin = 0;
sizemax = 10;
for(nf=1; nf<=maxn; nf++)
{
for(nl=1; nl<=maxn; nl++)
{
for(nhid1=0; nhid1<=maxhid; nhid1++)
{
for(nhid2=0; nhid2<=maxhid; nhid2++)
{
for(nkind=0; nkind<=3; nkind++)
{
for(ec=1; ec<=3; ec++)
{
/*
* Skip meaningless parameters combinations
*/
if( nkind==1&&nl<2 )
{
continue;
}
if( nhid1==0&&nhid2!=0 )
{
continue;
}
/*
* Tests
*/
testmlpeunit_testinformational(nkind, nf, nhid1, nhid2, nl, ec, passcount, &inferrors, _state);
testmlpeunit_testprocessing(nkind, nf, nhid1, nhid2, nl, ec, passcount, &procerrors, _state);
testmlpeunit_testerr(nkind, nf, nhid1, nhid2, nl, ec, passcount, sizemin, sizemax, &errerrors, _state);
}
}
}
}
}
}
/*
* Special tests on large datasets: test ability to correctly split
* work into smaller chunks.
*/
nf = 2;
nhid1 = 10;
nhid2 = 10;
nl = 2;
ec = 10;
sizemin = 1000;
sizemax = 1000;
testmlpeunit_testerr(0, nf, nhid1, nhid2, nl, ec, 1, sizemin, sizemax, &errerrors, _state);
/*
* Final report
*/
waserrors = (inferrors||procerrors)||errerrors;
if( !silent )
{
printf("MLP ENSEMBLE TEST\n");
printf("INFORMATIONAL FUNCTIONS: ");
if( !inferrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("BASIC PROCESSING: ");
if( !procerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("ERROR FUNCTIONS: ");
if( !errerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST SUMMARY: FAILED\n");
}
else
{
printf("TEST SUMMARY: PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
return result;
}
/*************************************************************************
Network creation
*************************************************************************/
static void testmlpeunit_createensemble(mlpensemble* ensemble,
ae_int_t nkind,
double a1,
double a2,
ae_int_t nin,
ae_int_t nhid1,
ae_int_t nhid2,
ae_int_t nout,
ae_int_t ec,
ae_state *_state)
{
ae_assert(((nin>0&&nhid1>=0)&&nhid2>=0)&&nout>0, "CreateNetwork error", _state);
ae_assert(nhid1!=0||nhid2==0, "CreateNetwork error", _state);
ae_assert(nkind!=1||nout>=2, "CreateNetwork error", _state);
if( nhid1==0 )
{
/*
* No hidden layers
*/
if( nkind==0 )
{
mlpecreate0(nin, nout, ec, ensemble, _state);
}
else
{
if( nkind==1 )
{
mlpecreatec0(nin, nout, ec, ensemble, _state);
}
else
{
if( nkind==2 )
{
mlpecreateb0(nin, nout, a1, a2, ec, ensemble, _state);
}
else
{
if( nkind==3 )
{
mlpecreater0(nin, nout, a1, a2, ec, ensemble, _state);
}
}
}
}
return;
}
if( nhid2==0 )
{
/*
* One hidden layer
*/
if( nkind==0 )
{
mlpecreate1(nin, nhid1, nout, ec, ensemble, _state);
}
else
{
if( nkind==1 )
{
mlpecreatec1(nin, nhid1, nout, ec, ensemble, _state);
}
else
{
if( nkind==2 )
{
mlpecreateb1(nin, nhid1, nout, a1, a2, ec, ensemble, _state);
}
else
{
if( nkind==3 )
{
mlpecreater1(nin, nhid1, nout, a1, a2, ec, ensemble, _state);
}
}
}
}
return;
}
/*
* Two hidden layers
*/
if( nkind==0 )
{
mlpecreate2(nin, nhid1, nhid2, nout, ec, ensemble, _state);
}
else
{
if( nkind==1 )
{
mlpecreatec2(nin, nhid1, nhid2, nout, ec, ensemble, _state);
}
else
{
if( nkind==2 )
{
mlpecreateb2(nin, nhid1, nhid2, nout, a1, a2, ec, ensemble, _state);
}
else
{
if( nkind==3 )
{
mlpecreater2(nin, nhid1, nhid2, nout, a1, a2, ec, ensemble, _state);
}
}
}
}
}
/*************************************************************************
Unsets network (initialize it to smallest network possible
*************************************************************************/
static void testmlpeunit_unsetensemble(mlpensemble* ensemble,
ae_state *_state)
{
mlpecreate0(1, 1, 1, ensemble, _state);
}
/*************************************************************************
Iformational functions test
*************************************************************************/
static void testmlpeunit_testinformational(ae_int_t nkind,
ae_int_t nin,
ae_int_t nhid1,
ae_int_t nhid2,
ae_int_t nout,
ae_int_t ec,
ae_int_t passcount,
ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
mlpensemble ensemble;
ae_int_t n1;
ae_int_t n2;
ae_frame_make(_state, &_frame_block);
memset(&ensemble, 0, sizeof(ensemble));
_mlpensemble_init(&ensemble, _state, ae_true);
testmlpeunit_createensemble(&ensemble, nkind, -1.0, 1.0, nin, nhid1, nhid2, nout, ec, _state);
mlpeproperties(&ensemble, &n1, &n2, _state);
*err = (*err||n1!=nin)||n2!=nout;
ae_frame_leave(_state);
}
/*************************************************************************
Processing functions test
*************************************************************************/
static void testmlpeunit_testprocessing(ae_int_t nkind,
ae_int_t nin,
ae_int_t nhid1,
ae_int_t nhid2,
ae_int_t nout,
ae_int_t ec,
ae_int_t passcount,
ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
mlpensemble ensemble;
mlpensemble ensemble2;
double a1;
double a2;
ae_int_t pass;
ae_int_t rkind;
ae_int_t i;
ae_bool allsame;
ae_vector x1;
ae_vector x2;
ae_vector y1;
ae_vector y2;
ae_vector ra;
ae_vector ra2;
double v;
ae_frame_make(_state, &_frame_block);
memset(&ensemble, 0, sizeof(ensemble));
memset(&ensemble2, 0, sizeof(ensemble2));
memset(&x1, 0, sizeof(x1));
memset(&x2, 0, sizeof(x2));
memset(&y1, 0, sizeof(y1));
memset(&y2, 0, sizeof(y2));
memset(&ra, 0, sizeof(ra));
memset(&ra2, 0, sizeof(ra2));
_mlpensemble_init(&ensemble, _state, ae_true);
_mlpensemble_init(&ensemble2, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ra, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ra2, 0, DT_REAL, _state, ae_true);
/*
* Prepare network
*/
a1 = (double)(0);
a2 = (double)(0);
if( nkind==2 )
{
a1 = 1000*ae_randomreal(_state)-500;
a2 = 2*ae_randomreal(_state)-1;
}
if( nkind==3 )
{
a1 = 1000*ae_randomreal(_state)-500;
a2 = a1+(2*ae_randominteger(2, _state)-1)*(0.1+0.9*ae_randomreal(_state));
}
/*
* Initialize arrays
*/
ae_vector_set_length(&x1, nin-1+1, _state);
ae_vector_set_length(&x2, nin-1+1, _state);
ae_vector_set_length(&y1, nout-1+1, _state);
ae_vector_set_length(&y2, nout-1+1, _state);
/*
* Main cycle:
* * Pass is a number of repeated test
* * RKind is a "replication kind":
* * RKind=0 means that we work with original ensemble
* * RKind=1 means that we work with replica created with MLPECopy()
* * RKind=2 means that we work with replica created with serialization/unserialization
*/
for(pass=1; pass<=passcount; pass++)
{
for(rkind=0; rkind<=2; rkind++)
{
/*
* Create network, pass through replication in order to test that replicated network works correctly.
*/
testmlpeunit_createensemble(&ensemble, nkind, a1, a2, nin, nhid1, nhid2, nout, ec, _state);
if( rkind==1 )
{
mlpecopy(&ensemble, &ensemble2, _state);
testmlpeunit_unsetensemble(&ensemble, _state);
mlpecopy(&ensemble2, &ensemble, _state);
testmlpeunit_unsetensemble(&ensemble2, _state);
}
if( rkind==2 )
{
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
mlpealloc(&_local_serializer, &ensemble, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpeserialize(&_local_serializer, &ensemble, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpeunserialize(&_local_serializer, &ensemble2, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
testmlpeunit_unsetensemble(&ensemble, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
mlpealloc(&_local_serializer, &ensemble2, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpeserialize(&_local_serializer, &ensemble2, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpeunserialize(&_local_serializer, &ensemble, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
testmlpeunit_unsetensemble(&ensemble2, _state);
}
/*
* Same inputs leads to same outputs
*/
for(i=0; i<=nin-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
for(i=0; i<=nout-1; i++)
{
y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
mlpeprocess(&ensemble, &x1, &y1, _state);
mlpeprocess(&ensemble, &x2, &y2, _state);
allsame = ae_true;
for(i=0; i<=nout-1; i++)
{
allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]);
}
*err = *err||!allsame;
/*
* Same inputs on original network leads to same outputs
* on copy created using MLPCopy
*/
testmlpeunit_unsetensemble(&ensemble2, _state);
mlpecopy(&ensemble, &ensemble2, _state);
for(i=0; i<=nin-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
for(i=0; i<=nout-1; i++)
{
y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
mlpeprocess(&ensemble, &x1, &y1, _state);
mlpeprocess(&ensemble2, &x2, &y2, _state);
allsame = ae_true;
for(i=0; i<=nout-1; i++)
{
allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]);
}
*err = *err||!allsame;
/*
* Same inputs on original network leads to same outputs
* on copy created using MLPSerialize
*/
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
mlpealloc(&_local_serializer, &ensemble, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpeserialize(&_local_serializer, &ensemble, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
mlpeunserialize(&_local_serializer, &ensemble2, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
for(i=0; i<=nin-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
for(i=0; i<=nout-1; i++)
{
y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
mlpeprocess(&ensemble, &x1, &y1, _state);
mlpeprocess(&ensemble2, &x2, &y2, _state);
allsame = ae_true;
for(i=0; i<=nout-1; i++)
{
allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]);
}
*err = *err||!allsame;
/*
* Different inputs leads to different outputs (non-zero network)
*/
for(i=0; i<=nin-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=nout-1; i++)
{
y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
y2.ptr.p_double[i] = y1.ptr.p_double[i];
}
mlpeprocess(&ensemble, &x1, &y1, _state);
mlpeprocess(&ensemble, &x2, &y2, _state);
allsame = ae_true;
for(i=0; i<=nout-1; i++)
{
allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]);
}
*err = *err||allsame;
/*
* Randomization changes outputs (when inputs are unchanged, non-zero network)
*/
for(i=0; i<=nin-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=nout-1; i++)
{
y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
y2.ptr.p_double[i] = y1.ptr.p_double[i];
}
mlpecopy(&ensemble, &ensemble2, _state);
mlperandomize(&ensemble2, _state);
mlpeprocess(&ensemble, &x1, &y1, _state);
mlpeprocess(&ensemble2, &x1, &y2, _state);
allsame = ae_true;
for(i=0; i<=nout-1; i++)
{
allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]);
}
*err = *err||allsame;
/*
* Normalization properties
*/
if( nkind==1 )
{
/*
* Classifier network outputs are normalized
*/
for(i=0; i<=nin-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
mlpeprocess(&ensemble, &x1, &y1, _state);
v = (double)(0);
for(i=0; i<=nout-1; i++)
{
v = v+y1.ptr.p_double[i];
*err = *err||ae_fp_less(y1.ptr.p_double[i],(double)(0));
}
*err = *err||ae_fp_greater(ae_fabs(v-1, _state),1000*ae_machineepsilon);
}
if( nkind==2 )
{
/*
* B-type network outputs are bounded from above/below
*/
for(i=0; i<=nin-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
mlpeprocess(&ensemble, &x1, &y1, _state);
for(i=0; i<=nout-1; i++)
{
if( ae_fp_greater_eq(a2,(double)(0)) )
{
*err = *err||ae_fp_less(y1.ptr.p_double[i],a1);
}
else
{
*err = *err||ae_fp_greater(y1.ptr.p_double[i],a1);
}
}
}
if( nkind==3 )
{
/*
* R-type network outputs are within [A1,A2] (or [A2,A1])
*/
for(i=0; i<=nin-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
mlpeprocess(&ensemble, &x1, &y1, _state);
for(i=0; i<=nout-1; i++)
{
*err = (*err||ae_fp_less(y1.ptr.p_double[i],ae_minreal(a1, a2, _state)))||ae_fp_greater(y1.ptr.p_double[i],ae_maxreal(a1, a2, _state));
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Error functions
Ensemble of type NKind is created, with NIn inputs, NHid1*NHid2 hidden
layers (one layer if NHid2=0), NOut outputs. PassCount random passes is
performed. Dataset has random size in [SizeMin,SizeMax].
*************************************************************************/
static void testmlpeunit_testerr(ae_int_t nkind,
ae_int_t nin,
ae_int_t nhid1,
ae_int_t nhid2,
ae_int_t nout,
ae_int_t ec,
ae_int_t passcount,
ae_int_t sizemin,
ae_int_t sizemax,
ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
mlpensemble ensemble;
sparsematrix sparsexy;
sparsematrix sparsexy2;
ae_int_t n1;
ae_int_t n2;
ae_int_t wcount;
double etol;
double escale;
double a1;
double a2;
ae_int_t pass;
ae_int_t i;
ae_int_t j;
ae_int_t ssize;
ae_matrix xy;
ae_matrix xy2;
ae_vector y;
ae_vector x1;
ae_vector y1;
ae_vector idx;
ae_vector dummy;
double refrmserror;
double refclserror;
double refavgce;
double refavgerror;
double refavgrelerror;
ae_int_t avgrelcnt;
modelerrors allerrors;
ae_int_t nnmax;
ae_int_t dsmax;
ae_frame_make(_state, &_frame_block);
memset(&ensemble, 0, sizeof(ensemble));
memset(&sparsexy, 0, sizeof(sparsexy));
memset(&sparsexy2, 0, sizeof(sparsexy2));
memset(&xy, 0, sizeof(xy));
memset(&xy2, 0, sizeof(xy2));
memset(&y, 0, sizeof(y));
memset(&x1, 0, sizeof(x1));
memset(&y1, 0, sizeof(y1));
memset(&idx, 0, sizeof(idx));
memset(&dummy, 0, sizeof(dummy));
memset(&allerrors, 0, sizeof(allerrors));
_mlpensemble_init(&ensemble, _state, ae_true);
_sparsematrix_init(&sparsexy, _state, ae_true);
_sparsematrix_init(&sparsexy2, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&idx, 0, DT_INT, _state, ae_true);
ae_vector_init(&dummy, 0, DT_INT, _state, ae_true);
_modelerrors_init(&allerrors, _state, ae_true);
a1 = (double)(0);
a2 = (double)(0);
if( nkind==2 )
{
a1 = 1000*ae_randomreal(_state)-500;
a2 = 2*ae_randomreal(_state)-1;
}
if( nkind==3 )
{
a1 = 1000*ae_randomreal(_state)-500;
a2 = a1+(2*ae_randominteger(2, _state)-1)*(0.1+0.9*ae_randomreal(_state));
}
testmlpeunit_createensemble(&ensemble, nkind, a1, a2, nin, nhid1, nhid2, nout, ec, _state);
mlpproperties(&ensemble.network, &n1, &n2, &wcount, _state);
etol = 1.0E-4;
escale = 1.0E-2;
/*
* Initialize
*/
ae_vector_set_length(&x1, nin, _state);
ae_vector_set_length(&y, nout, _state);
ae_vector_set_length(&y1, nout, _state);
/*
* Process
*/
for(pass=1; pass<=passcount; pass++)
{
/*
* Randomize Ensemble, then re-randomaze weights manually.
*
* NOTE: weights magnitude is chosen to be small, about 0.1,
* which allows us to avoid oversaturated Ensemble.
* In 10% of cases we use zero weights.
*/
mlperandomize(&ensemble, _state);
if( ae_fp_less_eq(ae_randomreal(_state),0.1) )
{
for(i=0; i<=wcount*ec-1; i++)
{
ensemble.weights.ptr.p_double[i] = 0.0;
}
}
else
{
for(i=0; i<=wcount*ec-1; i++)
{
ensemble.weights.ptr.p_double[i] = 0.2*ae_randomreal(_state)-0.1;
}
}
/*
* Generate random dataset.
* Calculate reference errors.
*
* NOTE: about 10% of tests are performed with zero SSize
*/
ssize = sizemin+ae_randominteger(sizemax-sizemin+1, _state);
if( mlpeissoftmax(&ensemble, _state) )
{
ae_matrix_set_length(&xy, ae_maxint(ssize, 1, _state), nin+1, _state);
sparsecreate(ae_maxint(ssize, 1, _state), nin+1, 0, &sparsexy, _state);
}
else
{
ae_matrix_set_length(&xy, ae_maxint(ssize, 1, _state), nin+nout, _state);
sparsecreate(ae_maxint(ssize, 1, _state), nin+nout, 0, &sparsexy, _state);
}
refrmserror = 0.0;
refclserror = 0.0;
refavgce = 0.0;
refavgerror = 0.0;
refavgrelerror = 0.0;
avgrelcnt = 0;
for(i=0; i<=ssize-1; i++)
{
/*
* Fill I-th row
*/
for(j=0; j<=nin-1; j++)
{
x1.ptr.p_double[j] = 4*ae_randomreal(_state)-2;
sparseset(&sparsexy, i, j, x1.ptr.p_double[j], _state);
}
ae_v_move(&xy.ptr.pp_double[i][0], 1, &x1.ptr.p_double[0], 1, ae_v_len(0,nin-1));
if( mlpeissoftmax(&ensemble, _state) )
{
for(j=0; j<=nout-1; j++)
{
y1.ptr.p_double[j] = (double)(0);
}
xy.ptr.pp_double[i][nin] = (double)(ae_randominteger(nout, _state));
sparseset(&sparsexy, i, nin, xy.ptr.pp_double[i][nin], _state);
y1.ptr.p_double[ae_round(xy.ptr.pp_double[i][nin], _state)] = (double)(1);
}
else
{
for(j=0; j<=nout-1; j++)
{
y1.ptr.p_double[j] = 4*ae_randomreal(_state)-2;
sparseset(&sparsexy, i, nin+j, y1.ptr.p_double[j], _state);
}
ae_v_move(&xy.ptr.pp_double[i][nin], 1, &y1.ptr.p_double[0], 1, ae_v_len(nin,nin+nout-1));
}
/*
* Process
*/
mlpeprocess(&ensemble, &x1, &y, _state);
/*
* Update reference errors
*/
nnmax = 0;
if( mlpeissoftmax(&ensemble, _state) )
{
if( ae_fp_greater(y.ptr.p_double[ae_round(xy.ptr.pp_double[i][nin], _state)],(double)(0)) )
{
refavgce = refavgce+ae_log(1/y.ptr.p_double[ae_round(xy.ptr.pp_double[i][nin], _state)], _state);
}
else
{
refavgce = refavgce+ae_log(ae_maxrealnumber, _state);
}
}
if( mlpeissoftmax(&ensemble, _state) )
{
dsmax = ae_round(xy.ptr.pp_double[i][nin], _state);
}
else
{
dsmax = 0;
}
for(j=0; j<=nout-1; j++)
{
refrmserror = refrmserror+ae_sqr(y.ptr.p_double[j]-y1.ptr.p_double[j], _state);
refavgerror = refavgerror+ae_fabs(y.ptr.p_double[j]-y1.ptr.p_double[j], _state);
if( ae_fp_neq(y1.ptr.p_double[j],(double)(0)) )
{
refavgrelerror = refavgrelerror+ae_fabs(y.ptr.p_double[j]-y1.ptr.p_double[j], _state)/ae_fabs(y1.ptr.p_double[j], _state);
avgrelcnt = avgrelcnt+1;
}
if( ae_fp_greater(y.ptr.p_double[j],y.ptr.p_double[nnmax]) )
{
nnmax = j;
}
if( !mlpeissoftmax(&ensemble, _state)&&ae_fp_greater(y1.ptr.p_double[j],y1.ptr.p_double[dsmax]) )
{
dsmax = j;
}
}
if( nnmax!=dsmax )
{
refclserror = refclserror+1;
}
}
sparseconverttocrs(&sparsexy, _state);
if( ssize>0 )
{
refrmserror = ae_sqrt(refrmserror/(ssize*nout), _state);
refavgerror = refavgerror/(ssize*nout);
refavgce = refavgce/(ssize*ae_log((double)(2), _state));
}
if( avgrelcnt>0 )
{
refavgrelerror = refavgrelerror/avgrelcnt;
}
/*
* Test "continuous" errors on full dataset
*/
seterrorflagdiff(err, mlpermserror(&ensemble, &xy, ssize, _state), refrmserror, etol, escale, _state);
seterrorflagdiff(err, mlpeavgce(&ensemble, &xy, ssize, _state), refavgce, etol, escale, _state);
seterrorflagdiff(err, mlpeavgerror(&ensemble, &xy, ssize, _state), refavgerror, etol, escale, _state);
seterrorflagdiff(err, mlpeavgrelerror(&ensemble, &xy, ssize, _state), refavgrelerror, etol, escale, _state);
}
ae_frame_leave(_state);
}
static ae_bool testmlptrainunit_testmlptraines(ae_state *_state);
static ae_bool testmlptrainunit_testmlptrainregr(ae_state *_state);
static ae_bool testmlptrainunit_testmlpxorregr(ae_state *_state);
static ae_bool testmlptrainunit_testmlptrainclass(ae_state *_state);
static ae_bool testmlptrainunit_testmlpxorcls(ae_state *_state);
static ae_bool testmlptrainunit_testmlpzeroweights(ae_state *_state);
static ae_bool testmlptrainunit_testmlprestarts(ae_state *_state);
static ae_bool testmlptrainunit_testmlpcverror(ae_state *_state);
static ae_bool testmlptrainunit_testmlptrainens(ae_state *_state);
static ae_bool testmlptrainunit_testmlptrainensregr(ae_state *_state);
static ae_bool testmlptrainunit_testmlptrainenscls(ae_state *_state);
ae_bool testmlptrain(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_bool waserrors;
ae_int_t info;
multilayerperceptron network;
multilayerperceptron network2;
mlpreport rep;
mlpcvreport cvrep;
ae_matrix xy;
ae_matrix valxy;
ae_bool trnerrors;
ae_bool mlpcverrorerr;
ae_bool mlptrainregrerr;
ae_bool mlptrainclasserr;
ae_bool mlprestartserr;
ae_bool mlpxorregrerr;
ae_bool mlpxorclserr;
ae_bool mlptrainenserrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&network, 0, sizeof(network));
memset(&network2, 0, sizeof(network2));
memset(&rep, 0, sizeof(rep));
memset(&cvrep, 0, sizeof(cvrep));
memset(&xy, 0, sizeof(xy));
memset(&valxy, 0, sizeof(valxy));
_multilayerperceptron_init(&network, _state, ae_true);
_multilayerperceptron_init(&network2, _state, ae_true);
_mlpreport_init(&rep, _state, ae_true);
_mlpcvreport_init(&cvrep, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&valxy, 0, 0, DT_REAL, _state, ae_true);
waserrors = ae_false;
trnerrors = ae_false;
mlpcverrorerr = ae_false;
mlptrainregrerr = ae_false;
mlptrainclasserr = ae_false;
mlprestartserr = ae_false;
mlpxorregrerr = ae_false;
mlpxorclserr = ae_false;
mlptrainenserrors = ae_false;
/*
* Test network training on simple XOR problem
*/
ae_matrix_set_length(&xy, 3+1, 2+1, _state);
xy.ptr.pp_double[0][0] = (double)(-1);
xy.ptr.pp_double[0][1] = (double)(-1);
xy.ptr.pp_double[0][2] = (double)(-1);
xy.ptr.pp_double[1][0] = (double)(1);
xy.ptr.pp_double[1][1] = (double)(-1);
xy.ptr.pp_double[1][2] = (double)(1);
xy.ptr.pp_double[2][0] = (double)(-1);
xy.ptr.pp_double[2][1] = (double)(1);
xy.ptr.pp_double[2][2] = (double)(1);
xy.ptr.pp_double[3][0] = (double)(1);
xy.ptr.pp_double[3][1] = (double)(1);
xy.ptr.pp_double[3][2] = (double)(-1);
mlpcreate1(2, 2, 1, &network, _state);
mlptrainlm(&network, &xy, 4, 0.001, 10, &info, &rep, _state);
trnerrors = trnerrors||ae_fp_greater(mlprmserror(&network, &xy, 4, _state),0.1);
/*
* Test early stopping
*/
trnerrors = trnerrors||testmlptrainunit_testmlptraines(_state);
/*
* Test for function MLPFoldCV()
*/
mlpcverrorerr = testmlptrainunit_testmlpcverror(_state);
/*
* Test for training functions
*/
mlptrainregrerr = testmlptrainunit_testmlptrainregr(_state)||testmlptrainunit_testmlpzeroweights(_state);
mlptrainclasserr = testmlptrainunit_testmlptrainclass(_state);
mlprestartserr = testmlptrainunit_testmlprestarts(_state);
mlpxorregrerr = testmlptrainunit_testmlpxorregr(_state);
mlpxorclserr = testmlptrainunit_testmlpxorcls(_state);
/*
* Training for ensembles
*/
mlptrainenserrors = (testmlptrainunit_testmlptrainens(_state)||testmlptrainunit_testmlptrainensregr(_state))||testmlptrainunit_testmlptrainenscls(_state);
/*
* Final report
*/
waserrors = ((((((trnerrors||mlptrainregrerr)||mlptrainclasserr)||mlprestartserr)||mlpxorregrerr)||mlpxorclserr)||mlpcverrorerr)||mlptrainenserrors;
if( !silent )
{
printf("MLP TEST\n");
printf("CROSS-VALIDATION ERRORS: ");
if( !mlpcverrorerr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("TRAINING: ");
if( !trnerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("TRAIN -LM -LBFGS FOR REGRESSION: ");
if( mlptrainregrerr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("TRAIN -LM -LBFGS FOR CLASSIFIER: ");
if( mlptrainclasserr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("PARAMETER RESTARTS IN TRAIN -LBFGS: ");
if( mlprestartserr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("TRAINIG WITH TRAINER FOR REGRESSION: ");
if( mlpxorregrerr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("TRAINIG WITH TRAINER FOR CLASSIFIER: ");
if( mlpxorclserr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("TRAINING ENSEMBLES: ");
if( mlptrainenserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST SUMMARY: FAILED\n");
}
else
{
printf("TEST SUMMARY: PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function tests MLPTrainES().
It returns True in case of errors, False when no errors were detected
*************************************************************************/
static ae_bool testmlptrainunit_testmlptraines(ae_state *_state)
{
ae_frame _frame_block;
ae_int_t pass;
ae_int_t passcount;
multilayerperceptron network;
ae_matrix trnxy;
ae_matrix valxy;
ae_vector x;
ae_vector y;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_int_t nrestarts;
ae_int_t info;
mlpreport rep;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&network, 0, sizeof(network));
memset(&trnxy, 0, sizeof(trnxy));
memset(&valxy, 0, sizeof(valxy));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&rep, 0, sizeof(rep));
_multilayerperceptron_init(&network, _state, ae_true);
ae_matrix_init(&trnxy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&valxy, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
_mlpreport_init(&rep, _state, ae_true);
result = ae_false;
/*
* First test checks that MLPTrainES() - when training set is equal to the validation
* set, MLPTrainES() behaves just like a "normal" training algorithm.
*
* Test sequence:
* * generate training set - 100 random points from 2D square [-1,+1]*[-1,+1]
* * generate network with 2 inputs, no hidden layers, nonlinear output layer,
* use its outputs as target values for the test set
* * randomize network
* * train with MLPTrainES(), using original set as both training and validation set
* * trained network must reproduce training set with good precision
*
* NOTE: it is important to test algorithm on nonlinear network because linear
* problems converge too fast. Slow convergence is important to detect
* some kinds of bugs.
*
* NOTE: it is important to have NRestarts at least equal to 5, because with just
* one restart algorithm fails test about once in several thousands of passes.
*/
passcount = 10;
nrestarts = 5;
for(pass=1; pass<=passcount; pass++)
{
/*
* Create network, generate training/validation sets
*/
mlpcreater0(2, 1, -2.0, 2.0, &network, _state);
mlprandomize(&network, _state);
n = 100;
ae_matrix_set_length(&trnxy, n, 3, _state);
ae_matrix_set_length(&valxy, n, 3, _state);
ae_vector_set_length(&x, 2, _state);
ae_vector_set_length(&y, 1, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=1; j++)
{
trnxy.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
valxy.ptr.pp_double[i][j] = trnxy.ptr.pp_double[i][j];
x.ptr.p_double[j] = trnxy.ptr.pp_double[i][j];
}
mlpprocess(&network, &x, &y, _state);
trnxy.ptr.pp_double[i][2] = y.ptr.p_double[0];
valxy.ptr.pp_double[i][2] = y.ptr.p_double[0];
}
mlprandomize(&network, _state);
mlptraines(&network, &trnxy, n, &valxy, n, 0.0001, nrestarts, &info, &rep, _state);
if( info<=0 )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
if( ae_fp_greater(ae_sqrt(mlperror(&network, &valxy, n, _state)/n, _state),0.01) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function tests MLPTrainLM, MLPTrainLBFGS and MLPTrainNetwork
functions for regression. It check that train functions work correctly.
Test use Create1 with 10 neurons.
Test function is f(x,y)=X^2+cos(3*Pi*y).
*************************************************************************/
static ae_bool testmlptrainunit_testmlptrainregr(ae_state *_state)
{
ae_frame _frame_block;
multilayerperceptron net;
mlptrainer trainer;
mlpreport rep;
ae_int_t info;
ae_matrix xy;
sparsematrix sm;
ae_vector x;
ae_vector y;
ae_int_t n;
ae_int_t sn;
ae_int_t nneurons;
double vdecay;
double averr;
double st;
double eps;
double traineps;
ae_int_t nneedrest;
ae_int_t trainits;
ae_int_t shift;
ae_int_t i;
ae_int_t j;
ae_int_t vtrain;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&net, 0, sizeof(net));
memset(&trainer, 0, sizeof(trainer));
memset(&rep, 0, sizeof(rep));
memset(&xy, 0, sizeof(xy));
memset(&sm, 0, sizeof(sm));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
_multilayerperceptron_init(&net, _state, ae_true);
_mlptrainer_init(&trainer, _state, ae_true);
_mlpreport_init(&rep, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_sparsematrix_init(&sm, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
eps = 0.01;
vdecay = 0.001;
nneurons = 10;
nneedrest = 5;
traineps = 1.0E-3;
trainits = 0;
sn = 5;
n = sn*sn;
st = (double)2/(double)(sn-1);
sparsecreate(n, 3, n*3, &sm, _state);
ae_matrix_set_length(&xy, n, 3, _state);
ae_vector_set_length(&x, 2, _state);
for(vtrain=0; vtrain<=3; vtrain++)
{
averr = (double)(0);
/*
* Create a train set(uniformly distributed set of points).
*/
for(i=0; i<=sn-1; i++)
{
for(j=0; j<=sn-1; j++)
{
shift = i*sn+j;
xy.ptr.pp_double[shift][0] = i*st-1.0;
xy.ptr.pp_double[shift][1] = j*st-1.0;
xy.ptr.pp_double[shift][2] = xy.ptr.pp_double[shift][0]*xy.ptr.pp_double[shift][0]+ae_cos(3*ae_pi*xy.ptr.pp_double[shift][1], _state);
}
}
/*
* Create and train a neural network
*/
mlpcreate1(2, nneurons, 1, &net, _state);
if( vtrain==0 )
{
mlptrainlm(&net, &xy, n, vdecay, nneedrest, &info, &rep, _state);
}
if( vtrain==1 )
{
mlptrainlbfgs(&net, &xy, n, vdecay, nneedrest, traineps, trainits, &info, &rep, _state);
}
/*
* Train with trainer, using:
* * dense matrix;
*/
if( vtrain==2 )
{
mlpcreatetrainer(2, 1, &trainer, _state);
mlpsetdataset(&trainer, &xy, n, _state);
mlpsetdecay(&trainer, vdecay, _state);
mlpsetcond(&trainer, traineps, trainits, _state);
mlptrainnetwork(&trainer, &net, nneedrest, &rep, _state);
}
/*
* * sparse matrix.
*/
if( vtrain==3 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=2; j++)
{
sparseset(&sm, i, j, xy.ptr.pp_double[i][j], _state);
}
}
mlpcreatetrainer(2, 1, &trainer, _state);
mlpsetsparsedataset(&trainer, &sm, n, _state);
mlpsetdecay(&trainer, vdecay, _state);
mlpsetcond(&trainer, traineps, trainits, _state);
mlptrainnetwork(&trainer, &net, nneedrest, &rep, _state);
}
/*
* Check that network is trained correctly
*/
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[0] = xy.ptr.pp_double[i][0];
x.ptr.p_double[1] = xy.ptr.pp_double[i][1];
mlpprocess(&net, &x, &y, _state);
/*
* Calculate average error
*/
averr = averr+ae_fabs(y.ptr.p_double[0]-xy.ptr.pp_double[i][2], _state);
}
if( ae_fp_greater(averr/n,eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function tests MLPTrainNetwork/MLPStartTraining/MLPContinueTraining
functions for regression. It check that train functions work correctly.
Test use Create1 with 2 neurons.
Test function is XOR(x,y).
*************************************************************************/
static ae_bool testmlptrainunit_testmlpxorregr(ae_state *_state)
{
ae_frame _frame_block;
multilayerperceptron net;
mlptrainer trainer;
mlpreport rep;
ae_matrix xy;
sparsematrix sm;
ae_vector x;
ae_vector y;
ae_int_t n;
ae_int_t sn;
ae_int_t nneurons;
double vdecay;
double averr;
double eps;
ae_int_t numxp;
double traineps;
ae_int_t nneedrest;
ae_int_t trainits;
ae_int_t shift;
ae_int_t i;
ae_int_t j;
ae_int_t vtrain;
ae_int_t xp;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&net, 0, sizeof(net));
memset(&trainer, 0, sizeof(trainer));
memset(&rep, 0, sizeof(rep));
memset(&xy, 0, sizeof(xy));
memset(&sm, 0, sizeof(sm));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
_multilayerperceptron_init(&net, _state, ae_true);
_mlptrainer_init(&trainer, _state, ae_true);
_mlpreport_init(&rep, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_sparsematrix_init(&sm, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
eps = 0.01;
numxp = 15;
vdecay = 0.001;
nneurons = 3;
nneedrest = 1;
traineps = 1.0E-4;
trainits = 0;
sn = 2;
n = sn*sn;
sparsecreate(n, 3, n*3, &sm, _state);
ae_matrix_set_length(&xy, n, 3, _state);
ae_vector_set_length(&x, 2, _state);
for(xp=1; xp<=numxp; xp++)
{
for(vtrain=0; vtrain<=3; vtrain++)
{
averr = (double)(0);
/*
* Create a train set(uniformly distributed set of points).
*/
for(i=0; i<=sn-1; i++)
{
for(j=0; j<=sn-1; j++)
{
shift = i*sn+j;
xy.ptr.pp_double[shift][0] = (double)(i);
xy.ptr.pp_double[shift][1] = (double)(j);
if( ae_fp_eq(xy.ptr.pp_double[shift][0],xy.ptr.pp_double[shift][1]) )
{
xy.ptr.pp_double[shift][2] = (double)(0);
}
else
{
xy.ptr.pp_double[shift][2] = (double)(1);
}
}
}
/*
* Create and train a neural network
*/
mlpcreate1(2, nneurons, 1, &net, _state);
/*
* Train with trainer, using:
* * dense matrix;
*/
if( vtrain==0 )
{
mlpcreatetrainer(2, 1, &trainer, _state);
mlpsetdataset(&trainer, &xy, n, _state);
mlpsetdecay(&trainer, vdecay, _state);
mlpsetcond(&trainer, traineps, trainits, _state);
mlptrainnetwork(&trainer, &net, nneedrest, &rep, _state);
}
if( vtrain==1 )
{
mlpcreatetrainer(2, 1, &trainer, _state);
mlpsetdataset(&trainer, &xy, n, _state);
mlpsetdecay(&trainer, vdecay, _state);
mlpsetcond(&trainer, traineps, trainits, _state);
mlpstarttraining(&trainer, &net, ae_true, _state);
while(mlpcontinuetraining(&trainer, &net, _state))
{
}
}
/*
* * sparse matrix.
*/
if( vtrain==2 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=2; j++)
{
sparseset(&sm, i, j, xy.ptr.pp_double[i][j], _state);
}
}
mlpcreatetrainer(2, 1, &trainer, _state);
mlpsetsparsedataset(&trainer, &sm, n, _state);
mlpsetdecay(&trainer, vdecay, _state);
mlpsetcond(&trainer, traineps, trainits, _state);
mlptrainnetwork(&trainer, &net, nneedrest, &rep, _state);
}
if( vtrain==3 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=2; j++)
{
sparseset(&sm, i, j, xy.ptr.pp_double[i][j], _state);
}
}
mlpcreatetrainer(2, 1, &trainer, _state);
mlpsetsparsedataset(&trainer, &sm, n, _state);
mlpsetdecay(&trainer, vdecay, _state);
mlpsetcond(&trainer, traineps, trainits, _state);
mlpstarttraining(&trainer, &net, ae_true, _state);
while(mlpcontinuetraining(&trainer, &net, _state))
{
}
}
/*
* Check that network is trained correctly
*/
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[0] = xy.ptr.pp_double[i][0];
x.ptr.p_double[1] = xy.ptr.pp_double[i][1];
mlpprocess(&net, &x, &y, _state);
/*
* Calculate average error
*/
averr = averr+ae_fabs(y.ptr.p_double[0]-xy.ptr.pp_double[i][2], _state);
}
if( ae_fp_greater(averr/n,eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function tests MLPTrainLM, MLPTrainLBFGS and MLPTrainNetwork
functions for classification problems. It check that train functions work
correctly when is used CreateC1 function. Here the network tries to
distinguish positive from negative numbers.
*************************************************************************/
static ae_bool testmlptrainunit_testmlptrainclass(ae_state *_state)
{
ae_frame _frame_block;
multilayerperceptron net;
mlptrainer trainer;
mlpreport rep;
ae_int_t info;
ae_matrix xy;
sparsematrix sm;
ae_vector x;
ae_vector y;
ae_int_t n;
double vdecay;
double traineps;
ae_int_t nneedrest;
ae_int_t trainits;
double tmp;
double mnc;
double mxc;
ae_int_t nxp;
ae_int_t i;
ae_int_t rndind;
ae_int_t vtrain;
ae_int_t xp;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&net, 0, sizeof(net));
memset(&trainer, 0, sizeof(trainer));
memset(&rep, 0, sizeof(rep));
memset(&xy, 0, sizeof(xy));
memset(&sm, 0, sizeof(sm));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
_multilayerperceptron_init(&net, _state, ae_true);
_mlptrainer_init(&trainer, _state, ae_true);
_mlpreport_init(&rep, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_sparsematrix_init(&sm, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
mnc = (double)(10);
mxc = (double)(11);
nxp = 15;
vdecay = 0.001;
nneedrest = 10;
traineps = 1.0E-4;
trainits = 0;
n = 100;
sparsecreate(n, 2, n*2, &sm, _state);
ae_vector_set_length(&x, 1, _state);
ae_matrix_set_length(&xy, n, 2, _state);
for(xp=1; xp<=nxp; xp++)
{
for(vtrain=0; vtrain<=3; vtrain++)
{
/*
* Initialization:
* * create negative part of the set;
*/
for(i=0; i<=n/2-1; i++)
{
xy.ptr.pp_double[i][0] = -1*((mxc-mnc)*ae_randomreal(_state)+mnc);
xy.ptr.pp_double[i][1] = (double)(0);
}
/*
* * create positive part of the set;
*/
for(i=n/2; i<=n-1; i++)
{
xy.ptr.pp_double[i][0] = (mxc-mnc)*ae_randomreal(_state)+mnc;
xy.ptr.pp_double[i][1] = (double)(1);
}
/*
* * mix two parts.
*/
for(i=0; i<=n-1; i++)
{
do
{
rndind = ae_randominteger(n, _state);
}
while(rndind==i);
tmp = xy.ptr.pp_double[i][0];
xy.ptr.pp_double[i][0] = xy.ptr.pp_double[rndind][0];
xy.ptr.pp_double[rndind][0] = tmp;
tmp = xy.ptr.pp_double[i][1];
xy.ptr.pp_double[i][1] = xy.ptr.pp_double[rndind][1];
xy.ptr.pp_double[rndind][1] = tmp;
}
/*
* Create and train a neural network
*/
mlpcreatec0(1, 2, &net, _state);
if( vtrain==0 )
{
mlptrainlm(&net, &xy, n, vdecay, nneedrest, &info, &rep, _state);
}
if( vtrain==1 )
{
mlptrainlbfgs(&net, &xy, n, vdecay, nneedrest, traineps, trainits, &info, &rep, _state);
}
/*
* Train with trainer, using:
* * dense matrix;
*/
if( vtrain==2 )
{
mlpcreatetrainercls(1, 2, &trainer, _state);
mlpsetdataset(&trainer, &xy, n, _state);
mlpsetdecay(&trainer, vdecay, _state);
mlpsetcond(&trainer, traineps, trainits, _state);
mlptrainnetwork(&trainer, &net, nneedrest, &rep, _state);
}
/*
* * sparse matrix.
*/
if( vtrain==3 )
{
for(i=0; i<=n-1; i++)
{
sparseset(&sm, i, 0, xy.ptr.pp_double[i][0], _state);
sparseset(&sm, i, 1, xy.ptr.pp_double[i][1], _state);
}
mlpcreatetrainercls(1, 2, &trainer, _state);
mlpsetsparsedataset(&trainer, &sm, n, _state);
mlpsetdecay(&trainer, vdecay, _state);
mlpsetcond(&trainer, traineps, trainits, _state);
mlptrainnetwork(&trainer, &net, nneedrest, &rep, _state);
}
/*
* Test on training set
*/
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[0] = xy.ptr.pp_double[i][0];
mlpprocess(&net, &x, &y, _state);
/*
* Negative number has to be negative and
* positive number has to be positive.
*/
if( ((ae_fp_less(x.ptr.p_double[0],(double)(0))&&ae_fp_less(y.ptr.p_double[0],0.95))&&ae_fp_greater(y.ptr.p_double[1],0.05))||((ae_fp_greater_eq(x.ptr.p_double[0],(double)(0))&&ae_fp_greater(y.ptr.p_double[0],0.05))&&ae_fp_less(y.ptr.p_double[1],0.95)) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
/*
* Test on random set
*/
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[0] = ae_pow((double)(-1), (double)(ae_randominteger(2, _state)), _state)*((mxc-mnc)*ae_randomreal(_state)+mnc);
mlpprocess(&net, &x, &y, _state);
if( ((ae_fp_less(x.ptr.p_double[0],(double)(0))&&ae_fp_less(y.ptr.p_double[0],0.95))&&ae_fp_greater(y.ptr.p_double[1],0.05))||((ae_fp_greater_eq(x.ptr.p_double[0],(double)(0))&&ae_fp_greater(y.ptr.p_double[0],0.05))&&ae_fp_less(y.ptr.p_double[1],0.95)) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function tests MLPTrainNetwork/MLPStartTraining/MLPContinueTraining
functions for classification problems. It check that train functions work
correctly when is used CreateC1 function. Here the network tries to
distinguish positive from negative numbers.
*************************************************************************/
static ae_bool testmlptrainunit_testmlpxorcls(ae_state *_state)
{
ae_frame _frame_block;
multilayerperceptron net;
mlptrainer trainer;
mlpreport rep;
ae_matrix xy;
sparsematrix sm;
ae_vector x;
ae_vector y;
ae_int_t n;
ae_int_t nin;
ae_int_t nout;
ae_int_t wcount;
double e;
double ebest;
double v;
ae_vector wbest;
double vdecay;
double traineps;
ae_int_t nneurons;
ae_int_t nneedrest;
ae_int_t trainits;
ae_int_t nxp;
ae_int_t i;
ae_int_t vtrain;
ae_int_t xp;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&net, 0, sizeof(net));
memset(&trainer, 0, sizeof(trainer));
memset(&rep, 0, sizeof(rep));
memset(&xy, 0, sizeof(xy));
memset(&sm, 0, sizeof(sm));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&wbest, 0, sizeof(wbest));
_multilayerperceptron_init(&net, _state, ae_true);
_mlptrainer_init(&trainer, _state, ae_true);
_mlpreport_init(&rep, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_sparsematrix_init(&sm, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&wbest, 0, DT_REAL, _state, ae_true);
nxp = 15;
nneurons = 3;
vdecay = 0.001;
nneedrest = 3;
traineps = 1.0E-4;
trainits = 0;
n = 4;
sparsecreate(n, 3, n*3, &sm, _state);
ae_vector_set_length(&x, 2, _state);
ae_matrix_set_length(&xy, n, 3, _state);
/*
* Initialization:
*/
xy.ptr.pp_double[0][0] = (double)(0);
xy.ptr.pp_double[0][1] = (double)(0);
xy.ptr.pp_double[0][2] = (double)(0);
xy.ptr.pp_double[1][0] = (double)(0);
xy.ptr.pp_double[1][1] = (double)(1);
xy.ptr.pp_double[1][2] = (double)(1);
xy.ptr.pp_double[2][0] = (double)(1);
xy.ptr.pp_double[2][1] = (double)(0);
xy.ptr.pp_double[2][2] = (double)(1);
xy.ptr.pp_double[3][0] = (double)(1);
xy.ptr.pp_double[3][1] = (double)(1);
xy.ptr.pp_double[3][2] = (double)(0);
/*
* Create a neural network
*/
mlpcreatec1(2, nneurons, 2, &net, _state);
mlpproperties(&net, &nin, &nout, &wcount, _state);
ae_vector_set_length(&wbest, wcount, _state);
/*
* Test
*/
for(xp=1; xp<=nxp; xp++)
{
for(vtrain=0; vtrain<=3; vtrain++)
{
/*
* Train with trainer, using:
* * dense matrix;
*/
if( vtrain==0 )
{
mlpcreatetrainercls(2, 2, &trainer, _state);
mlpsetdataset(&trainer, &xy, n, _state);
mlpsetdecay(&trainer, vdecay, _state);
mlpsetcond(&trainer, traineps, trainits, _state);
mlptrainnetwork(&trainer, &net, nneedrest, &rep, _state);
}
if( vtrain==1 )
{
mlpcreatetrainercls(2, 2, &trainer, _state);
mlpsetdataset(&trainer, &xy, n, _state);
mlpsetdecay(&trainer, vdecay, _state);
mlpsetcond(&trainer, traineps, trainits, _state);
ebest = ae_maxrealnumber;
for(i=1; i<=nneedrest; i++)
{
mlpstarttraining(&trainer, &net, ae_true, _state);
while(mlpcontinuetraining(&trainer, &net, _state))
{
}
v = ae_v_dotproduct(&net.weights.ptr.p_double[0], 1, &net.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
e = mlperror(&net, &xy, n, _state)+0.5*vdecay*v;
/*
* Compare with the best answer.
*/
if( ae_fp_less(e,ebest) )
{
ae_v_move(&wbest.ptr.p_double[0], 1, &net.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
ebest = e;
}
}
/*
* The best result
*/
ae_v_move(&net.weights.ptr.p_double[0], 1, &wbest.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
}
/*
* * sparse matrix.
*/
if( vtrain==2 )
{
for(i=0; i<=n-1; i++)
{
sparseset(&sm, i, 0, xy.ptr.pp_double[i][0], _state);
sparseset(&sm, i, 1, xy.ptr.pp_double[i][1], _state);
sparseset(&sm, i, 2, xy.ptr.pp_double[i][2], _state);
}
mlpcreatetrainercls(2, 2, &trainer, _state);
mlpsetsparsedataset(&trainer, &sm, n, _state);
mlpsetdecay(&trainer, vdecay, _state);
mlpsetcond(&trainer, traineps, trainits, _state);
mlptrainnetwork(&trainer, &net, nneedrest, &rep, _state);
}
if( vtrain==3 )
{
for(i=0; i<=n-1; i++)
{
sparseset(&sm, i, 0, xy.ptr.pp_double[i][0], _state);
sparseset(&sm, i, 1, xy.ptr.pp_double[i][1], _state);
sparseset(&sm, i, 2, xy.ptr.pp_double[i][2], _state);
}
mlpcreatetrainercls(2, 2, &trainer, _state);
mlpsetsparsedataset(&trainer, &sm, n, _state);
mlpsetdecay(&trainer, vdecay, _state);
mlpsetcond(&trainer, traineps, trainits, _state);
ebest = ae_maxrealnumber;
for(i=1; i<=nneedrest; i++)
{
mlpstarttraining(&trainer, &net, ae_true, _state);
while(mlpcontinuetraining(&trainer, &net, _state))
{
}
v = ae_v_dotproduct(&net.weights.ptr.p_double[0], 1, &net.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
e = mlperror(&net, &xy, n, _state)+0.5*vdecay*v;
/*
* Compare with the best answer.
*/
if( ae_fp_less(e,ebest) )
{
ae_v_move(&wbest.ptr.p_double[0], 1, &net.weights.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
ebest = e;
}
}
/*
* The best result
*/
ae_v_move(&net.weights.ptr.p_double[0], 1, &wbest.ptr.p_double[0], 1, ae_v_len(0,wcount-1));
}
/*
* Test on training set
*/
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[0] = xy.ptr.pp_double[i][0];
x.ptr.p_double[1] = xy.ptr.pp_double[i][1];
mlpprocess(&net, &x, &y, _state);
if( ((ae_fp_eq(x.ptr.p_double[0],x.ptr.p_double[1])&&ae_fp_less(y.ptr.p_double[0],0.95))&&ae_fp_greater(y.ptr.p_double[1],0.05))||((ae_fp_neq(x.ptr.p_double[0],x.ptr.p_double[1])&&ae_fp_greater(y.ptr.p_double[0],0.05))&&ae_fp_less(y.ptr.p_double[1],0.95)) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
The test check, that all weights are zero after training with trainer
using empty dataset(either zero size or is't used MLPSetDataSet function).
Test on regression and classification problems given by dense or sparse
matrix.
NOTE: Result of the function is written in MLPTrainRegrErr variable in
unit test.
*************************************************************************/
static ae_bool testmlptrainunit_testmlpzeroweights(ae_state *_state)
{
ae_frame _frame_block;
mlptrainer trainer;
multilayerperceptron net;
mlpreport rep;
ae_int_t nin;
ae_int_t nout;
ae_int_t wcount;
ae_int_t mxnin;
ae_int_t mxnout;
double vdecay;
double traineps;
ae_int_t trainits;
ae_int_t nneedrest;
ae_matrix dds;
sparsematrix sds;
ae_bool iscls;
ae_bool issparse;
ae_int_t c;
ae_int_t n;
ae_int_t xp;
ae_int_t nxp;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&trainer, 0, sizeof(trainer));
memset(&net, 0, sizeof(net));
memset(&rep, 0, sizeof(rep));
memset(&dds, 0, sizeof(dds));
memset(&sds, 0, sizeof(sds));
_mlptrainer_init(&trainer, _state, ae_true);
_multilayerperceptron_init(&net, _state, ae_true);
_mlpreport_init(&rep, _state, ae_true);
ae_matrix_init(&dds, 0, 0, DT_REAL, _state, ae_true);
_sparsematrix_init(&sds, _state, ae_true);
mxnin = 10;
mxnout = 10;
vdecay = 1.0E-3;
nneedrest = 1;
traineps = 1.0E-3;
trainits = 0;
sparsecreate(1, 1, 0, &sds, _state);
sparseconverttocrs(&sds, _state);
nxp = 10;
for(xp=1; xp<=nxp; xp++)
{
c = ae_randominteger(2, _state);
iscls = c==1;
c = ae_randominteger(2, _state);
issparse = c==1;
/*
* Create trainer and network
*/
if( !iscls )
{
/*
* Regression
*/
nin = ae_randominteger(mxnin, _state)+1;
nout = ae_randominteger(mxnout, _state)+1;
mlpcreatetrainer(nin, nout, &trainer, _state);
mlpcreate0(nin, nout, &net, _state);
}
else
{
/*
* Classification
*/
nin = ae_randominteger(mxnin, _state)+1;
nout = ae_randominteger(mxnout, _state)+2;
mlpcreatetrainercls(nin, nout, &trainer, _state);
mlpcreatec0(nin, nout, &net, _state);
}
n = ae_randominteger(2, _state)-1;
if( n==0 )
{
if( !issparse )
{
mlpsetdataset(&trainer, &dds, n, _state);
}
else
{
mlpsetsparsedataset(&trainer, &sds, n, _state);
}
}
mlpsetdecay(&trainer, vdecay, _state);
mlpsetcond(&trainer, traineps, trainits, _state);
c = ae_randominteger(2, _state);
if( c==0 )
{
mlpstarttraining(&trainer, &net, ae_true, _state);
while(mlpcontinuetraining(&trainer, &net, _state))
{
}
}
if( c==1 )
{
mlptrainnetwork(&trainer, &net, nneedrest, &rep, _state);
}
/*
* Check weights
*/
mlpproperties(&net, &nin, &nout, &wcount, _state);
for(c=0; c<=wcount-1; c++)
{
if( ae_fp_neq(net.weights.ptr.p_double[c],(double)(0)) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function tests that increasing numbers of restarts lead to statistical
improvement quality of solution.
Neural network created by Create1(10 neurons) and trained by MLPTrainLBFGS.
TEST's DISCRIPTION:
Net0 - network trained with one restart (denoted as R1)
Net1 - network trained with more than one restart (denoted as Rn)
We must refuse hypothesis that R1 equivalent to Rn.
Here Mean = N/2, Sigma = Sqrt(N)/2.
_
| 0 - R1 worse than Rn;
ri = |
|_1 - Rn same or worse then R1.
If Sum(ri)1 restarts.
*/
mlpproperties(&net1, &nin, &nout, &wcount1, _state);
e1 = ae_v_dotproduct(&net1.weights.ptr.p_double[0], 1, &net1.weights.ptr.p_double[0], 1, ae_v_len(0,wcount1-1));
e1 = mlperrorn(&net1, &xy, n, _state)+0.5*vdecay*e1;
if( ae_fp_less_eq(e0,e1) )
{
avval = avval+1;
}
}
if( ae_fp_less(mean-numsigma,avval) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
The function test function MLPKFoldCV.
*************************************************************************/
static ae_bool testmlptrainunit_testmlpcverror(ae_state *_state)
{
ae_frame _frame_block;
multilayerperceptron net;
mlptrainer trainer;
mlpreport rep;
mlpreport cvrep;
ae_int_t nin;
ae_int_t nout;
ae_int_t nneurons;
ae_int_t rowsz;
double decay;
double wstep;
ae_int_t maxits;
ae_int_t foldscount;
ae_int_t nneedrest;
sparsematrix sptrainingset;
ae_matrix trainingset;
ae_matrix testset;
ae_int_t npoints;
ae_int_t ntstpoints;
double mean;
double numsigma;
double diffms;
double tstrelclserror;
double tstavgce;
double tstrmserror;
double tstavgerror;
double tstavgrelerror;
ae_int_t r0;
ae_int_t r1;
ae_int_t r2;
ae_int_t r3;
ae_int_t r4;
ae_int_t ntest;
ae_int_t xp;
ae_int_t nxp;
ae_bool isregr;
ae_int_t issparse;
ae_int_t i;
ae_int_t j;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&net, 0, sizeof(net));
memset(&trainer, 0, sizeof(trainer));
memset(&rep, 0, sizeof(rep));
memset(&cvrep, 0, sizeof(cvrep));
memset(&sptrainingset, 0, sizeof(sptrainingset));
memset(&trainingset, 0, sizeof(trainingset));
memset(&testset, 0, sizeof(testset));
_multilayerperceptron_init(&net, _state, ae_true);
_mlptrainer_init(&trainer, _state, ae_true);
_mlpreport_init(&rep, _state, ae_true);
_mlpreport_init(&cvrep, _state, ae_true);
_sparsematrix_init(&sptrainingset, _state, ae_true);
ae_matrix_init(&trainingset, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&testset, 0, 0, DT_REAL, _state, ae_true);
decay = 1.0E-6;
wstep = 0.0;
foldscount = 5;
nneedrest = 1;
ntest = ae_randominteger(4, _state);
nxp = 1000;
maxits = 50;
nin = 1;
nout = 1;
npoints = 5;
ntstpoints = 100;
isregr = ae_true;
nneurons = 3;
if( ntest==1 )
{
nxp = 1000;
maxits = 50;
nin = 1;
nout = 10;
npoints = 5;
ntstpoints = 100;
isregr = ae_true;
}
if( ntest==2 )
{
nxp = 1000;
maxits = 50;
nin = 10;
nout = 1;
npoints = 20;
ntstpoints = 100;
isregr = ae_true;
}
if( ntest==3 )
{
nxp = 2000;
maxits = 10;
nin = 1;
nneurons = 3;
nout = 3;
npoints = 10;
ntstpoints = 100;
isregr = ae_false;
}
mean = nxp/2.0;
numsigma = 5.0*ae_sqrt((double)(nxp), _state)/2.0;
diffms = mean-numsigma;
issparse = ae_randominteger(2, _state);
if( isregr )
{
mlpcreate0(nin, nout, &net, _state);
mlpcreatetrainer(nin, nout, &trainer, _state);
}
else
{
mlpcreatec1(nin, nneurons, nout, &net, _state);
mlpcreatetrainercls(nin, nout, &trainer, _state);
}
mlpsetcond(&trainer, wstep, maxits, _state);
mlpsetdecay(&trainer, decay, _state);
if( isregr )
{
rowsz = nin+nout;
}
else
{
rowsz = nin+1;
}
r0 = 0;
r1 = 0;
r2 = 0;
r3 = 0;
r4 = 0;
for(xp=1; xp<=nxp; xp++)
{
/*
* Dense matrix
*/
if( issparse==0 )
{
rmatrixsetlengthatleast(&trainingset, npoints, rowsz, _state);
/*
* Create training set
*/
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nin-1; j++)
{
trainingset.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
if( isregr )
{
for(i=0; i<=npoints-1; i++)
{
for(j=nin; j<=rowsz-1; j++)
{
trainingset.ptr.pp_double[i][j] = 2*ae_randomreal(_state)+1;
}
}
}
else
{
for(i=0; i<=npoints-1; i++)
{
for(j=nin; j<=rowsz-1; j++)
{
trainingset.ptr.pp_double[i][j] = (double)(ae_randominteger(nout, _state));
}
}
}
mlpsetdataset(&trainer, &trainingset, npoints, _state);
}
/*
* Sparse matrix
*/
if( issparse==1 )
{
sparsecreate(npoints, rowsz, npoints*rowsz, &sptrainingset, _state);
/*
* Create training set
*/
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nin-1; j++)
{
sparseset(&sptrainingset, i, j, 2*ae_randomreal(_state)-1, _state);
}
}
if( isregr )
{
for(i=0; i<=npoints-1; i++)
{
for(j=nin; j<=rowsz-1; j++)
{
sparseset(&sptrainingset, i, j, 2*ae_randomreal(_state)+1, _state);
}
}
}
else
{
for(i=0; i<=npoints-1; i++)
{
for(j=nin; j<=rowsz-1; j++)
{
sparseset(&sptrainingset, i, j, (double)(ae_randominteger(nout, _state)), _state);
}
}
}
sparseconverttocrs(&sptrainingset, _state);
mlpsetsparsedataset(&trainer, &sptrainingset, npoints, _state);
}
rmatrixsetlengthatleast(&testset, ntstpoints, rowsz, _state);
/*
* Create test set
*/
for(i=0; i<=ntstpoints-1; i++)
{
for(j=0; j<=nin-1; j++)
{
testset.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
if( isregr )
{
for(i=0; i<=ntstpoints-1; i++)
{
for(j=nin; j<=rowsz-1; j++)
{
testset.ptr.pp_double[i][j] = 2*ae_randomreal(_state)+1;
}
}
}
else
{
for(i=0; i<=ntstpoints-1; i++)
{
for(j=nin; j<=rowsz-1; j++)
{
testset.ptr.pp_double[i][j] = (double)(ae_randominteger(nout, _state));
}
}
}
mlptrainnetwork(&trainer, &net, nneedrest, &rep, _state);
tstrelclserror = (double)(0);
tstavgce = (double)(0);
tstrmserror = (double)(0);
tstavgerror = (double)(0);
tstavgrelerror = (double)(0);
if( !isregr )
{
tstrelclserror = mlprelclserror(&net, &testset, ntstpoints, _state);
tstavgce = mlpavgce(&net, &testset, ntstpoints, _state);
}
tstrmserror = mlprmserror(&net, &testset, ntstpoints, _state);
tstavgerror = mlpavgerror(&net, &testset, ntstpoints, _state);
tstavgrelerror = mlpavgrelerror(&net, &testset, ntstpoints, _state);
/*
* Cross-validation
*/
mlpkfoldcv(&trainer, &net, nneedrest, foldscount, &cvrep, _state);
if( !isregr )
{
if( ae_fp_less(ae_fabs(tstrelclserror-rep.relclserror, _state),ae_fabs(tstrelclserror-cvrep.relclserror, _state)) )
{
r0 = r0+1;
}
if( ae_fp_less(ae_fabs(tstavgce-rep.avgce, _state),ae_fabs(tstavgce-cvrep.avgce, _state)) )
{
r1 = r1+1;
}
}
if( ae_fp_less(ae_fabs(tstrmserror-rep.rmserror, _state),ae_fabs(tstrmserror-cvrep.rmserror, _state)) )
{
r2 = r2+1;
}
if( ae_fp_less(ae_fabs(tstavgerror-rep.avgerror, _state),ae_fabs(tstavgerror-cvrep.avgerror, _state)) )
{
r3 = r3+1;
}
if( ae_fp_less(ae_fabs(tstavgrelerror-rep.avgrelerror, _state),ae_fabs(tstavgrelerror-cvrep.avgrelerror, _state)) )
{
r4 = r4+1;
}
}
if( !isregr )
{
if( ae_fp_less_eq(diffms,(double)(r0))||ae_fp_less_eq(diffms,(double)(r1)) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
if( (ae_fp_less_eq(diffms,(double)(r2))||ae_fp_less_eq(diffms,(double)(r3)))||ae_fp_less_eq(diffms,(double)(r4)) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
/*
* Test FoldCV when no dataset was specified with
* MLPSetDataset/SetSparseDataset(), or subset with
* only one point was given.
*
* NPoints values:
* * -1 - don't set dataset with using MLPSetDataset..;
* * 0 - zero dataset;
* * 1 - dataset with one point.
*/
for(npoints=-1; npoints<=1; npoints++)
{
if( isregr )
{
mlpcreatetrainer(nin, nout, &trainer, _state);
}
else
{
mlpcreatetrainercls(nin, nout, &trainer, _state);
}
if( npoints>-1 )
{
if( issparse==0 )
{
mlpsetdataset(&trainer, &trainingset, npoints, _state);
}
if( issparse==1 )
{
mlpsetsparsedataset(&trainer, &sptrainingset, npoints, _state);
}
}
mlpkfoldcv(&trainer, &net, nneedrest, foldscount, &cvrep, _state);
if( ((((((ae_fp_neq(cvrep.relclserror,(double)(0))||ae_fp_neq(cvrep.avgce,(double)(0)))||ae_fp_neq(cvrep.rmserror,(double)(0)))||ae_fp_neq(cvrep.avgerror,(double)(0)))||ae_fp_neq(cvrep.avgrelerror,(double)(0)))||cvrep.ngrad!=0)||cvrep.nhess!=0)||cvrep.ncholesky!=0 )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
The function tests functions for training ensembles: MLPEBaggingLM,
MLPEBaggingLBFGS.
*************************************************************************/
static ae_bool testmlptrainunit_testmlptrainens(ae_state *_state)
{
ae_frame _frame_block;
mlpensemble ensemble;
mlpreport rep;
mlpcvreport oobrep;
ae_int_t info;
ae_matrix xy;
ae_int_t nin;
ae_int_t nout;
ae_int_t npoints;
ae_int_t nhid;
ae_int_t algtype;
ae_int_t tasktype;
ae_int_t pass;
double e;
ae_int_t nless;
ae_int_t nall;
ae_int_t nclasses;
ae_int_t i;
ae_int_t j;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&ensemble, 0, sizeof(ensemble));
memset(&rep, 0, sizeof(rep));
memset(&oobrep, 0, sizeof(oobrep));
memset(&xy, 0, sizeof(xy));
_mlpensemble_init(&ensemble, _state, ae_true);
_mlpreport_init(&rep, _state, ae_true);
_mlpcvreport_init(&oobrep, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
result = ae_false;
/*
* network training must reduce error
* test on random regression task
*/
nin = 3;
nout = 2;
nhid = 5;
npoints = 100;
nless = 0;
nall = 0;
for(pass=1; pass<=10; pass++)
{
for(algtype=0; algtype<=1; algtype++)
{
for(tasktype=0; tasktype<=1; tasktype++)
{
if( tasktype==0 )
{
ae_matrix_set_length(&xy, npoints, nin+nout, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nin+nout-1; j++)
{
xy.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
mlpecreate1(nin, nhid, nout, 1+ae_randominteger(3, _state), &ensemble, _state);
}
else
{
ae_matrix_set_length(&xy, npoints, nin+1, _state);
nclasses = 2+ae_randominteger(2, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nin-1; j++)
{
xy.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
xy.ptr.pp_double[i][nin] = (double)(ae_randominteger(nclasses, _state));
}
mlpecreatec1(nin, nhid, nclasses, 1+ae_randominteger(3, _state), &ensemble, _state);
}
e = mlpermserror(&ensemble, &xy, npoints, _state);
if( algtype==0 )
{
mlpebagginglm(&ensemble, &xy, npoints, 0.001, 1, &info, &rep, &oobrep, _state);
}
else
{
mlpebagginglbfgs(&ensemble, &xy, npoints, 0.001, 1, 0.01, 0, &info, &rep, &oobrep, _state);
}
if( info<0 )
{
result = ae_true;
}
else
{
if( ae_fp_less(mlpermserror(&ensemble, &xy, npoints, _state),e) )
{
nless = nless+1;
}
}
nall = nall+1;
}
}
}
result = result||ae_fp_greater((double)(nall-nless),0.3*nall);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Testing for functions MLPETrainES and MLPTrainEnsembleES on regression
problems. Returns TRUE for errors, FALSE for success.
*************************************************************************/
static ae_bool testmlptrainunit_testmlptrainensregr(ae_state *_state)
{
ae_frame _frame_block;
mlptrainer trainer;
mlpensemble netens;
mlpreport rep;
modelerrors repx;
ae_int_t info;
sparsematrix xytrainsp;
ae_matrix xytrain;
ae_matrix xytest;
ae_int_t nin;
ae_int_t nout;
ae_int_t nneurons;
ae_vector x;
ae_vector y;
double decay;
double wstep;
ae_int_t maxits;
ae_int_t nneedrest;
ae_int_t enssize;
double mnval;
double mxval;
ae_int_t ntrain;
ae_int_t ntest;
double avgerr;
ae_int_t issparse;
ae_int_t withtrainer;
double eps;
ae_int_t xp;
ae_int_t i;
ae_int_t j;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&trainer, 0, sizeof(trainer));
memset(&netens, 0, sizeof(netens));
memset(&rep, 0, sizeof(rep));
memset(&repx, 0, sizeof(repx));
memset(&xytrainsp, 0, sizeof(xytrainsp));
memset(&xytrain, 0, sizeof(xytrain));
memset(&xytest, 0, sizeof(xytest));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
_mlptrainer_init(&trainer, _state, ae_true);
_mlpensemble_init(&netens, _state, ae_true);
_mlpreport_init(&rep, _state, ae_true);
_modelerrors_init(&repx, _state, ae_true);
_sparsematrix_init(&xytrainsp, _state, ae_true);
ae_matrix_init(&xytrain, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xytest, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
result = ae_false;
/*
* This test checks ability to train ensemble on simple regression
* problem "f(x0,x1,x2,...) = x0 + x1 + x2 + ...".
*/
eps = 5.0E-2;
mnval = (double)(-1);
mxval = (double)(1);
ntrain = 40;
ntest = 20;
decay = 1.0E-3;
wstep = 1.0E-3;
maxits = 20;
nneedrest = 1;
nneurons = 20;
nout = 1;
enssize = 100;
for(xp=1; xp<=2; xp++)
{
nin = ae_randominteger(3, _state)+1;
rvectorsetlengthatleast(&x, nin, _state);
mlpcreatetrainer(nin, nout, &trainer, _state);
mlpsetdecay(&trainer, decay, _state);
mlpsetcond(&trainer, wstep, maxits, _state);
rmatrixsetlengthatleast(&xytrain, ntrain, nin+nout, _state);
rmatrixsetlengthatleast(&xytest, ntest, nin+nout, _state);
withtrainer = ae_randominteger(2, _state);
issparse = 0;
if( withtrainer==0 )
{
issparse = 0;
}
if( withtrainer==1 )
{
issparse = ae_randominteger(2, _state);
}
/*
* Training set
*/
for(i=0; i<=ntrain-1; i++)
{
for(j=0; j<=nin-1; j++)
{
xytrain.ptr.pp_double[i][j] = (mxval-mnval)*ae_randomreal(_state)+mnval;
}
xytrain.ptr.pp_double[i][nin] = (double)(0);
for(j=0; j<=nin-1; j++)
{
xytrain.ptr.pp_double[i][nin] = xytrain.ptr.pp_double[i][nin]+xytrain.ptr.pp_double[i][j];
}
}
if( withtrainer==1 )
{
/*
* Dense matrix
*/
if( issparse==0 )
{
mlpsetdataset(&trainer, &xytrain, ntrain, _state);
}
/*
* Sparse matrix
*/
if( issparse==1 )
{
sparsecreate(ntrain, nin+nout, ntrain*(nin+nout), &xytrainsp, _state);
/*
* Just copy dense matrix to sparse matrix(using SparseGet() is too expensive).
*/
for(i=0; i<=ntrain-1; i++)
{
for(j=0; j<=nin+nout-1; j++)
{
sparseset(&xytrainsp, i, j, xytrain.ptr.pp_double[i][j], _state);
}
}
sparseconverttocrs(&xytrainsp, _state);
mlpsetsparsedataset(&trainer, &xytrainsp, ntrain, _state);
}
}
/*
* Test set
*/
for(i=0; i<=ntest-1; i++)
{
for(j=0; j<=nin-1; j++)
{
xytest.ptr.pp_double[i][j] = (mxval-mnval)*ae_randomreal(_state)+mnval;
}
xytest.ptr.pp_double[i][nin] = (double)(0);
for(j=0; j<=nin-1; j++)
{
xytest.ptr.pp_double[i][nin] = xytest.ptr.pp_double[i][nin]+xytest.ptr.pp_double[i][j];
}
}
/*
* Create ensemble
*/
mlpecreate1(nin, nneurons, nout, enssize, &netens, _state);
/*
* Train ensembles:
* * without trainer;
*/
if( withtrainer==0 )
{
mlpetraines(&netens, &xytrain, ntrain, decay, nneedrest, &info, &rep, _state);
}
/*
* * with trainer.
*/
if( withtrainer==1 )
{
mlptrainensemblees(&trainer, &netens, nneedrest, &rep, _state);
}
/*
* Test that Rep contains correct error values
*/
mlpeallerrorsx(&netens, &xytrain, &xytrainsp, ntrain, 0, &netens.network.dummyidx, 0, ntrain, 0, &netens.network.buf, &repx, _state);
seterrorflagdiff(&result, rep.relclserror, repx.relclserror, 1.0E-4, 1.0E-2, _state);
seterrorflagdiff(&result, rep.avgce, repx.avgce, 1.0E-4, 1.0E-2, _state);
seterrorflagdiff(&result, rep.rmserror, repx.rmserror, 1.0E-4, 1.0E-2, _state);
seterrorflagdiff(&result, rep.avgerror, repx.avgerror, 1.0E-4, 1.0E-2, _state);
seterrorflagdiff(&result, rep.avgrelerror, repx.avgrelerror, 1.0E-4, 1.0E-2, _state);
/*
* Test that network fits data well. Calculate average error:
* * on training dataset;
* * on test dataset. (here we reduce the accuracy
* requirements - average error is compared with 2*Eps).
*/
avgerr = (double)(0);
for(i=0; i<=ntrain-1; i++)
{
if( issparse==0 )
{
ae_v_move(&x.ptr.p_double[0], 1, &xytrain.ptr.pp_double[i][0], 1, ae_v_len(0,nin-1));
}
if( issparse==1 )
{
sparsegetrow(&xytrainsp, i, &x, _state);
}
mlpeprocess(&netens, &x, &y, _state);
avgerr = avgerr+ae_fabs(y.ptr.p_double[0]-xytrain.ptr.pp_double[i][nin], _state);
}
avgerr = avgerr/ntrain;
ae_set_error_flag(&result, ae_fp_greater(avgerr,eps), __FILE__, __LINE__, "testmlptrainunit.ap:1799");
avgerr = (double)(0);
for(i=0; i<=ntest-1; i++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xytest.ptr.pp_double[i][0], 1, ae_v_len(0,nin-1));
mlpeprocess(&netens, &x, &y, _state);
avgerr = avgerr+ae_fabs(y.ptr.p_double[0]-xytest.ptr.pp_double[i][nin], _state);
}
avgerr = avgerr/ntest;
ae_set_error_flag(&result, ae_fp_greater(avgerr,2*eps), __FILE__, __LINE__, "testmlptrainunit.ap:1808");
}
/*
* Catch bug in implementation of MLPTrainEnsembleX:
* test ensemble training on empty dataset.
*
* Unfixed version should crash with violation of array
* bounds (at least in C#).
*/
nin = 2;
nout = 2;
nneurons = 3;
enssize = 3;
nneedrest = 2;
wstep = 0.001;
maxits = 2;
mlpcreatetrainer(nin, nout, &trainer, _state);
mlpsetcond(&trainer, wstep, maxits, _state);
mlpecreate1(nin, nneurons, nout, enssize, &netens, _state);
mlptrainensemblees(&trainer, &netens, nneedrest, &rep, _state);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Testing for functions MLPETrainES and MLPTrainEnsembleES on classification
problems.
*************************************************************************/
static ae_bool testmlptrainunit_testmlptrainenscls(ae_state *_state)
{
ae_frame _frame_block;
mlptrainer trainer;
mlpensemble netens;
mlpreport rep;
ae_int_t info;
sparsematrix xytrainsp;
ae_matrix xytrain;
ae_matrix xytest;
ae_int_t nin;
ae_int_t nout;
ae_vector x;
ae_vector y;
double decay;
double wstep;
ae_int_t maxits;
ae_int_t nneedrest;
ae_int_t enssize;
ae_int_t val;
ae_int_t ntrain;
ae_int_t ntest;
double avgerr;
double eps;
double delta;
ae_int_t issparse;
ae_int_t withtrainer;
ae_int_t xp;
ae_int_t nxp;
ae_int_t i;
ae_int_t j;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&trainer, 0, sizeof(trainer));
memset(&netens, 0, sizeof(netens));
memset(&rep, 0, sizeof(rep));
memset(&xytrainsp, 0, sizeof(xytrainsp));
memset(&xytrain, 0, sizeof(xytrain));
memset(&xytest, 0, sizeof(xytest));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
_mlptrainer_init(&trainer, _state, ae_true);
_mlpensemble_init(&netens, _state, ae_true);
_mlpreport_init(&rep, _state, ae_true);
_sparsematrix_init(&xytrainsp, _state, ae_true);
ae_matrix_init(&xytrain, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xytest, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
eps = 5.0E-2;
delta = 0.1;
ntrain = 90;
ntest = 90;
nin = 3;
nout = 3;
rvectorsetlengthatleast(&x, nin, _state);
rmatrixsetlengthatleast(&xytrain, ntrain, nin+1, _state);
rmatrixsetlengthatleast(&xytest, ntest, nin+1, _state);
decay = 1.0E-3;
wstep = 1.0E-3;
maxits = 100;
nneedrest = 1;
mlpcreatetrainercls(nin, nout, &trainer, _state);
mlpsetdecay(&trainer, decay, _state);
mlpsetcond(&trainer, wstep, maxits, _state);
nxp = 5;
for(xp=1; xp<=nxp; xp++)
{
enssize = ae_round(ae_pow((double)(10), (double)(ae_randominteger(2, _state)+1), _state), _state);
withtrainer = ae_randominteger(2, _state);
issparse = 0;
if( withtrainer==0 )
{
issparse = 0;
}
if( withtrainer==1 )
{
issparse = ae_randominteger(2, _state);
}
for(i=0; i<=ntrain-1; i++)
{
val = i%nin;
for(j=0; j<=nin-1; j++)
{
xytrain.ptr.pp_double[i][j] = delta*(ae_randomreal(_state)-1);
}
xytrain.ptr.pp_double[i][val] = xytrain.ptr.pp_double[i][val]+1;
xytrain.ptr.pp_double[i][nin] = (double)(val);
}
/*
* Set dense dataset in trainer
*/
if( issparse==0 )
{
mlpsetdataset(&trainer, &xytrain, ntrain, _state);
}
/*
* * Sparse dataset(create it with using dense dataset).
*/
if( issparse==1 )
{
sparsecreate(ntrain, nin+1, ntrain*(nin+1), &xytrainsp, _state);
for(i=0; i<=ntrain-1; i++)
{
for(j=0; j<=nin-1; j++)
{
sparseset(&xytrainsp, i, j, xytrain.ptr.pp_double[i][j], _state);
}
sparseset(&xytrainsp, i, nin, xytrain.ptr.pp_double[i][nin], _state);
}
sparseconverttocrs(&xytrainsp, _state);
/*
* Set sparse dataset in trainer
*/
mlpsetsparsedataset(&trainer, &xytrainsp, ntrain, _state);
}
/*
* Create test set
*/
for(i=0; i<=ntest-1; i++)
{
val = ae_randominteger(nin, _state);
for(j=0; j<=nin-1; j++)
{
xytest.ptr.pp_double[i][j] = delta*(ae_randomreal(_state)-1);
}
xytest.ptr.pp_double[i][val] = xytest.ptr.pp_double[i][val]+1;
xytest.ptr.pp_double[i][nin] = (double)(val);
}
/*
* Create ensemble
*/
mlpecreatec0(nin, nout, enssize, &netens, _state);
/*
* Train ensembles:
* * without trainer;
*/
if( withtrainer==0 )
{
mlpetraines(&netens, &xytrain, ntrain, decay, nneedrest, &info, &rep, _state);
}
/*
* * with trainer.
*/
if( withtrainer==1 )
{
mlptrainensemblees(&trainer, &netens, nneedrest, &rep, _state);
}
/*
* Calculate average error:
* * on training dataset;
*/
avgerr = (double)(0);
for(i=0; i<=ntrain-1; i++)
{
if( issparse==0 )
{
ae_v_move(&x.ptr.p_double[0], 1, &xytrain.ptr.pp_double[i][0], 1, ae_v_len(0,nin-1));
}
if( issparse==1 )
{
sparsegetrow(&xytrainsp, i, &x, _state);
}
mlpeprocess(&netens, &x, &y, _state);
for(j=0; j<=nout-1; j++)
{
if( ae_fp_neq((double)(j),xytrain.ptr.pp_double[i][nin]) )
{
avgerr = avgerr+y.ptr.p_double[j];
}
else
{
avgerr = avgerr+(1-y.ptr.p_double[j]);
}
}
}
avgerr = avgerr/(ntrain*nout);
if( ae_fp_greater(avgerr,eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
/*
* * on test dataset.
*/
avgerr = (double)(0);
for(i=0; i<=ntest-1; i++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xytest.ptr.pp_double[i][0], 1, ae_v_len(0,nin-1));
mlpeprocess(&netens, &x, &y, _state);
for(j=0; j<=nout-1; j++)
{
if( ae_fp_neq((double)(j),xytest.ptr.pp_double[i][nin]) )
{
avgerr = avgerr+y.ptr.p_double[j];
}
else
{
avgerr = avgerr+(1-y.ptr.p_double[j]);
}
}
}
avgerr = avgerr/(ntest*nout);
if( ae_fp_greater(avgerr,eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
static ae_bool testclusteringunit_basicahctests(ae_state *_state);
static ae_bool testclusteringunit_advancedahctests(ae_state *_state);
static void testclusteringunit_kmeanssimpletest1(ae_int_t nvars,
ae_int_t nc,
ae_int_t passcount,
ae_bool* converrors,
ae_bool* othererrors,
ae_bool* simpleerrors,
ae_state *_state);
static void testclusteringunit_kmeansspecialtests(ae_bool* othererrors,
ae_state *_state);
static void testclusteringunit_kmeansinfinitelooptest(ae_bool* othererrors,
ae_state *_state);
static void testclusteringunit_kmeansrestartstest(ae_bool* converrors,
ae_bool* restartserrors,
ae_state *_state);
static double testclusteringunit_rnormal(ae_state *_state);
static void testclusteringunit_rsphere(/* Real */ ae_matrix* xy,
ae_int_t n,
ae_int_t i,
ae_state *_state);
static double testclusteringunit_distfunc(/* Real */ ae_vector* x0,
/* Real */ ae_vector* x1,
ae_int_t d,
ae_int_t disttype,
ae_state *_state);
static ae_bool testclusteringunit_errorsinmerges(/* Real */ ae_matrix* d,
/* Real */ ae_matrix* xy,
ae_int_t npoints,
ae_int_t nf,
ahcreport* rep,
ae_int_t ahcalgo,
ae_state *_state);
static void testclusteringunit_kmeansreferenceupdatedistances(/* Real */ ae_matrix* xy,
ae_int_t npoints,
ae_int_t nvars,
/* Real */ ae_matrix* ct,
ae_int_t k,
/* Integer */ ae_vector* xyc,
/* Real */ ae_vector* xydist2,
ae_state *_state);
/*************************************************************************
Testing clustering
*************************************************************************/
ae_bool testclustering(ae_bool silent, ae_state *_state)
{
ae_bool waserrors;
ae_bool basicahcerrors;
ae_bool ahcerrors;
ae_bool kmeansconverrors;
ae_bool kmeanssimpleerrors;
ae_bool kmeansothererrors;
ae_bool kmeansrestartserrors;
ae_int_t passcount;
ae_int_t nf;
ae_int_t nc;
ae_bool result;
/*
* AHC tests
*/
basicahcerrors = testclusteringunit_basicahctests(_state);
ahcerrors = testclusteringunit_advancedahctests(_state);
/*
* k-means tests
*/
passcount = 10;
kmeansconverrors = ae_false;
kmeansothererrors = ae_false;
kmeanssimpleerrors = ae_false;
kmeansrestartserrors = ae_false;
testclusteringunit_kmeansspecialtests(&kmeansothererrors, _state);
testclusteringunit_kmeansinfinitelooptest(&kmeansothererrors, _state);
testclusteringunit_kmeansrestartstest(&kmeansconverrors, &kmeansrestartserrors, _state);
for(nf=1; nf<=5; nf++)
{
for(nc=1; nc<=5; nc++)
{
testclusteringunit_kmeanssimpletest1(nf, nc, passcount, &kmeansconverrors, &kmeansothererrors, &kmeanssimpleerrors, _state);
}
}
/*
* Results
*/
waserrors = ae_false;
waserrors = waserrors||(basicahcerrors||ahcerrors);
waserrors = waserrors||(((kmeansconverrors||kmeansothererrors)||kmeanssimpleerrors)||kmeansrestartserrors);
if( !silent )
{
printf("TESTING CLUSTERING\n");
printf("AHC: \n");
printf("* BASIC TESTS ");
if( !basicahcerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* GENERAL TESTS ");
if( !ahcerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("K-MEANS: \n");
printf("* CONVERGENCE ");
if( !kmeansconverrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* SIMPLE TASKS ");
if( !kmeanssimpleerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* OTHER PROPERTIES ");
if( !kmeansothererrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* RESTARTS PROPERTIES ");
if( !kmeansrestartserrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
return result;
}
/*************************************************************************
Basic agglomerative hierarchical clustering tests:
returns True on failure, False on success.
Basic tests study algorithm behavior on simple, hand-made datasets with
small number of points (1..10).
*************************************************************************/
static ae_bool testclusteringunit_basicahctests(ae_state *_state)
{
ae_frame _frame_block;
clusterizerstate s;
ahcreport rep;
ae_matrix xy;
ae_matrix d;
ae_matrix c;
ae_bool berr;
ae_int_t ahcalgo;
ae_int_t i;
ae_int_t j;
ae_int_t npoints;
ae_int_t k;
ae_vector cidx;
ae_vector cz;
ae_vector cidx2;
ae_vector cz2;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&xy, 0, sizeof(xy));
memset(&d, 0, sizeof(d));
memset(&c, 0, sizeof(c));
memset(&cidx, 0, sizeof(cidx));
memset(&cz, 0, sizeof(cz));
memset(&cidx2, 0, sizeof(cidx2));
memset(&cz2, 0, sizeof(cz2));
_clusterizerstate_init(&s, _state, ae_true);
_ahcreport_init(&rep, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&d, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&cidx, 0, DT_INT, _state, ae_true);
ae_vector_init(&cz, 0, DT_INT, _state, ae_true);
ae_vector_init(&cidx2, 0, DT_INT, _state, ae_true);
ae_vector_init(&cz2, 0, DT_INT, _state, ae_true);
result = ae_true;
/*
* Test on empty problem
*/
clusterizercreate(&s, _state);
clusterizerrunahc(&s, &rep, _state);
if( rep.npoints!=0 )
{
ae_frame_leave(_state);
return result;
}
/*
* Test on problem with one point
*/
ae_matrix_set_length(&xy, 1, 2, _state);
xy.ptr.pp_double[0][0] = ae_randomreal(_state);
xy.ptr.pp_double[0][1] = ae_randomreal(_state);
clusterizercreate(&s, _state);
clusterizersetpoints(&s, &xy, 1, 2, 0, _state);
clusterizerrunahc(&s, &rep, _state);
if( rep.npoints!=1 )
{
ae_frame_leave(_state);
return result;
}
/*
* Test on problem with two points
*/
ae_matrix_set_length(&xy, 2, 2, _state);
xy.ptr.pp_double[0][0] = ae_randomreal(_state);
xy.ptr.pp_double[0][1] = ae_randomreal(_state);
xy.ptr.pp_double[1][0] = ae_randomreal(_state);
xy.ptr.pp_double[1][1] = ae_randomreal(_state);
clusterizercreate(&s, _state);
clusterizersetpoints(&s, &xy, 2, 2, 0, _state);
clusterizerrunahc(&s, &rep, _state);
if( (rep.npoints!=2||rep.z.rows!=1)||rep.z.cols!=2 )
{
ae_frame_leave(_state);
return result;
}
if( rep.z.ptr.pp_int[0][0]!=0||rep.z.ptr.pp_int[0][1]!=1 )
{
ae_frame_leave(_state);
return result;
}
/*
* Test on specially designed problem which should have
* following dendrogram:
*
* ------
* | |
* ---- ----
* | | | |
* 0 1 2 3
*
* ...with first merge performed on 0 and 1, second merge
* performed on 2 and 3. Complete linkage is used.
*
* Additionally we test ClusterizerSeparatedByDist() on this
* problem for different distances. Test is performed by
* comparing function result with ClusterizerGetKClusters()
* for known K.
*/
ae_matrix_set_length(&xy, 4, 1, _state);
xy.ptr.pp_double[0][0] = 0.0;
xy.ptr.pp_double[1][0] = 1.0;
xy.ptr.pp_double[2][0] = 3.0;
xy.ptr.pp_double[3][0] = 4.1;
clusterizercreate(&s, _state);
clusterizersetpoints(&s, &xy, 4, 1, 0, _state);
clusterizersetahcalgo(&s, 0, _state);
clusterizerrunahc(&s, &rep, _state);
if( (((rep.npoints!=4||rep.z.rows!=3)||rep.z.cols!=2)||rep.pz.rows!=3)||rep.pz.cols!=2 )
{
ae_frame_leave(_state);
return result;
}
berr = ae_false;
berr = (berr||rep.z.ptr.pp_int[0][0]!=0)||rep.z.ptr.pp_int[0][1]!=1;
berr = (berr||rep.z.ptr.pp_int[1][0]!=2)||rep.z.ptr.pp_int[1][1]!=3;
berr = (berr||rep.z.ptr.pp_int[2][0]!=4)||rep.z.ptr.pp_int[2][1]!=5;
berr = (((berr||rep.p.ptr.p_int[0]!=0)||rep.p.ptr.p_int[1]!=1)||rep.p.ptr.p_int[2]!=2)||rep.p.ptr.p_int[3]!=3;
berr = (berr||rep.pz.ptr.pp_int[0][0]!=0)||rep.pz.ptr.pp_int[0][1]!=1;
berr = (berr||rep.pz.ptr.pp_int[1][0]!=2)||rep.pz.ptr.pp_int[1][1]!=3;
berr = (berr||rep.pz.ptr.pp_int[2][0]!=4)||rep.pz.ptr.pp_int[2][1]!=5;
berr = (((berr||rep.pm.ptr.pp_int[0][0]!=0)||rep.pm.ptr.pp_int[0][1]!=0)||rep.pm.ptr.pp_int[0][2]!=1)||rep.pm.ptr.pp_int[0][3]!=1;
berr = (((berr||rep.pm.ptr.pp_int[1][0]!=2)||rep.pm.ptr.pp_int[1][1]!=2)||rep.pm.ptr.pp_int[1][2]!=3)||rep.pm.ptr.pp_int[1][3]!=3;
berr = (((berr||rep.pm.ptr.pp_int[2][0]!=0)||rep.pm.ptr.pp_int[2][1]!=1)||rep.pm.ptr.pp_int[2][2]!=2)||rep.pm.ptr.pp_int[2][3]!=3;
if( berr )
{
ae_frame_leave(_state);
return result;
}
clusterizerseparatedbydist(&rep, 0.5, &k, &cidx, &cz, _state);
clusterizergetkclusters(&rep, 4, &cidx2, &cz2, _state);
if( k!=4 )
{
ae_frame_leave(_state);
return result;
}
if( ((cidx.ptr.p_int[0]!=cidx2.ptr.p_int[0]||cidx.ptr.p_int[1]!=cidx2.ptr.p_int[1])||cidx.ptr.p_int[2]!=cidx2.ptr.p_int[2])||cidx.ptr.p_int[3]!=cidx2.ptr.p_int[3] )
{
ae_frame_leave(_state);
return result;
}
if( ((cz.ptr.p_int[0]!=cz2.ptr.p_int[0]||cz.ptr.p_int[1]!=cz2.ptr.p_int[1])||cz.ptr.p_int[2]!=cz2.ptr.p_int[2])||cz.ptr.p_int[3]!=cz2.ptr.p_int[3] )
{
ae_frame_leave(_state);
return result;
}
clusterizerseparatedbydist(&rep, 1.05, &k, &cidx, &cz, _state);
clusterizergetkclusters(&rep, 3, &cidx2, &cz2, _state);
if( k!=3 )
{
ae_frame_leave(_state);
return result;
}
if( ((cidx.ptr.p_int[0]!=cidx2.ptr.p_int[0]||cidx.ptr.p_int[1]!=cidx2.ptr.p_int[1])||cidx.ptr.p_int[2]!=cidx2.ptr.p_int[2])||cidx.ptr.p_int[3]!=cidx2.ptr.p_int[3] )
{
ae_frame_leave(_state);
return result;
}
if( (cz.ptr.p_int[0]!=cz2.ptr.p_int[0]||cz.ptr.p_int[1]!=cz2.ptr.p_int[1])||cz.ptr.p_int[2]!=cz2.ptr.p_int[2] )
{
ae_frame_leave(_state);
return result;
}
clusterizerseparatedbydist(&rep, 1.15, &k, &cidx, &cz, _state);
clusterizergetkclusters(&rep, 2, &cidx2, &cz2, _state);
if( k!=2 )
{
ae_frame_leave(_state);
return result;
}
if( ((cidx.ptr.p_int[0]!=cidx2.ptr.p_int[0]||cidx.ptr.p_int[1]!=cidx2.ptr.p_int[1])||cidx.ptr.p_int[2]!=cidx2.ptr.p_int[2])||cidx.ptr.p_int[3]!=cidx2.ptr.p_int[3] )
{
ae_frame_leave(_state);
return result;
}
if( cz.ptr.p_int[0]!=cz2.ptr.p_int[0]||cz.ptr.p_int[1]!=cz2.ptr.p_int[1] )
{
ae_frame_leave(_state);
return result;
}
/*
* Test on specially designed problem with Pearson distance
* which should have following dendrogram:
*
* ------
* | |
* ---- ----
* | | | |
* 0 1 2 3
*
* This problem is used to test ClusterizerSeparatedByDist().
* The test is performed by comparing function result with
* ClusterizerGetKClusters() for known K.
*
* NOTE:
* * corr(a0,a1) = 0.866
* * corr(a2,a3) = 0.990
* * corr(a0/a1, a2/a3)<=0.5
*/
ae_matrix_set_length(&xy, 4, 3, _state);
xy.ptr.pp_double[0][0] = 0.3;
xy.ptr.pp_double[0][1] = 0.5;
xy.ptr.pp_double[0][2] = 0.3;
xy.ptr.pp_double[1][0] = 0.3;
xy.ptr.pp_double[1][1] = 0.5;
xy.ptr.pp_double[1][2] = 0.4;
xy.ptr.pp_double[2][0] = 0.1;
xy.ptr.pp_double[2][1] = 0.5;
xy.ptr.pp_double[2][2] = 0.9;
xy.ptr.pp_double[3][0] = 0.1;
xy.ptr.pp_double[3][1] = 0.4;
xy.ptr.pp_double[3][2] = 0.9;
clusterizercreate(&s, _state);
clusterizersetpoints(&s, &xy, 4, 3, 10, _state);
clusterizersetahcalgo(&s, 1, _state);
clusterizerrunahc(&s, &rep, _state);
clusterizerseparatedbycorr(&rep, 0.999, &k, &cidx, &cz, _state);
clusterizergetkclusters(&rep, 4, &cidx2, &cz2, _state);
if( k!=4 )
{
ae_frame_leave(_state);
return result;
}
if( ((cidx.ptr.p_int[0]!=cidx2.ptr.p_int[0]||cidx.ptr.p_int[1]!=cidx2.ptr.p_int[1])||cidx.ptr.p_int[2]!=cidx2.ptr.p_int[2])||cidx.ptr.p_int[3]!=cidx2.ptr.p_int[3] )
{
ae_frame_leave(_state);
return result;
}
if( ((cz.ptr.p_int[0]!=cz2.ptr.p_int[0]||cz.ptr.p_int[1]!=cz2.ptr.p_int[1])||cz.ptr.p_int[2]!=cz2.ptr.p_int[2])||cz.ptr.p_int[3]!=cz2.ptr.p_int[3] )
{
ae_frame_leave(_state);
return result;
}
clusterizerseparatedbycorr(&rep, 0.900, &k, &cidx, &cz, _state);
clusterizergetkclusters(&rep, 3, &cidx2, &cz2, _state);
if( k!=3 )
{
ae_frame_leave(_state);
return result;
}
if( ((cidx.ptr.p_int[0]!=cidx2.ptr.p_int[0]||cidx.ptr.p_int[1]!=cidx2.ptr.p_int[1])||cidx.ptr.p_int[2]!=cidx2.ptr.p_int[2])||cidx.ptr.p_int[3]!=cidx2.ptr.p_int[3] )
{
ae_frame_leave(_state);
return result;
}
if( (cz.ptr.p_int[0]!=cz2.ptr.p_int[0]||cz.ptr.p_int[1]!=cz2.ptr.p_int[1])||cz.ptr.p_int[2]!=cz2.ptr.p_int[2] )
{
ae_frame_leave(_state);
return result;
}
clusterizerseparatedbycorr(&rep, 0.600, &k, &cidx, &cz, _state);
clusterizergetkclusters(&rep, 2, &cidx2, &cz2, _state);
if( k!=2 )
{
ae_frame_leave(_state);
return result;
}
if( ((cidx.ptr.p_int[0]!=cidx2.ptr.p_int[0]||cidx.ptr.p_int[1]!=cidx2.ptr.p_int[1])||cidx.ptr.p_int[2]!=cidx2.ptr.p_int[2])||cidx.ptr.p_int[3]!=cidx2.ptr.p_int[3] )
{
ae_frame_leave(_state);
return result;
}
if( cz.ptr.p_int[0]!=cz2.ptr.p_int[0]||cz.ptr.p_int[1]!=cz2.ptr.p_int[1] )
{
ae_frame_leave(_state);
return result;
}
/*
* Single linkage vs. complete linkage
*/
ae_matrix_set_length(&xy, 6, 1, _state);
xy.ptr.pp_double[0][0] = 0.0;
xy.ptr.pp_double[1][0] = 1.0;
xy.ptr.pp_double[2][0] = 2.1;
xy.ptr.pp_double[3][0] = 3.3;
xy.ptr.pp_double[4][0] = 6.0;
xy.ptr.pp_double[5][0] = 4.6;
clusterizercreate(&s, _state);
clusterizersetpoints(&s, &xy, 6, 1, 0, _state);
clusterizersetahcalgo(&s, 0, _state);
clusterizerrunahc(&s, &rep, _state);
if( rep.npoints!=6||rep.p.cnt!=6 )
{
ae_frame_leave(_state);
return result;
}
if( ((rep.z.rows!=5||rep.z.cols!=2)||rep.pz.rows!=5)||rep.pz.cols!=2 )
{
ae_frame_leave(_state);
return result;
}
berr = ae_false;
berr = berr||rep.p.ptr.p_int[0]!=2;
berr = berr||rep.p.ptr.p_int[1]!=3;
berr = berr||rep.p.ptr.p_int[2]!=4;
berr = berr||rep.p.ptr.p_int[3]!=5;
berr = berr||rep.p.ptr.p_int[4]!=0;
berr = berr||rep.p.ptr.p_int[5]!=1;
berr = (berr||rep.z.ptr.pp_int[0][0]!=0)||rep.z.ptr.pp_int[0][1]!=1;
berr = (berr||rep.z.ptr.pp_int[1][0]!=2)||rep.z.ptr.pp_int[1][1]!=3;
berr = (berr||rep.z.ptr.pp_int[2][0]!=4)||rep.z.ptr.pp_int[2][1]!=5;
berr = (berr||rep.z.ptr.pp_int[3][0]!=6)||rep.z.ptr.pp_int[3][1]!=7;
berr = (berr||rep.z.ptr.pp_int[4][0]!=8)||rep.z.ptr.pp_int[4][1]!=9;
berr = (berr||rep.pz.ptr.pp_int[0][0]!=2)||rep.pz.ptr.pp_int[0][1]!=3;
berr = (berr||rep.pz.ptr.pp_int[1][0]!=4)||rep.pz.ptr.pp_int[1][1]!=5;
berr = (berr||rep.pz.ptr.pp_int[2][0]!=0)||rep.pz.ptr.pp_int[2][1]!=1;
berr = (berr||rep.pz.ptr.pp_int[3][0]!=6)||rep.pz.ptr.pp_int[3][1]!=7;
berr = (berr||rep.pz.ptr.pp_int[4][0]!=8)||rep.pz.ptr.pp_int[4][1]!=9;
if( berr )
{
ae_frame_leave(_state);
return result;
}
clusterizersetahcalgo(&s, 1, _state);
clusterizerrunahc(&s, &rep, _state);
if( (rep.npoints!=6||rep.z.rows!=5)||rep.z.cols!=2 )
{
ae_frame_leave(_state);
return result;
}
berr = ae_false;
berr = (berr||rep.z.ptr.pp_int[0][0]!=0)||rep.z.ptr.pp_int[0][1]!=1;
berr = (berr||rep.z.ptr.pp_int[1][0]!=2)||rep.z.ptr.pp_int[1][1]!=6;
berr = (berr||rep.z.ptr.pp_int[2][0]!=3)||rep.z.ptr.pp_int[2][1]!=7;
berr = (berr||rep.z.ptr.pp_int[3][0]!=5)||rep.z.ptr.pp_int[3][1]!=8;
berr = (berr||rep.z.ptr.pp_int[4][0]!=4)||rep.z.ptr.pp_int[4][1]!=9;
if( berr )
{
ae_frame_leave(_state);
return result;
}
/*
* Test which differentiates complete linkage and average linkage from
* single linkage:
* * we have cluster C0={(-0.5), (0)},
* cluster C1={(19.0), (20.0), (21.0), (22.0), (23.0)},
* and point P between them - (10.0)
* * we try three different strategies - single linkage, complete
* linkage, average linkage.
* * any strategy will merge C0 first, then merge points of C1,
* and then merge P with C0 or C1 (depending on linkage type)
* * we test that:
* a) C0 is merged first
* b) after 5 merges (including merge of C0), P is merged with C0 or C1
* c) P is merged with C1 when we have single linkage, with C0 otherwise
*/
ae_matrix_set_length(&xy, 8, 1, _state);
xy.ptr.pp_double[0][0] = -0.5;
xy.ptr.pp_double[1][0] = 0.0;
xy.ptr.pp_double[2][0] = 10.0;
xy.ptr.pp_double[3][0] = 19.0;
xy.ptr.pp_double[4][0] = 20.0;
xy.ptr.pp_double[5][0] = 21.0;
xy.ptr.pp_double[6][0] = 22.0;
xy.ptr.pp_double[7][0] = 23.0;
clusterizercreate(&s, _state);
clusterizersetpoints(&s, &xy, 8, 1, 0, _state);
for(ahcalgo=0; ahcalgo<=2; ahcalgo++)
{
clusterizersetahcalgo(&s, ahcalgo, _state);
clusterizerrunahc(&s, &rep, _state);
if( (rep.npoints!=8||rep.z.rows!=7)||rep.z.cols!=2 )
{
ae_frame_leave(_state);
return result;
}
if( rep.z.ptr.pp_int[0][0]!=0||rep.z.ptr.pp_int[0][1]!=1 )
{
ae_frame_leave(_state);
return result;
}
if( rep.z.ptr.pp_int[5][0]!=2&&rep.z.ptr.pp_int[5][1]!=2 )
{
ae_frame_leave(_state);
return result;
}
if( rep.z.ptr.pp_int[5][0]!=2&&rep.z.ptr.pp_int[5][1]!=2 )
{
ae_frame_leave(_state);
return result;
}
if( (ahcalgo==0||ahcalgo==2)&&(rep.z.ptr.pp_int[5][0]!=8&&rep.z.ptr.pp_int[5][1]!=8) )
{
ae_frame_leave(_state);
return result;
}
if( ahcalgo==1&&(rep.z.ptr.pp_int[5][0]==8||rep.z.ptr.pp_int[5][1]==8) )
{
ae_frame_leave(_state);
return result;
}
}
/*
* Test which differentiates single linkage and average linkage from
* complete linkage:
* * we have cluster C0={(-2.5), (-2.0)},
* cluster C1={(19.0), (20.0), (21.0), (22.0), (23.0)},
* and point P between them - (10.0)
* * we try three different strategies - single linkage, complete
* linkage, average linkage.
* * any strategy will merge C0 first, then merge points of C1,
* and then merge P with C0 or C1 (depending on linkage type)
* * we test that:
* a) C0 is merged first
* b) after 5 merges (including merge of C0), P is merged with C0 or C1
* c) P is merged with C0 when we have complete linkage, with C1 otherwise
*/
ae_matrix_set_length(&xy, 8, 1, _state);
xy.ptr.pp_double[0][0] = -2.5;
xy.ptr.pp_double[1][0] = -2.0;
xy.ptr.pp_double[2][0] = 10.0;
xy.ptr.pp_double[3][0] = 19.0;
xy.ptr.pp_double[4][0] = 20.0;
xy.ptr.pp_double[5][0] = 21.0;
xy.ptr.pp_double[6][0] = 22.0;
xy.ptr.pp_double[7][0] = 23.0;
clusterizercreate(&s, _state);
clusterizersetpoints(&s, &xy, 8, 1, 0, _state);
for(ahcalgo=0; ahcalgo<=2; ahcalgo++)
{
clusterizersetahcalgo(&s, ahcalgo, _state);
clusterizerrunahc(&s, &rep, _state);
if( (rep.npoints!=8||rep.z.rows!=7)||rep.z.cols!=2 )
{
ae_frame_leave(_state);
return result;
}
if( rep.z.ptr.pp_int[0][0]!=0||rep.z.ptr.pp_int[0][1]!=1 )
{
ae_frame_leave(_state);
return result;
}
if( rep.z.ptr.pp_int[5][0]!=2&&rep.z.ptr.pp_int[5][1]!=2 )
{
ae_frame_leave(_state);
return result;
}
if( rep.z.ptr.pp_int[5][0]!=2&&rep.z.ptr.pp_int[5][1]!=2 )
{
ae_frame_leave(_state);
return result;
}
if( ahcalgo==0&&(rep.z.ptr.pp_int[5][0]!=8&&rep.z.ptr.pp_int[5][1]!=8) )
{
ae_frame_leave(_state);
return result;
}
if( (ahcalgo==1||ahcalgo==2)&&(rep.z.ptr.pp_int[5][0]==8||rep.z.ptr.pp_int[5][1]==8) )
{
ae_frame_leave(_state);
return result;
}
}
/*
* Test which differentiates weighred average linkage from unweighted average linkage:
* * we have cluster C0={(0.0), (1.5), (2.5)},
* cluster C1={(7.5), (7.99)},
* and point P between them - (4.5)
* * we try two different strategies - weighted average linkage and unweighted average linkage
* * any strategy will merge C1 first, then merge points of C0,
* and then merge P with C0 or C1 (depending on linkage type)
* * we test that:
* a) C1 is merged first, C0 is merged after that
* b) after first 3 merges P is merged with C0 or C1
* c) P is merged with C1 when we have weighted average linkage, with C0 otherwise
*/
ae_matrix_set_length(&xy, 6, 1, _state);
xy.ptr.pp_double[0][0] = 0.0;
xy.ptr.pp_double[1][0] = 1.5;
xy.ptr.pp_double[2][0] = 2.5;
xy.ptr.pp_double[3][0] = 4.5;
xy.ptr.pp_double[4][0] = 7.5;
xy.ptr.pp_double[5][0] = 7.99;
clusterizercreate(&s, _state);
clusterizersetpoints(&s, &xy, 6, 1, 0, _state);
for(ahcalgo=2; ahcalgo<=3; ahcalgo++)
{
clusterizersetahcalgo(&s, ahcalgo, _state);
clusterizerrunahc(&s, &rep, _state);
if( (rep.npoints!=6||rep.z.rows!=5)||rep.z.cols!=2 )
{
ae_frame_leave(_state);
return result;
}
if( rep.z.ptr.pp_int[0][0]!=4||rep.z.ptr.pp_int[0][1]!=5 )
{
ae_frame_leave(_state);
return result;
}
if( rep.z.ptr.pp_int[1][0]!=1||rep.z.ptr.pp_int[1][1]!=2 )
{
ae_frame_leave(_state);
return result;
}
if( rep.z.ptr.pp_int[2][0]!=0||rep.z.ptr.pp_int[2][1]!=7 )
{
ae_frame_leave(_state);
return result;
}
if( rep.z.ptr.pp_int[3][0]!=3 )
{
ae_frame_leave(_state);
return result;
}
if( ahcalgo==2&&rep.z.ptr.pp_int[3][1]!=8 )
{
ae_frame_leave(_state);
return result;
}
if( ahcalgo==3&&rep.z.ptr.pp_int[3][1]!=6 )
{
ae_frame_leave(_state);
return result;
}
}
/*
* Test which checks correctness of Ward's method on very basic problem
*/
ae_matrix_set_length(&xy, 4, 1, _state);
xy.ptr.pp_double[0][0] = 0.0;
xy.ptr.pp_double[1][0] = 1.0;
xy.ptr.pp_double[2][0] = 3.1;
xy.ptr.pp_double[3][0] = 4.0;
clusterizercreate(&s, _state);
clusterizersetpoints(&s, &xy, xy.rows, xy.cols, 2, _state);
clusterizergetdistances(&xy, xy.rows, xy.cols, 2, &d, _state);
clusterizersetahcalgo(&s, 4, _state);
clusterizerrunahc(&s, &rep, _state);
if( testclusteringunit_errorsinmerges(&d, &xy, xy.rows, xy.cols, &rep, 4, _state) )
{
ae_frame_leave(_state);
return result;
}
/*
* One more Ward's test
*/
ae_matrix_set_length(&xy, 8, 2, _state);
xy.ptr.pp_double[0][0] = 0.4700566262;
xy.ptr.pp_double[0][1] = 0.4565938448;
xy.ptr.pp_double[1][0] = 0.2394499506;
xy.ptr.pp_double[1][1] = 0.1750209592;
xy.ptr.pp_double[2][0] = 0.6518417019;
xy.ptr.pp_double[2][1] = 0.6151370746;
xy.ptr.pp_double[3][0] = 0.9863942841;
xy.ptr.pp_double[3][1] = 0.7855012189;
xy.ptr.pp_double[4][0] = 0.1517812919;
xy.ptr.pp_double[4][1] = 0.2600174758;
xy.ptr.pp_double[5][0] = 0.7840203638;
xy.ptr.pp_double[5][1] = 0.9023597604;
xy.ptr.pp_double[6][0] = 0.2604194835;
xy.ptr.pp_double[6][1] = 0.9792704661;
xy.ptr.pp_double[7][0] = 0.6353096042;
xy.ptr.pp_double[7][1] = 0.8252606906;
clusterizercreate(&s, _state);
clusterizersetpoints(&s, &xy, xy.rows, xy.cols, 2, _state);
clusterizergetdistances(&xy, xy.rows, xy.cols, 2, &d, _state);
clusterizersetahcalgo(&s, 4, _state);
clusterizerrunahc(&s, &rep, _state);
if( rep.z.ptr.pp_int[0][0]!=1||rep.z.ptr.pp_int[0][1]!=4 )
{
ae_frame_leave(_state);
return result;
}
if( rep.z.ptr.pp_int[1][0]!=5||rep.z.ptr.pp_int[1][1]!=7 )
{
ae_frame_leave(_state);
return result;
}
if( rep.z.ptr.pp_int[2][0]!=0||rep.z.ptr.pp_int[2][1]!=2 )
{
ae_frame_leave(_state);
return result;
}
if( rep.z.ptr.pp_int[3][0]!=3||rep.z.ptr.pp_int[3][1]!=9 )
{
ae_frame_leave(_state);
return result;
}
if( rep.z.ptr.pp_int[4][0]!=10||rep.z.ptr.pp_int[4][1]!=11 )
{
ae_frame_leave(_state);
return result;
}
if( rep.z.ptr.pp_int[5][0]!=6||rep.z.ptr.pp_int[5][1]!=12 )
{
ae_frame_leave(_state);
return result;
}
if( rep.z.ptr.pp_int[6][0]!=8||rep.z.ptr.pp_int[6][1]!=13 )
{
ae_frame_leave(_state);
return result;
}
if( testclusteringunit_errorsinmerges(&d, &xy, xy.rows, xy.cols, &rep, 4, _state) )
{
ae_frame_leave(_state);
return result;
}
/*
* Ability to solve problems with zero distance matrix
*/
npoints = 20;
ae_matrix_set_length(&d, npoints, npoints, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=npoints-1; j++)
{
d.ptr.pp_double[i][j] = 0.0;
}
}
for(ahcalgo=0; ahcalgo<=4; ahcalgo++)
{
clusterizercreate(&s, _state);
clusterizersetdistances(&s, &d, npoints, ae_true, _state);
clusterizersetahcalgo(&s, ahcalgo, _state);
clusterizerrunahc(&s, &rep, _state);
if( (rep.npoints!=npoints||rep.z.rows!=npoints-1)||rep.z.cols!=2 )
{
ae_frame_leave(_state);
return result;
}
}
/*
* Test GetKClusters()
*/
ae_matrix_set_length(&xy, 8, 1, _state);
xy.ptr.pp_double[0][0] = -2.5;
xy.ptr.pp_double[1][0] = -2.0;
xy.ptr.pp_double[2][0] = 10.0;
xy.ptr.pp_double[3][0] = 19.0;
xy.ptr.pp_double[4][0] = 20.0;
xy.ptr.pp_double[5][0] = 21.0;
xy.ptr.pp_double[6][0] = 22.0;
xy.ptr.pp_double[7][0] = 23.0;
clusterizercreate(&s, _state);
clusterizersetpoints(&s, &xy, 8, 1, 0, _state);
clusterizersetahcalgo(&s, 0, _state);
clusterizerrunahc(&s, &rep, _state);
clusterizergetkclusters(&rep, 3, &cidx, &cz, _state);
if( ((((((cidx.ptr.p_int[0]!=1||cidx.ptr.p_int[1]!=1)||cidx.ptr.p_int[2]!=0)||cidx.ptr.p_int[3]!=2)||cidx.ptr.p_int[4]!=2)||cidx.ptr.p_int[5]!=2)||cidx.ptr.p_int[6]!=2)||cidx.ptr.p_int[7]!=2 )
{
ae_frame_leave(_state);
return result;
}
if( (cz.ptr.p_int[0]!=2||cz.ptr.p_int[1]!=8)||cz.ptr.p_int[2]!=12 )
{
ae_frame_leave(_state);
return result;
}
/*
* Test is done
*/
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Advanced agglomerative hierarchical clustering tests : returns True on
failure, False on success.
Advanced testing subroutine perform several automatically generated tests.
*************************************************************************/
static ae_bool testclusteringunit_advancedahctests(ae_state *_state)
{
ae_frame _frame_block;
clusterizerstate s;
ahcreport rep;
ae_matrix xy;
ae_matrix dm;
ae_matrix dm2;
ae_vector idx;
ae_vector disttypes;
ae_vector x0;
ae_vector x1;
ae_int_t d;
ae_int_t n;
ae_int_t npoints;
ae_int_t ahcalgo;
ae_int_t disttype;
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
ae_int_t t;
ae_int_t euclidean;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&xy, 0, sizeof(xy));
memset(&dm, 0, sizeof(dm));
memset(&dm2, 0, sizeof(dm2));
memset(&idx, 0, sizeof(idx));
memset(&disttypes, 0, sizeof(disttypes));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
_clusterizerstate_init(&s, _state, ae_true);
_ahcreport_init(&rep, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&dm, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&dm2, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&idx, 0, DT_INT, _state, ae_true);
ae_vector_init(&disttypes, 0, DT_INT, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
result = ae_false;
euclidean = 2;
/*
* Test on D-dimensional problem:
* * D = 2...5
* * D clusters, each has N points;
* centers are located at x=(0 ... 1 ... 0);
* cluster radii are approximately 0.1
* * single/complete/unweighted_average/weighted_average linkage/Ward's method are tested
* * Euclidean distance is used, either:
* a) one given by distance matrix (ClusterizerSetDistances)
* b) one calculated from dataset (ClusterizerSetPoints)
* * we have N*D points, and N*D-1 merges in total
* * points are randomly rearranged after generation
*
* For all kinds of linkage we perform following test:
* * for each point we remember index of its cluster
* (one which is determined during dataset generation)
* * we clusterize points with ALGLIB capabilities
* * we scan Rep.Z and perform first D*(N-1) merges
* * for each merge we check that it merges points
* from same cluster;
*
* Additonally, we call ErrorsInMerges(). See function comments
* for more information about specific tests performed. This function
* allows us to check that clusters are built exactly as specified by
* definition of the clustering algorithm.
*/
for(d=2; d<=5; d++)
{
for(ahcalgo=0; ahcalgo<=4; ahcalgo++)
{
n = ae_round(ae_pow((double)(3), (double)(ae_randominteger(3, _state)), _state), _state);
npoints = d*n;
/*
* 1. generate dataset.
* 2. fill Idx (array of cluster indexes):
* * first N*D elements store cluster indexes
* * next D*(N-1) elements are filled during merges
* 3. build distance matrix DM
*/
ae_matrix_set_length(&xy, n*d, d, _state);
ae_vector_set_length(&idx, n*d+d*(n-1), _state);
for(i=0; i<=n*d-1; i++)
{
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][j] = 0.2*ae_randomreal(_state)-0.1;
}
xy.ptr.pp_double[i][i%d] = xy.ptr.pp_double[i][i%d]+1.0;
idx.ptr.p_int[i] = i%d;
}
for(i=0; i<=n*d-1; i++)
{
k = ae_randominteger(n*d, _state);
if( k!=i )
{
for(j=0; j<=d-1; j++)
{
v = xy.ptr.pp_double[i][j];
xy.ptr.pp_double[i][j] = xy.ptr.pp_double[k][j];
xy.ptr.pp_double[k][j] = v;
}
t = idx.ptr.p_int[k];
idx.ptr.p_int[k] = idx.ptr.p_int[i];
idx.ptr.p_int[i] = t;
}
}
ae_matrix_set_length(&dm, npoints, npoints, _state);
ae_vector_set_length(&x0, d, _state);
ae_vector_set_length(&x1, d, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=npoints-1; j++)
{
ae_v_move(&x0.ptr.p_double[0], 1, &xy.ptr.pp_double[i][0], 1, ae_v_len(0,d-1));
ae_v_move(&x1.ptr.p_double[0], 1, &xy.ptr.pp_double[j][0], 1, ae_v_len(0,d-1));
dm.ptr.pp_double[i][j] = testclusteringunit_distfunc(&x0, &x1, d, euclidean, _state);
}
}
/*
* Clusterize with SetPoints()
*/
clusterizercreate(&s, _state);
clusterizersetpoints(&s, &xy, n*d, d, euclidean, _state);
clusterizersetahcalgo(&s, ahcalgo, _state);
clusterizerrunahc(&s, &rep, _state);
/*
* Tests:
* * replay first D*(N-1) merges; these merges should take place
* within clusters, intercluster merges will be performed at the
* last stages of the processing.
* * test with ErrorsInMerges()
*/
if( rep.npoints!=npoints )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=d*(n-1)-1; i++)
{
/*
* Check correctness of I-th row of Z
*/
if( (rep.z.ptr.pp_int[i][0]<0||rep.z.ptr.pp_int[i][0]>=rep.z.ptr.pp_int[i][1])||rep.z.ptr.pp_int[i][1]>=d*n+i )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
/*
* Check that merge is performed within cluster
*/
if( idx.ptr.p_int[rep.z.ptr.pp_int[i][0]]!=idx.ptr.p_int[rep.z.ptr.pp_int[i][1]] )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
/*
* Write new entry of Idx.
* Both points from the same cluster, so result of the merge
* belongs to the same cluster
*/
idx.ptr.p_int[n*d+i] = idx.ptr.p_int[rep.z.ptr.pp_int[i][1]];
}
if( ((ahcalgo==0||ahcalgo==1)||ahcalgo==2)||ahcalgo==4 )
{
if( testclusteringunit_errorsinmerges(&dm, &xy, d*n, d, &rep, ahcalgo, _state) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
/*
* Clusterize one more time, now with distance matrix
*/
clusterizercreate(&s, _state);
clusterizersetdistances(&s, &dm, n*d, ae_fp_greater(ae_randomreal(_state),0.5), _state);
clusterizersetahcalgo(&s, ahcalgo, _state);
clusterizerrunahc(&s, &rep, _state);
/*
* Tests:
* * replay first D*(N-1) merges; these merges should take place
* within clusters, intercluster merges will be performed at the
* last stages of the processing.
* * test with ErrorsInMerges()
*/
if( rep.npoints!=npoints )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=d*(n-1)-1; i++)
{
/*
* Check correctness of I-th row of Z
*/
if( (rep.z.ptr.pp_int[i][0]<0||rep.z.ptr.pp_int[i][0]>=rep.z.ptr.pp_int[i][1])||rep.z.ptr.pp_int[i][1]>=d*n+i )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
/*
* Check that merge is performed within cluster
*/
if( idx.ptr.p_int[rep.z.ptr.pp_int[i][0]]!=idx.ptr.p_int[rep.z.ptr.pp_int[i][1]] )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
/*
* Write new entry of Idx.
* Both points from the same cluster, so result of the merge
* belongs to the same cluster
*/
idx.ptr.p_int[n*d+i] = idx.ptr.p_int[rep.z.ptr.pp_int[i][1]];
}
if( ((ahcalgo==0||ahcalgo==1)||ahcalgo==2)||ahcalgo==4 )
{
if( testclusteringunit_errorsinmerges(&dm, &xy, d*n, d, &rep, ahcalgo, _state) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
/*
* Test on random D-dimensional problem:
* * D = 2...5
* * N=1..16 random points from unit hypercube
* * single/complete/unweighted_average linkage/Ward's method are tested
* * different distance functions are tested
* * we call ErrorsInMerges() and we check distance matrix
* calculated by unit test against one returned by GetDistances()
*/
ae_vector_set_length(&disttypes, 9, _state);
disttypes.ptr.p_int[0] = 0;
disttypes.ptr.p_int[1] = 1;
disttypes.ptr.p_int[2] = 2;
disttypes.ptr.p_int[3] = 10;
disttypes.ptr.p_int[4] = 11;
disttypes.ptr.p_int[5] = 12;
disttypes.ptr.p_int[6] = 13;
disttypes.ptr.p_int[7] = 20;
disttypes.ptr.p_int[8] = 21;
for(disttype=0; disttype<=disttypes.cnt-1; disttype++)
{
for(ahcalgo=0; ahcalgo<=4; ahcalgo++)
{
if( ahcalgo==3 )
{
continue;
}
if( ahcalgo==4&&disttype!=2 )
{
continue;
}
npoints = ae_round(ae_pow((double)(2), (double)(ae_randominteger(5, _state)), _state), _state);
d = 2+ae_randominteger(4, _state);
/*
* Generate dataset and distance matrix
*/
ae_matrix_set_length(&xy, npoints, d, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][j] = ae_randomreal(_state);
}
}
ae_matrix_set_length(&dm, npoints, npoints, _state);
ae_vector_set_length(&x0, d, _state);
ae_vector_set_length(&x1, d, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=npoints-1; j++)
{
ae_v_move(&x0.ptr.p_double[0], 1, &xy.ptr.pp_double[i][0], 1, ae_v_len(0,d-1));
ae_v_move(&x1.ptr.p_double[0], 1, &xy.ptr.pp_double[j][0], 1, ae_v_len(0,d-1));
dm.ptr.pp_double[i][j] = testclusteringunit_distfunc(&x0, &x1, d, disttypes.ptr.p_int[disttype], _state);
}
}
/*
* Clusterize
*/
clusterizercreate(&s, _state);
clusterizersetpoints(&s, &xy, npoints, d, disttypes.ptr.p_int[disttype], _state);
clusterizersetahcalgo(&s, ahcalgo, _state);
clusterizerrunahc(&s, &rep, _state);
/*
* Test with ErrorsInMerges()
*/
if( testclusteringunit_errorsinmerges(&dm, &xy, npoints, d, &rep, ahcalgo, _state) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
/*
* Test distance matrix
*/
clusterizergetdistances(&xy, npoints, d, disttypes.ptr.p_int[disttype], &dm2, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=npoints-1; j++)
{
if( !ae_isfinite(dm2.ptr.pp_double[i][j], _state)||ae_fp_greater(ae_fabs(dm.ptr.pp_double[i][j]-dm2.ptr.pp_double[i][j], _state),1.0E5*ae_machineepsilon) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Simple test 1: ellipsoid in NF-dimensional space.
compare k-means centers with random centers
*************************************************************************/
static void testclusteringunit_kmeanssimpletest1(ae_int_t nvars,
ae_int_t nc,
ae_int_t passcount,
ae_bool* converrors,
ae_bool* othererrors,
ae_bool* simpleerrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t npoints;
ae_int_t majoraxis;
ae_matrix xy;
ae_vector tmp;
double v;
ae_int_t i;
ae_int_t j;
ae_int_t pass;
ae_int_t restarts;
double ekmeans;
double erandom;
double dclosest;
ae_int_t cclosest;
clusterizerstate s;
kmeansreport rep;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
memset(&tmp, 0, sizeof(tmp));
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
_clusterizerstate_init(&s, _state, ae_true);
_kmeansreport_init(&rep, _state, ae_true);
npoints = nc*100;
restarts = 5;
passcount = 10;
ae_vector_set_length(&tmp, nvars-1+1, _state);
for(pass=1; pass<=passcount; pass++)
{
/*
* Fill
*/
ae_matrix_set_length(&xy, npoints-1+1, nvars-1+1, _state);
majoraxis = ae_randominteger(nvars, _state);
for(i=0; i<=npoints-1; i++)
{
testclusteringunit_rsphere(&xy, nvars, i, _state);
xy.ptr.pp_double[i][majoraxis] = nc*xy.ptr.pp_double[i][majoraxis];
}
/*
* Test
*/
clusterizercreate(&s, _state);
clusterizersetpoints(&s, &xy, npoints, nvars, 2, _state);
clusterizersetkmeanslimits(&s, restarts, 0, _state);
clusterizerrunkmeans(&s, nc, &rep, _state);
if( rep.terminationtype<=0 )
{
*converrors = ae_true;
ae_frame_leave(_state);
return;
}
/*
* Test that XYC is correct mapping to cluster centers
*/
for(i=0; i<=npoints-1; i++)
{
cclosest = -1;
dclosest = ae_maxrealnumber;
for(j=0; j<=nc-1; j++)
{
ae_v_move(&tmp.ptr.p_double[0], 1, &xy.ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
ae_v_sub(&tmp.ptr.p_double[0], 1, &rep.c.ptr.pp_double[j][0], 1, ae_v_len(0,nvars-1));
v = ae_v_dotproduct(&tmp.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,nvars-1));
if( ae_fp_less(v,dclosest) )
{
cclosest = j;
dclosest = v;
}
}
if( cclosest!=rep.cidx.ptr.p_int[i] )
{
*othererrors = ae_true;
ae_frame_leave(_state);
return;
}
}
/*
* Use first NC rows of XY as random centers
* (XY is totally random, so it is as good as any other choice).
*
* Compare potential functions.
*/
ekmeans = (double)(0);
for(i=0; i<=npoints-1; i++)
{
ae_v_move(&tmp.ptr.p_double[0], 1, &xy.ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
ae_v_sub(&tmp.ptr.p_double[0], 1, &rep.c.ptr.pp_double[rep.cidx.ptr.p_int[i]][0], 1, ae_v_len(0,nvars-1));
v = ae_v_dotproduct(&tmp.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,nvars-1));
ekmeans = ekmeans+v;
}
erandom = (double)(0);
for(i=0; i<=npoints-1; i++)
{
dclosest = ae_maxrealnumber;
v = (double)(0);
for(j=0; j<=nc-1; j++)
{
ae_v_move(&tmp.ptr.p_double[0], 1, &xy.ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
ae_v_sub(&tmp.ptr.p_double[0], 1, &xy.ptr.pp_double[j][0], 1, ae_v_len(0,nvars-1));
v = ae_v_dotproduct(&tmp.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,nvars-1));
if( ae_fp_less(v,dclosest) )
{
dclosest = v;
}
}
erandom = erandom+v;
}
if( ae_fp_less(erandom,ekmeans) )
{
*simpleerrors = ae_true;
ae_frame_leave(_state);
return;
}
}
ae_frame_leave(_state);
}
/*************************************************************************
This test perform several checks for special properties
On failure sets error flag, on success leaves it unchanged.
*************************************************************************/
static void testclusteringunit_kmeansspecialtests(ae_bool* othererrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t npoints;
ae_int_t nfeatures;
ae_int_t nclusters;
ae_int_t initalgo;
ae_matrix xy;
ae_matrix c;
ae_int_t idx0;
ae_int_t idx1;
ae_int_t idx2;
ae_int_t i;
ae_int_t j;
ae_int_t pass;
ae_int_t passcount;
ae_int_t separation;
ae_vector xyc;
ae_vector xycref;
ae_vector xydist2;
ae_vector xydist2ref;
ae_vector energies;
hqrndstate rs;
clusterizerstate s;
kmeansreport rep;
ae_shared_pool bufferpool;
apbuffers bufferseed;
ae_vector pointslist;
ae_vector featureslist;
ae_vector clusterslist;
ae_bool allsame;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
memset(&c, 0, sizeof(c));
memset(&xyc, 0, sizeof(xyc));
memset(&xycref, 0, sizeof(xycref));
memset(&xydist2, 0, sizeof(xydist2));
memset(&xydist2ref, 0, sizeof(xydist2ref));
memset(&energies, 0, sizeof(energies));
memset(&rs, 0, sizeof(rs));
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&bufferpool, 0, sizeof(bufferpool));
memset(&bufferseed, 0, sizeof(bufferseed));
memset(&pointslist, 0, sizeof(pointslist));
memset(&featureslist, 0, sizeof(featureslist));
memset(&clusterslist, 0, sizeof(clusterslist));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xyc, 0, DT_INT, _state, ae_true);
ae_vector_init(&xycref, 0, DT_INT, _state, ae_true);
ae_vector_init(&xydist2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xydist2ref, 0, DT_REAL, _state, ae_true);
ae_vector_init(&energies, 0, DT_REAL, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
_clusterizerstate_init(&s, _state, ae_true);
_kmeansreport_init(&rep, _state, ae_true);
ae_shared_pool_init(&bufferpool, _state, ae_true);
_apbuffers_init(&bufferseed, _state, ae_true);
ae_vector_init(&pointslist, 0, DT_INT, _state, ae_true);
ae_vector_init(&featureslist, 0, DT_INT, _state, ae_true);
ae_vector_init(&clusterslist, 0, DT_INT, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Compare different initialization algorithms:
* * dataset is K balls, chosen at random gaussian points, with
* radius equal to 2^(-Separation).
* * we generate random sample, run k-means initialization algorithm
* and calculate mean energy for each initialization algorithm.
* In order to suppress Lloyd's iteration we use KmeansDbgNoIts
* debug flag.
* * then, we compare mean energies; kmeans++ must be best one,
* random initialization must be worst one.
*/
ae_vector_set_length(&energies, 4, _state);
passcount = 1000;
npoints = 100;
nfeatures = 3;
nclusters = 6;
ae_matrix_set_length(&xy, npoints, nfeatures, _state);
ae_matrix_set_length(&c, nclusters, nfeatures, _state);
clusterizercreate(&s, _state);
s.kmeansdbgnoits = ae_true;
for(separation=2; separation<=5; separation++)
{
/*
* Try different init algorithms
*/
for(initalgo=1; initalgo<=3; initalgo++)
{
energies.ptr.p_double[initalgo] = 0.0;
clusterizersetkmeansinit(&s, initalgo, _state);
for(pass=1; pass<=passcount; pass++)
{
/*
* Generate centers of balls
*/
for(i=0; i<=nclusters-1; i++)
{
for(j=0; j<=nfeatures-1; j++)
{
c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
/*
* Generate points
*/
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nfeatures-1; j++)
{
xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state)*ae_pow((double)(2), (double)(-separation), _state)+c.ptr.pp_double[i%nclusters][j];
}
}
/*
* Run clusterization
*/
clusterizersetpoints(&s, &xy, npoints, nfeatures, 2, _state);
clusterizerrunkmeans(&s, nclusters, &rep, _state);
ae_set_error_flag(othererrors, rep.terminationtype<=0, __FILE__, __LINE__, "testclusteringunit.ap:1069");
energies.ptr.p_double[initalgo] = energies.ptr.p_double[initalgo]+rep.energy/passcount;
}
}
/*
* Compare
*/
ae_set_error_flag(othererrors, !ae_fp_less(energies.ptr.p_double[2],energies.ptr.p_double[1]), __FILE__, __LINE__, "testclusteringunit.ap:1077");
ae_set_error_flag(othererrors, !ae_fp_less(energies.ptr.p_double[3],energies.ptr.p_double[1]), __FILE__, __LINE__, "testclusteringunit.ap:1078");
}
/*
* Test distance calculation algorithm
*/
ae_vector_set_length(&pointslist, 6, _state);
pointslist.ptr.p_int[0] = 1;
pointslist.ptr.p_int[1] = 10;
pointslist.ptr.p_int[2] = 32;
pointslist.ptr.p_int[3] = 100;
pointslist.ptr.p_int[4] = 512;
pointslist.ptr.p_int[5] = 8000;
ae_vector_set_length(&featureslist, 5, _state);
featureslist.ptr.p_int[0] = 1;
featureslist.ptr.p_int[1] = 5;
featureslist.ptr.p_int[2] = 32;
featureslist.ptr.p_int[3] = 50;
featureslist.ptr.p_int[4] = 96;
ae_vector_set_length(&clusterslist, 5, _state);
clusterslist.ptr.p_int[0] = 1;
clusterslist.ptr.p_int[1] = 5;
clusterslist.ptr.p_int[2] = 32;
clusterslist.ptr.p_int[3] = 50;
clusterslist.ptr.p_int[4] = 96;
ae_shared_pool_set_seed(&bufferpool, &bufferseed, sizeof(bufferseed), _apbuffers_init, _apbuffers_init_copy, _apbuffers_destroy, _state);
for(idx0=0; idx0<=pointslist.cnt-1; idx0++)
{
for(idx1=0; idx1<=featureslist.cnt-1; idx1++)
{
for(idx2=0; idx2<=clusterslist.cnt-1; idx2++)
{
npoints = pointslist.ptr.p_int[idx0];
nfeatures = featureslist.ptr.p_int[idx1];
nclusters = clusterslist.ptr.p_int[idx2];
ae_matrix_set_length(&xy, npoints, nfeatures, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nfeatures-1; j++)
{
xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
ae_matrix_set_length(&c, nclusters, nfeatures, _state);
for(i=0; i<=nclusters-1; i++)
{
for(j=0; j<=nfeatures-1; j++)
{
c.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
ae_vector_set_length(&xyc, npoints, _state);
ae_vector_set_length(&xycref, npoints, _state);
ae_vector_set_length(&xydist2, npoints, _state);
ae_vector_set_length(&xydist2ref, npoints, _state);
/*
* Test
*/
kmeansupdatedistances(&xy, 0, npoints, nfeatures, &c, 0, nclusters, &xyc, &xydist2, &bufferpool, _state);
testclusteringunit_kmeansreferenceupdatedistances(&xy, npoints, nfeatures, &c, nclusters, &xycref, &xydist2ref, _state);
for(i=0; i<=npoints-1; i++)
{
ae_set_error_flag(othererrors, xyc.ptr.p_int[i]!=xycref.ptr.p_int[i], __FILE__, __LINE__, "testclusteringunit.ap:1137");
ae_set_error_flag(othererrors, ae_fp_greater(ae_fabs(xydist2.ptr.p_double[i]-xydist2ref.ptr.p_double[i], _state),1.0E-6), __FILE__, __LINE__, "testclusteringunit.ap:1138");
}
}
}
}
/*
* Test degenerate dataset (less than NClusters distinct points)
*/
for(nclusters=2; nclusters<=10; nclusters++)
{
for(initalgo=0; initalgo<=3; initalgo++)
{
for(pass=1; pass<=10; pass++)
{
/*
* Initialize points. Two algorithms are used:
* * initialization by small integers (no rounding problems)
* * initialization by "long" fraction
*/
npoints = 100;
nfeatures = 10;
ae_matrix_set_length(&xy, npoints, nfeatures, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
for(i=0; i<=nclusters-2; i++)
{
for(j=0; j<=nfeatures-1; j++)
{
xy.ptr.pp_double[i][j] = ae_sin(hqrndnormal(&rs, _state), _state);
}
}
}
else
{
for(i=0; i<=nclusters-2; i++)
{
for(j=0; j<=nfeatures-1; j++)
{
xy.ptr.pp_double[i][j] = (double)(hqrnduniformi(&rs, 50, _state));
}
}
}
for(i=nclusters-1; i<=npoints-1; i++)
{
idx0 = hqrnduniformi(&rs, nclusters-1, _state);
for(j=0; j<=nfeatures-1; j++)
{
xy.ptr.pp_double[i][j] = xy.ptr.pp_double[idx0][j];
}
}
/*
* Clusterize with unlimited number of iterations.
* Correct error code must be returned.
*/
clusterizercreate(&s, _state);
clusterizersetpoints(&s, &xy, npoints, nfeatures, 2, _state);
clusterizersetkmeanslimits(&s, 1, 0, _state);
clusterizersetkmeansinit(&s, initalgo, _state);
clusterizerrunkmeans(&s, nclusters, &rep, _state);
ae_set_error_flag(othererrors, rep.terminationtype!=-3, __FILE__, __LINE__, "testclusteringunit.ap:1185");
}
}
}
/*
* Test deterministic seed:
* * specyfying zero seed, or not specyfind seed at all = nondeterministic algo
* * nonzero zeed = deterministic algo
*/
for(initalgo=0; initalgo<=3; initalgo++)
{
/*
* Initialize points.
*/
npoints = 100;
nfeatures = 3;
ae_matrix_set_length(&xy, npoints, nfeatures, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nfeatures-1; j++)
{
xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
/*
* Clusterize with negative seed.
*
* Perform multiple runs, compare results with
* first one returned - at least one result must
* be different.
*/
clusterizercreate(&s, _state);
clusterizersetpoints(&s, &xy, npoints, nfeatures, 2, _state);
clusterizersetkmeanslimits(&s, 1, 1, _state);
clusterizersetkmeansinit(&s, initalgo, _state);
clusterizersetseed(&s, -ae_randominteger(3, _state), _state);
allsame = ae_true;
for(pass=0; pass<=10; pass++)
{
clusterizerrunkmeans(&s, nclusters, &rep, _state);
ae_set_error_flag(othererrors, rep.terminationtype<=0, __FILE__, __LINE__, "testclusteringunit.ap:1221");
if( *othererrors )
{
ae_frame_leave(_state);
return;
}
if( pass==0 )
{
/*
* Save clusters
*/
ae_matrix_set_length(&c, rep.c.rows, rep.c.cols, _state);
for(i=0; i<=rep.c.rows-1; i++)
{
for(j=0; j<=rep.c.cols-1; j++)
{
c.ptr.pp_double[i][j] = rep.c.ptr.pp_double[i][j];
}
}
}
else
{
/*
* Compare clusters with ones returned from first run.
*/
for(i=0; i<=rep.c.rows-1; i++)
{
for(j=0; j<=rep.c.cols-1; j++)
{
allsame = allsame&&ae_fp_eq(c.ptr.pp_double[i][j],rep.c.ptr.pp_double[i][j]);
}
}
}
}
ae_set_error_flag(othererrors, allsame, __FILE__, __LINE__, "testclusteringunit.ap:1244");
/*
* Clusterize with positive seed.
*
* Perform multiple runs, compare results with
* first one returned - all results must be same.
*/
clusterizercreate(&s, _state);
clusterizersetpoints(&s, &xy, npoints, nfeatures, 2, _state);
clusterizersetkmeanslimits(&s, 1, 1, _state);
clusterizersetkmeansinit(&s, initalgo, _state);
clusterizersetseed(&s, 1+ae_randominteger(3, _state), _state);
allsame = ae_true;
for(pass=0; pass<=10; pass++)
{
clusterizerrunkmeans(&s, nclusters, &rep, _state);
ae_set_error_flag(othererrors, rep.terminationtype<=0, __FILE__, __LINE__, "testclusteringunit.ap:1261");
if( *othererrors )
{
ae_frame_leave(_state);
return;
}
if( pass==0 )
{
/*
* Save clusters
*/
ae_matrix_set_length(&c, rep.c.rows, rep.c.cols, _state);
for(i=0; i<=rep.c.rows-1; i++)
{
for(j=0; j<=rep.c.cols-1; j++)
{
c.ptr.pp_double[i][j] = rep.c.ptr.pp_double[i][j];
}
}
}
else
{
/*
* Compare clusters with ones returned from first run.
*/
for(i=0; i<=rep.c.rows-1; i++)
{
for(j=0; j<=rep.c.cols-1; j++)
{
allsame = allsame&&ae_fp_eq(c.ptr.pp_double[i][j],rep.c.ptr.pp_double[i][j]);
}
}
}
}
ae_set_error_flag(othererrors, !allsame, __FILE__, __LINE__, "testclusteringunit.ap:1284");
/*
* Clusterize with default seed.
*
* Perform multiple runs, compare results with
* first one returned - all results must be same.
*/
clusterizercreate(&s, _state);
clusterizersetpoints(&s, &xy, npoints, nfeatures, 2, _state);
clusterizersetkmeanslimits(&s, 1, 1, _state);
clusterizersetkmeansinit(&s, initalgo, _state);
allsame = ae_true;
for(pass=0; pass<=10; pass++)
{
clusterizerrunkmeans(&s, nclusters, &rep, _state);
ae_set_error_flag(othererrors, rep.terminationtype<=0, __FILE__, __LINE__, "testclusteringunit.ap:1301");
if( *othererrors )
{
ae_frame_leave(_state);
return;
}
if( pass==0 )
{
/*
* Save clusters
*/
ae_matrix_set_length(&c, rep.c.rows, rep.c.cols, _state);
for(i=0; i<=rep.c.rows-1; i++)
{
for(j=0; j<=rep.c.cols-1; j++)
{
c.ptr.pp_double[i][j] = rep.c.ptr.pp_double[i][j];
}
}
}
else
{
/*
* Compare clusters with ones returned from first run.
*/
for(i=0; i<=rep.c.rows-1; i++)
{
for(j=0; j<=rep.c.cols-1; j++)
{
allsame = allsame&&ae_fp_eq(c.ptr.pp_double[i][j],rep.c.ptr.pp_double[i][j]);
}
}
}
}
ae_set_error_flag(othererrors, !allsame, __FILE__, __LINE__, "testclusteringunit.ap:1324");
}
ae_frame_leave(_state);
}
/*************************************************************************
This test checks algorithm ability to handle degenerate problems without
causing infinite loop.
*************************************************************************/
static void testclusteringunit_kmeansinfinitelooptest(ae_bool* othererrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t npoints;
ae_int_t nfeatures;
ae_int_t nclusters;
ae_int_t restarts;
ae_matrix xy;
ae_int_t i;
ae_int_t j;
clusterizerstate s;
kmeansreport rep;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_clusterizerstate_init(&s, _state, ae_true);
_kmeansreport_init(&rep, _state, ae_true);
/*
* Problem 1: all points are same.
*
* For NClusters=1 we must get correct solution, for NClusters>1 we must get failure.
*/
npoints = 100;
nfeatures = 1;
restarts = 5;
ae_matrix_set_length(&xy, npoints, nfeatures, _state);
for(j=0; j<=nfeatures-1; j++)
{
xy.ptr.pp_double[0][j] = ae_randomreal(_state);
}
for(i=1; i<=npoints-1; i++)
{
for(j=0; j<=nfeatures-1; j++)
{
xy.ptr.pp_double[i][j] = xy.ptr.pp_double[0][j];
}
}
nclusters = 1;
clusterizercreate(&s, _state);
clusterizersetpoints(&s, &xy, npoints, nfeatures, 2, _state);
clusterizersetkmeanslimits(&s, restarts, 0, _state);
clusterizerrunkmeans(&s, nclusters, &rep, _state);
*othererrors = *othererrors||rep.terminationtype<=0;
for(i=0; i<=nfeatures-1; i++)
{
*othererrors = *othererrors||ae_fp_greater(ae_fabs(rep.c.ptr.pp_double[0][i]-xy.ptr.pp_double[0][i], _state),1000*ae_machineepsilon);
}
for(i=0; i<=npoints-1; i++)
{
*othererrors = *othererrors||rep.cidx.ptr.p_int[i]!=0;
}
nclusters = 5;
clusterizerrunkmeans(&s, nclusters, &rep, _state);
*othererrors = *othererrors||rep.terminationtype>0;
/*
* Problem 2: degenerate dataset (report by Andreas).
*/
npoints = 57;
nfeatures = 1;
restarts = 1;
nclusters = 4;
ae_matrix_set_length(&xy, npoints, nfeatures, _state);
xy.ptr.pp_double[0][0] = 12.244689632138986;
xy.ptr.pp_double[1][0] = 12.244689632138982;
xy.ptr.pp_double[2][0] = 12.244689632138986;
xy.ptr.pp_double[3][0] = 12.244689632138982;
xy.ptr.pp_double[4][0] = 12.244689632138986;
xy.ptr.pp_double[5][0] = 12.244689632138986;
xy.ptr.pp_double[6][0] = 12.244689632138986;
xy.ptr.pp_double[7][0] = 12.244689632138986;
xy.ptr.pp_double[8][0] = 12.244689632138986;
xy.ptr.pp_double[9][0] = 12.244689632138986;
xy.ptr.pp_double[10][0] = 12.244689632138989;
xy.ptr.pp_double[11][0] = 12.244689632138984;
xy.ptr.pp_double[12][0] = 12.244689632138986;
xy.ptr.pp_double[13][0] = 12.244689632138986;
xy.ptr.pp_double[14][0] = 12.244689632138989;
xy.ptr.pp_double[15][0] = 12.244689632138986;
xy.ptr.pp_double[16][0] = 12.244689632138986;
xy.ptr.pp_double[17][0] = 12.244689632138986;
xy.ptr.pp_double[18][0] = 12.244689632138986;
xy.ptr.pp_double[19][0] = 12.244689632138989;
xy.ptr.pp_double[20][0] = 12.244689632138972;
xy.ptr.pp_double[21][0] = 12.244689632138986;
xy.ptr.pp_double[22][0] = 12.244689632138986;
xy.ptr.pp_double[23][0] = 12.244689632138986;
xy.ptr.pp_double[24][0] = 12.244689632138984;
xy.ptr.pp_double[25][0] = 12.244689632138982;
xy.ptr.pp_double[26][0] = 12.244689632138986;
xy.ptr.pp_double[27][0] = 12.244689632138986;
xy.ptr.pp_double[28][0] = 12.244689632138986;
xy.ptr.pp_double[29][0] = 12.244689632138986;
xy.ptr.pp_double[30][0] = 12.244689632138986;
xy.ptr.pp_double[31][0] = 12.244689632138986;
xy.ptr.pp_double[32][0] = 12.244689632138986;
xy.ptr.pp_double[33][0] = 12.244689632138986;
xy.ptr.pp_double[34][0] = 12.244689632138986;
xy.ptr.pp_double[35][0] = 12.244689632138982;
xy.ptr.pp_double[36][0] = 12.244689632138989;
xy.ptr.pp_double[37][0] = 12.244689632138986;
xy.ptr.pp_double[38][0] = 12.244689632138986;
xy.ptr.pp_double[39][0] = 12.244689632138986;
xy.ptr.pp_double[40][0] = 12.244689632138986;
xy.ptr.pp_double[41][0] = 12.244689632138986;
xy.ptr.pp_double[42][0] = 12.244689632138986;
xy.ptr.pp_double[43][0] = 12.244689632138986;
xy.ptr.pp_double[44][0] = 12.244689632138986;
xy.ptr.pp_double[45][0] = 12.244689632138986;
xy.ptr.pp_double[46][0] = 12.244689632138986;
xy.ptr.pp_double[47][0] = 12.244689632138986;
xy.ptr.pp_double[48][0] = 12.244689632138986;
xy.ptr.pp_double[49][0] = 12.244689632138986;
xy.ptr.pp_double[50][0] = 12.244689632138984;
xy.ptr.pp_double[51][0] = 12.244689632138986;
xy.ptr.pp_double[52][0] = 12.244689632138986;
xy.ptr.pp_double[53][0] = 12.244689632138986;
xy.ptr.pp_double[54][0] = 12.244689632138986;
xy.ptr.pp_double[55][0] = 12.244689632138986;
xy.ptr.pp_double[56][0] = 12.244689632138986;
clusterizercreate(&s, _state);
clusterizersetpoints(&s, &xy, npoints, nfeatures, 2, _state);
clusterizersetkmeanslimits(&s, restarts, 0, _state);
clusterizerrunkmeans(&s, nclusters, &rep, _state);
*othererrors = *othererrors||rep.terminationtype<=0;
ae_frame_leave(_state);
}
/*************************************************************************
This non-deterministic test checks that Restarts>1 significantly improves
quality of results.
Subroutine generates random task 3 unit balls in 2D, each with 20 points,
separated by 5 units wide gaps, and solves it with Restarts=1 and with
Restarts=5. Potential functions are compared, outcome of the trial is
either 0 or 1 (depending on what is better).
Sequence of 1000 such tasks is solved. If Restarts>1 actually improve
quality of solution, sum of outcome will be non-binomial. If it doesn't
matter, it will be binomially distributed.
P.S. This test was added after report from Gianluca Borello who noticed
error in the handling of multiple restarts.
*************************************************************************/
static void testclusteringunit_kmeansrestartstest(ae_bool* converrors,
ae_bool* restartserrors,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t npoints;
ae_int_t nvars;
ae_int_t nclusters;
ae_int_t clustersize;
ae_int_t restarts;
ae_int_t passcount;
double sigmathreshold;
double p;
double s;
ae_matrix xy;
ae_vector tmp;
ae_int_t i;
ae_int_t j;
ae_int_t pass;
double ea;
double eb;
double v;
clusterizerstate state;
kmeansreport rep1;
kmeansreport rep2;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
memset(&tmp, 0, sizeof(tmp));
memset(&state, 0, sizeof(state));
memset(&rep1, 0, sizeof(rep1));
memset(&rep2, 0, sizeof(rep2));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
_clusterizerstate_init(&state, _state, ae_true);
_kmeansreport_init(&rep1, _state, ae_true);
_kmeansreport_init(&rep2, _state, ae_true);
restarts = 5;
passcount = 1000;
clustersize = 20;
nclusters = 3;
nvars = 2;
npoints = nclusters*clustersize;
sigmathreshold = (double)(5);
ae_matrix_set_length(&xy, npoints, nvars, _state);
ae_vector_set_length(&tmp, nvars, _state);
p = (double)(0);
for(pass=1; pass<=passcount; pass++)
{
/*
* Fill
*/
for(i=0; i<=npoints-1; i++)
{
testclusteringunit_rsphere(&xy, nvars, i, _state);
for(j=0; j<=nvars-1; j++)
{
xy.ptr.pp_double[i][j] = xy.ptr.pp_double[i][j]+(double)i/(double)clustersize*5;
}
}
clusterizercreate(&state, _state);
clusterizersetpoints(&state, &xy, npoints, nvars, 2, _state);
/*
* Test: Restarts=1
*/
clusterizersetkmeanslimits(&state, 1, 0, _state);
clusterizerrunkmeans(&state, nclusters, &rep1, _state);
if( rep1.terminationtype<=0 )
{
*converrors = ae_true;
ae_frame_leave(_state);
return;
}
ea = (double)(0);
for(i=0; i<=npoints-1; i++)
{
ae_v_move(&tmp.ptr.p_double[0], 1, &xy.ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
ae_v_sub(&tmp.ptr.p_double[0], 1, &rep1.c.ptr.pp_double[rep1.cidx.ptr.p_int[i]][0], 1, ae_v_len(0,nvars-1));
v = ae_v_dotproduct(&tmp.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,nvars-1));
ea = ea+v;
}
/*
* Test: Restarts>1
*/
clusterizersetkmeanslimits(&state, restarts, 0, _state);
clusterizerrunkmeans(&state, nclusters, &rep2, _state);
if( rep2.terminationtype<=0 )
{
*converrors = ae_true;
ae_frame_leave(_state);
return;
}
eb = (double)(0);
for(i=0; i<=npoints-1; i++)
{
ae_v_move(&tmp.ptr.p_double[0], 1, &xy.ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
ae_v_sub(&tmp.ptr.p_double[0], 1, &rep2.c.ptr.pp_double[rep2.cidx.ptr.p_int[i]][0], 1, ae_v_len(0,nvars-1));
v = ae_v_dotproduct(&tmp.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,nvars-1));
eb = eb+v;
}
/*
* Calculate statistic.
*/
if( ae_fp_less(ea,eb) )
{
p = p+1;
}
if( ae_fp_eq(ea,eb) )
{
p = p+0.5;
}
}
/*
* If Restarts doesn't influence quality of centers found, P must be
* binomially distributed random value with mean 0.5*PassCount and
* standard deviation Sqrt(PassCount/4).
*
* If Restarts do influence quality of solution, P must be significantly
* lower than 0.5*PassCount.
*/
s = (p-0.5*passcount)/ae_sqrt((double)passcount/(double)4, _state);
*restartserrors = *restartserrors||ae_fp_greater(s,-sigmathreshold);
ae_frame_leave(_state);
}
/*************************************************************************
Random normal number
*************************************************************************/
static double testclusteringunit_rnormal(ae_state *_state)
{
double u;
double v;
double s;
double x1;
double result;
for(;;)
{
u = 2*ae_randomreal(_state)-1;
v = 2*ae_randomreal(_state)-1;
s = ae_sqr(u, _state)+ae_sqr(v, _state);
if( ae_fp_greater(s,(double)(0))&&ae_fp_less(s,(double)(1)) )
{
s = ae_sqrt(-2*ae_log(s, _state)/s, _state);
x1 = u*s;
break;
}
}
result = x1;
return result;
}
/*************************************************************************
Random point from sphere
*************************************************************************/
static void testclusteringunit_rsphere(/* Real */ ae_matrix* xy,
ae_int_t n,
ae_int_t i,
ae_state *_state)
{
ae_int_t j;
double v;
for(j=0; j<=n-1; j++)
{
xy->ptr.pp_double[i][j] = testclusteringunit_rnormal(_state);
}
v = ae_v_dotproduct(&xy->ptr.pp_double[i][0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
v = ae_randomreal(_state)/ae_sqrt(v, _state);
ae_v_muld(&xy->ptr.pp_double[i][0], 1, ae_v_len(0,n-1), v);
}
/*************************************************************************
Distance function: distance between X0 and X1
X0, X1 - array[D], points
DistType - distance type
*************************************************************************/
static double testclusteringunit_distfunc(/* Real */ ae_vector* x0,
/* Real */ ae_vector* x1,
ae_int_t d,
ae_int_t disttype,
ae_state *_state)
{
ae_int_t i;
double s0;
double s1;
double result;
ae_assert((((((((disttype==0||disttype==1)||disttype==2)||disttype==10)||disttype==11)||disttype==12)||disttype==13)||disttype==20)||disttype==21, "Assertion failed", _state);
if( disttype==0 )
{
result = 0.0;
for(i=0; i<=d-1; i++)
{
result = ae_maxreal(result, ae_fabs(x0->ptr.p_double[i]-x1->ptr.p_double[i], _state), _state);
}
return result;
}
if( disttype==1 )
{
result = 0.0;
for(i=0; i<=d-1; i++)
{
result = result+ae_fabs(x0->ptr.p_double[i]-x1->ptr.p_double[i], _state);
}
return result;
}
if( disttype==2 )
{
result = 0.0;
for(i=0; i<=d-1; i++)
{
result = result+ae_sqr(x0->ptr.p_double[i]-x1->ptr.p_double[i], _state);
}
result = ae_sqrt(result, _state);
return result;
}
if( disttype==10 )
{
result = ae_maxreal(1-pearsoncorr2(x0, x1, d, _state), 0.0, _state);
return result;
}
if( disttype==11 )
{
result = ae_maxreal(1-ae_fabs(pearsoncorr2(x0, x1, d, _state), _state), 0.0, _state);
return result;
}
if( disttype==12||disttype==13 )
{
s0 = 0.0;
s1 = 0.0;
for(i=0; i<=d-1; i++)
{
s0 = s0+ae_sqr(x0->ptr.p_double[i], _state)/d;
s1 = s1+ae_sqr(x1->ptr.p_double[i], _state)/d;
}
s0 = ae_sqrt(s0, _state);
s1 = ae_sqrt(s1, _state);
result = (double)(0);
for(i=0; i<=d-1; i++)
{
result = result+x0->ptr.p_double[i]/s0*(x1->ptr.p_double[i]/s1)/d;
}
if( disttype==12 )
{
result = ae_maxreal(1-result, 0.0, _state);
}
else
{
result = ae_maxreal(1-ae_fabs(result, _state), 0.0, _state);
}
return result;
}
if( disttype==20 )
{
result = ae_maxreal(1-spearmancorr2(x0, x1, d, _state), 0.0, _state);
return result;
}
if( disttype==21 )
{
result = ae_maxreal(1-ae_fabs(spearmancorr2(x0, x1, d, _state), _state), 0.0, _state);
return result;
}
result = (double)(0);
return result;
}
/*************************************************************************
This function replays merges and checks that:
* Rep.NPoints, Rep.Z, Rep.PZ and Rep.PM are consistent and correct
* Rep.MergeDist is consistent with distance between clusters being merged
* clusters with minimal distance are merged at each step
* GetKClusters() correctly unpacks clusters for each K
NOTE: this algorithm correctly handle ties, i.e. situations where several
pairs of clusters have same intercluster distance, and we can't
unambiguously choose clusters to merge.
INPUT PARAMETERS
D - distance matrix, array[NPoints,NPoints], full matrix
is given (including both triangles and zeros on the
main diagonal)
XY - dataset matrix, array[NPoints,NF]
NPoints - dataset size
NF - number of features
Rep - clusterizer report
AHCAlgo - AHC algorithm:
* 0 - complete linkage
* 1 - single linkage
* 2 - unweighted average linkage
This function returns True on failure, False on success.
*************************************************************************/
static ae_bool testclusteringunit_errorsinmerges(/* Real */ ae_matrix* d,
/* Real */ ae_matrix* xy,
ae_int_t npoints,
ae_int_t nf,
ahcreport* rep,
ae_int_t ahcalgo,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix dm;
ae_matrix cm;
ae_vector clustersizes;
ae_vector clusterheights;
ae_vector b;
ae_vector x0;
ae_vector x1;
ae_bool bflag;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t i0;
ae_int_t i1;
ae_int_t c0;
ae_int_t c1;
ae_int_t s0;
ae_int_t s1;
double v;
ae_int_t t;
ae_int_t mergeidx;
ae_vector kidx;
ae_vector kidxz;
ae_int_t currentelement;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&dm, 0, sizeof(dm));
memset(&cm, 0, sizeof(cm));
memset(&clustersizes, 0, sizeof(clustersizes));
memset(&clusterheights, 0, sizeof(clusterheights));
memset(&b, 0, sizeof(b));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&kidx, 0, sizeof(kidx));
memset(&kidxz, 0, sizeof(kidxz));
ae_matrix_init(&dm, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&cm, 0, 0, DT_INT, _state, ae_true);
ae_vector_init(&clustersizes, 0, DT_INT, _state, ae_true);
ae_vector_init(&clusterheights, 0, DT_INT, _state, ae_true);
ae_vector_init(&b, 0, DT_BOOL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&kidx, 0, DT_INT, _state, ae_true);
ae_vector_init(&kidxz, 0, DT_INT, _state, ae_true);
ae_assert(ahcalgo!=3, "integrity error", _state);
result = ae_false;
ae_vector_set_length(&x0, nf, _state);
ae_vector_set_length(&x1, nf, _state);
/*
* Basic checks:
* * positive completion code
* * sizes of arrays
* * Rep.P is correct permutation
* * Rep.Z contains correct cluster indexes
* * Rep.PZ is consistent with Rep.P/Rep.Z
* * Rep.PM contains consistent indexes
* * GetKClusters() for K=NPoints
*/
bflag = ae_false;
bflag = bflag||rep->terminationtype<=0;
if( bflag )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
bflag = bflag||rep->npoints!=npoints;
bflag = (bflag||rep->z.rows!=npoints-1)||(npoints>1&&rep->z.cols!=2);
bflag = (bflag||rep->pz.rows!=npoints-1)||(npoints>1&&rep->pz.cols!=2);
bflag = (bflag||rep->pm.rows!=npoints-1)||(npoints>1&&rep->pm.cols!=6);
bflag = bflag||rep->mergedist.cnt!=npoints-1;
bflag = bflag||rep->p.cnt!=npoints;
if( bflag )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
ae_vector_set_length(&b, npoints, _state);
for(i=0; i<=npoints-1; i++)
{
b.ptr.p_bool[i] = ae_false;
}
for(i=0; i<=npoints-1; i++)
{
if( (rep->p.ptr.p_int[i]<0||rep->p.ptr.p_int[i]>=npoints)||b.ptr.p_bool[rep->p.ptr.p_int[i]] )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
b.ptr.p_bool[rep->p.ptr.p_int[i]] = ae_true;
}
for(i=0; i<=npoints-2; i++)
{
if( (rep->z.ptr.pp_int[i][0]<0||rep->z.ptr.pp_int[i][0]>=rep->z.ptr.pp_int[i][1])||rep->z.ptr.pp_int[i][1]>=npoints+i )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
if( (rep->pz.ptr.pp_int[i][0]<0||rep->pz.ptr.pp_int[i][0]>=rep->pz.ptr.pp_int[i][1])||rep->pz.ptr.pp_int[i][1]>=npoints+i )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
for(i=0; i<=npoints-2; i++)
{
c0 = rep->z.ptr.pp_int[i][0];
c1 = rep->z.ptr.pp_int[i][1];
s0 = rep->pz.ptr.pp_int[i][0];
s1 = rep->pz.ptr.pp_int[i][1];
if( c0p.ptr.p_int[c0];
}
if( c1p.ptr.p_int[c1];
}
if( c0!=s0||c1!=s1 )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
clusterizergetkclusters(rep, npoints, &kidx, &kidxz, _state);
if( kidx.cnt!=npoints||kidxz.cnt!=npoints )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=npoints-1; i++)
{
if( kidxz.ptr.p_int[i]!=i||kidx.ptr.p_int[i]!=i )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
/*
* Test description:
* * we generate (2*NPoints-1)x(2*NPoints-1) matrix of distances DM and
* (2*NPoints-1)xNPoints matrix of clusters CM (I-th row contains indexes
* of elements which belong to I-th cluster, negative indexes denote
* empty cells). Leading N*N square of DM is just a distance matrix,
* other elements are filled by some large number M (used to mark empty
* elements).
* * we replay all merges
* * every time we merge clusters I and J into K, we:
* * check that distance between I and J is equal to the smallest
* element of DM (note: we account for rounding errors when we
* decide on that)
* * check that distance is consistent with Rep.MergeDist
* * then, we enumerate all elements in clusters being merged,
* and check that after permutation their indexes fall into range
* prescribed by Rep.PM
* * fill K-th column/row of D by distances to cluster K
* * merge I-th and J-th rows of CM and store result into K-th row
* * clear DM and CM: fill I-th and J-th column/row of DM by large
* number M, fill I-th and J-th row of CM by -1.
*
* NOTE: DM is initialized by distance metric specific to AHC algorithm
* being used. CLINK, SLINK and average linkage use user-provided
* distance measure, say Euclidean one, without any modifications.
* Ward's method uses (and reports) squared and scaled Euclidean
* distances.
*/
ae_matrix_set_length(&dm, 2*npoints-1, 2*npoints-1, _state);
ae_matrix_set_length(&cm, 2*npoints-1, npoints, _state);
ae_vector_set_length(&clustersizes, 2*npoints-1, _state);
for(i=0; i<=2*npoints-2; i++)
{
for(j=0; j<=2*npoints-2; j++)
{
if( iptr.pp_double[i][j];
if( ahcalgo==4 )
{
dm.ptr.pp_double[i][j] = 0.5*ae_sqr(dm.ptr.pp_double[i][j], _state);
}
}
else
{
dm.ptr.pp_double[i][j] = ae_maxrealnumber;
}
}
}
for(i=0; i<=2*npoints-2; i++)
{
for(j=0; j<=npoints-1; j++)
{
cm.ptr.pp_int[i][j] = -1;
}
}
for(i=0; i<=npoints-1; i++)
{
cm.ptr.pp_int[i][0] = i;
clustersizes.ptr.p_int[i] = 1;
}
for(i=npoints; i<=2*npoints-2; i++)
{
clustersizes.ptr.p_int[i] = 0;
}
ae_vector_set_length(&clusterheights, 2*npoints-1, _state);
for(i=0; i<=npoints-1; i++)
{
clusterheights.ptr.p_int[i] = 0;
}
for(mergeidx=0; mergeidx<=npoints-2; mergeidx++)
{
/*
* Check that clusters with minimum distance are merged,
* and that MergeDist is consistent with results.
*
* NOTE: we do not check for specific cluster indexes,
* because it is possible to have a tie. We just
* check that distance between clusters is a true
* minimum over all possible clusters.
*/
v = ae_maxrealnumber;
for(i=0; i<=2*npoints-2; i++)
{
for(j=0; j<=2*npoints-2; j++)
{
if( i!=j )
{
v = ae_minreal(v, dm.ptr.pp_double[i][j], _state);
}
}
}
c0 = rep->z.ptr.pp_int[mergeidx][0];
c1 = rep->z.ptr.pp_int[mergeidx][1];
if( ae_fp_greater(dm.ptr.pp_double[c0][c1],v+10000*ae_machineepsilon) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
if( ae_fp_greater(rep->mergedist.ptr.p_double[mergeidx],v+10000*ae_machineepsilon) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
/*
* Check that indexes of elements fall into range prescribed by Rep.PM,
* and Rep.PM correctly described merge operation
*/
s0 = clustersizes.ptr.p_int[c0];
s1 = clustersizes.ptr.p_int[c1];
for(j=0; j<=clustersizes.ptr.p_int[c0]-1; j++)
{
if( rep->p.ptr.p_int[cm.ptr.pp_int[c0][j]]pm.ptr.pp_int[mergeidx][0]||rep->p.ptr.p_int[cm.ptr.pp_int[c0][j]]>rep->pm.ptr.pp_int[mergeidx][1] )
{
/*
* Element falls outside of range described by PM
*/
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
for(j=0; j<=clustersizes.ptr.p_int[c1]-1; j++)
{
if( rep->p.ptr.p_int[cm.ptr.pp_int[c1][j]]pm.ptr.pp_int[mergeidx][2]||rep->p.ptr.p_int[cm.ptr.pp_int[c1][j]]>rep->pm.ptr.pp_int[mergeidx][3] )
{
/*
* Element falls outside of range described by PM
*/
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
if( (rep->pm.ptr.pp_int[mergeidx][1]-rep->pm.ptr.pp_int[mergeidx][0]!=s0-1||rep->pm.ptr.pp_int[mergeidx][3]-rep->pm.ptr.pp_int[mergeidx][2]!=s1-1)||rep->pm.ptr.pp_int[mergeidx][2]!=rep->pm.ptr.pp_int[mergeidx][1]+1 )
{
/*
* Cluster size (as given by PM) is inconsistent with its actual size.
*/
result = ae_true;
ae_frame_leave(_state);
return result;
}
if( rep->pm.ptr.pp_int[mergeidx][4]!=clusterheights.ptr.p_int[rep->z.ptr.pp_int[mergeidx][0]]||rep->pm.ptr.pp_int[mergeidx][5]!=clusterheights.ptr.p_int[rep->z.ptr.pp_int[mergeidx][1]] )
{
/*
* Heights of subdendrograms as returned by PM are inconsistent with heights
* calculated by us.
*/
result = ae_true;
ae_frame_leave(_state);
return result;
}
/*
* Update cluster heights
*/
clusterheights.ptr.p_int[mergeidx+npoints] = ae_maxint(clusterheights.ptr.p_int[rep->z.ptr.pp_int[mergeidx][0]], clusterheights.ptr.p_int[rep->z.ptr.pp_int[mergeidx][1]], _state)+1;
/*
* Update CM
*/
t = 0;
for(j=0; j<=clustersizes.ptr.p_int[rep->z.ptr.pp_int[mergeidx][0]]-1; j++)
{
cm.ptr.pp_int[npoints+mergeidx][t] = cm.ptr.pp_int[rep->z.ptr.pp_int[mergeidx][0]][j];
t = t+1;
}
for(j=0; j<=clustersizes.ptr.p_int[rep->z.ptr.pp_int[mergeidx][1]]-1; j++)
{
cm.ptr.pp_int[npoints+mergeidx][t] = cm.ptr.pp_int[rep->z.ptr.pp_int[mergeidx][1]][j];
t = t+1;
}
clustersizes.ptr.p_int[npoints+mergeidx] = t;
clustersizes.ptr.p_int[rep->z.ptr.pp_int[mergeidx][0]] = 0;
clustersizes.ptr.p_int[rep->z.ptr.pp_int[mergeidx][1]] = 0;
/*
* Update distance matrix D
*/
for(i=0; i<=2*npoints-2; i++)
{
/*
* "Remove" columns/rows corresponding to clusters being merged
*/
dm.ptr.pp_double[i][rep->z.ptr.pp_int[mergeidx][0]] = ae_maxrealnumber;
dm.ptr.pp_double[i][rep->z.ptr.pp_int[mergeidx][1]] = ae_maxrealnumber;
dm.ptr.pp_double[rep->z.ptr.pp_int[mergeidx][0]][i] = ae_maxrealnumber;
dm.ptr.pp_double[rep->z.ptr.pp_int[mergeidx][1]][i] = ae_maxrealnumber;
}
for(i=0; i<=npoints+mergeidx-1; i++)
{
if( clustersizes.ptr.p_int[i]>0 )
{
/*
* Calculate column/row corresponding to new cluster
*/
if( ahcalgo==0 )
{
/*
* Calculate distance between clusters I and NPoints+MergeIdx for CLINK
*/
v = 0.0;
for(i0=0; i0<=clustersizes.ptr.p_int[i]-1; i0++)
{
for(i1=0; i1<=clustersizes.ptr.p_int[npoints+mergeidx]-1; i1++)
{
v = ae_maxreal(v, d->ptr.pp_double[cm.ptr.pp_int[i][i0]][cm.ptr.pp_int[npoints+mergeidx][i1]], _state);
}
}
}
if( ahcalgo==1 )
{
/*
* Calculate distance between clusters I and NPoints+MergeIdx for SLINK
*/
v = ae_maxrealnumber;
for(i0=0; i0<=clustersizes.ptr.p_int[i]-1; i0++)
{
for(i1=0; i1<=clustersizes.ptr.p_int[npoints+mergeidx]-1; i1++)
{
v = ae_minreal(v, d->ptr.pp_double[cm.ptr.pp_int[i][i0]][cm.ptr.pp_int[npoints+mergeidx][i1]], _state);
}
}
}
if( ahcalgo==2 )
{
/*
* Calculate distance between clusters I and NPoints+MergeIdx for unweighted average
*/
v = 0.0;
t = 0;
for(i0=0; i0<=clustersizes.ptr.p_int[i]-1; i0++)
{
for(i1=0; i1<=clustersizes.ptr.p_int[npoints+mergeidx]-1; i1++)
{
v = v+d->ptr.pp_double[cm.ptr.pp_int[i][i0]][cm.ptr.pp_int[npoints+mergeidx][i1]];
t = t+1;
}
}
v = v/t;
}
if( ahcalgo==3 )
{
ae_assert(ae_false, "Assertion failed", _state);
}
if( ahcalgo==4 )
{
/*
* Calculate distance between clusters I and NPoints+MergeIdx for Ward's method:
* * X0 = center of mass for cluster I
* * X1 = center of mass for cluster NPoints+MergeIdx
* * S0 = size of cluster I
* * S1 = size of cluster NPoints+MergeIdx
* * distance between clusters is S0*S1/(S0+S1)*|X0-X1|^2
*
*/
for(j=0; j<=nf-1; j++)
{
x0.ptr.p_double[j] = 0.0;
x1.ptr.p_double[j] = 0.0;
}
for(i0=0; i0<=clustersizes.ptr.p_int[i]-1; i0++)
{
for(j=0; j<=nf-1; j++)
{
x0.ptr.p_double[j] = x0.ptr.p_double[j]+xy->ptr.pp_double[cm.ptr.pp_int[i][i0]][j]/clustersizes.ptr.p_int[i];
}
}
for(i1=0; i1<=clustersizes.ptr.p_int[npoints+mergeidx]-1; i1++)
{
for(j=0; j<=nf-1; j++)
{
x1.ptr.p_double[j] = x1.ptr.p_double[j]+xy->ptr.pp_double[cm.ptr.pp_int[npoints+mergeidx][i1]][j]/clustersizes.ptr.p_int[npoints+mergeidx];
}
}
v = 0.0;
for(j=0; j<=nf-1; j++)
{
v = v+ae_sqr(x0.ptr.p_double[j]-x1.ptr.p_double[j], _state);
}
v = v*clustersizes.ptr.p_int[i]*clustersizes.ptr.p_int[npoints+mergeidx]/(clustersizes.ptr.p_int[i]+clustersizes.ptr.p_int[npoints+mergeidx]);
}
dm.ptr.pp_double[i][npoints+mergeidx] = v;
dm.ptr.pp_double[npoints+mergeidx][i] = v;
}
}
/*
* Check that GetKClusters() correctly unpacks clusters for K=NPoints-(MergeIdx+1):
* * check lengths of arays
* * check consistency of CIdx/CZ parameters
* * scan clusters (CZ parameter), for each cluster scan CM matrix which stores
* cluster elements (according to our replay of merges), for each element of
* the current cluster check that CIdx array correctly reflects its status.
*/
k = npoints-(mergeidx+1);
clusterizergetkclusters(rep, k, &kidx, &kidxz, _state);
if( kidx.cnt!=npoints||kidxz.cnt!=k )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=k-2; i++)
{
if( (kidxz.ptr.p_int[i]<0||kidxz.ptr.p_int[i]>=kidxz.ptr.p_int[i+1])||kidxz.ptr.p_int[i+1]>2*npoints-2 )
{
/*
* CZ is inconsistent
*/
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
for(i=0; i<=npoints-1; i++)
{
if( kidx.ptr.p_int[i]<0||kidx.ptr.p_int[i]>=k )
{
/*
* CIdx is inconsistent
*/
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
for(i=0; i<=k-1; i++)
{
for(j=0; j<=clustersizes.ptr.p_int[kidxz.ptr.p_int[i]]-1; j++)
{
currentelement = cm.ptr.pp_int[kidxz.ptr.p_int[i]][j];
if( kidx.ptr.p_int[currentelement]!=i )
{
/*
* We've found element which belongs to I-th cluster (according to CM
* matrix, which reflects current status of agglomerative clustering),
* but this element does not belongs to I-th cluster according to
* results of ClusterizerGetKClusters()
*/
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This procedure is a reference version of KMeansUpdateDistances().
INPUT PARAMETERS:
XY - dataset, array [0..NPoints-1,0..NVars-1].
NPoints - dataset size, NPoints>=K
NVars - number of variables, NVars>=1
CT - matrix of centers, centers are stored in rows
K - number of centers, K>=1
XYC - preallocated output buffer
XYDist2 - preallocated output buffer
OUTPUT PARAMETERS:
XYC - new assignment of points to centers
XYDist2 - squared distances
-- ALGLIB --
Copyright 21.01.2015 by Bochkanov Sergey
*************************************************************************/
static void testclusteringunit_kmeansreferenceupdatedistances(/* Real */ ae_matrix* xy,
ae_int_t npoints,
ae_int_t nvars,
/* Real */ ae_matrix* ct,
ae_int_t k,
/* Integer */ ae_vector* xyc,
/* Real */ ae_vector* xydist2,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_int_t cclosest;
double dclosest;
double v;
ae_vector tmp;
ae_frame_make(_state, &_frame_block);
memset(&tmp, 0, sizeof(tmp));
ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
ae_vector_set_length(&tmp, nvars, _state);
for(i=0; i<=npoints-1; i++)
{
cclosest = -1;
dclosest = ae_maxrealnumber;
for(j=0; j<=k-1; j++)
{
ae_v_move(&tmp.ptr.p_double[0], 1, &xy->ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
ae_v_sub(&tmp.ptr.p_double[0], 1, &ct->ptr.pp_double[j][0], 1, ae_v_len(0,nvars-1));
v = ae_v_dotproduct(&tmp.ptr.p_double[0], 1, &tmp.ptr.p_double[0], 1, ae_v_len(0,nvars-1));
if( ae_fp_less(v,dclosest) )
{
cclosest = j;
dclosest = v;
}
}
ae_assert(cclosest>=0, "KMeansUpdateDistances: internal error", _state);
xyc->ptr.p_int[i] = cclosest;
xydist2->ptr.p_double[i] = dclosest;
}
ae_frame_leave(_state);
}
static ae_int_t testdforestunit_algomax = 0;
static ae_int_t testdforestunit_splitmax = 2;
static void testdforestunit_testprocessing(ae_bool* err, ae_state *_state);
static void testdforestunit_basictest1(ae_bool* err, ae_state *_state);
static void testdforestunit_basictest2(ae_bool* err, ae_state *_state);
static void testdforestunit_basictest3(ae_bool* err, ae_state *_state);
static void testdforestunit_basictest4(ae_bool* err, ae_state *_state);
static void testdforestunit_basictest5(ae_bool* err, ae_state *_state);
static void testdforestunit_basictestrandom(ae_bool* err,
ae_state *_state);
static void testdforestunit_basictestallsame(ae_bool* err,
ae_state *_state);
static void testdforestunit_testcompression(ae_bool* err,
ae_state *_state);
static void testdforestunit_testimportance(ae_bool* err, ae_state *_state);
static void testdforestunit_unsetdf(decisionforest* df, ae_state *_state);
static void testdforestunit_randomlyrearrange(/* Real */ ae_matrix* xy,
ae_int_t npoints,
ae_int_t nvars,
hqrndstate* rs,
ae_state *_state);
ae_bool testdforest(ae_bool silent, ae_state *_state)
{
ae_bool waserrors;
ae_bool basicerrors;
ae_bool procerrors;
ae_bool compressionerrors;
ae_bool importanceerrors;
ae_bool result;
/*
* Primary settings
*/
basicerrors = ae_false;
procerrors = ae_false;
compressionerrors = ae_false;
importanceerrors = ae_false;
waserrors = ae_false;
/*
* Tests
*/
testdforestunit_testprocessing(&procerrors, _state);
testdforestunit_basictest1(&basicerrors, _state);
testdforestunit_basictest2(&basicerrors, _state);
testdforestunit_basictest3(&basicerrors, _state);
testdforestunit_basictest4(&basicerrors, _state);
testdforestunit_basictest5(&basicerrors, _state);
testdforestunit_basictestrandom(&basicerrors, _state);
testdforestunit_basictestallsame(&basicerrors, _state);
testdforestunit_testcompression(&compressionerrors, _state);
testdforestunit_testimportance(&importanceerrors, _state);
/*
* Final report
*/
waserrors = ((basicerrors||procerrors)||compressionerrors)||importanceerrors;
if( !silent )
{
printf("RANDOM FOREST TEST\n");
printf("TOTAL RESULTS: ");
if( !waserrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* PROCESSING FUNCTIONS: ");
if( !procerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* BASIC TESTS: ");
if( !basicerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* COMPRESSION TESTS: ");
if( !compressionerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* VARIABLE IMPORTANCE TESTS: ");
if( !importanceerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST SUMMARY: FAILED\n");
}
else
{
printf("TEST SUMMARY: PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
return result;
}
/*************************************************************************
Processing functions test
*************************************************************************/
static void testdforestunit_testprocessing(ae_bool* err, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t nvars;
ae_int_t nclasses;
ae_int_t ntrees;
ae_int_t foresttype;
decisionforest df1;
decisionforest df2;
decisionforestbuilder builder;
dfreport rep;
decisionforestbuffer buf;
ae_int_t npoints;
ae_matrix xy;
ae_int_t pass;
ae_int_t passcount;
ae_int_t i;
ae_int_t j;
ae_bool allsame;
ae_vector x1;
ae_vector x2;
ae_vector y1;
ae_vector y2;
double v;
hqrndstate rs;
ae_frame_make(_state, &_frame_block);
memset(&df1, 0, sizeof(df1));
memset(&df2, 0, sizeof(df2));
memset(&builder, 0, sizeof(builder));
memset(&rep, 0, sizeof(rep));
memset(&buf, 0, sizeof(buf));
memset(&xy, 0, sizeof(xy));
memset(&x1, 0, sizeof(x1));
memset(&x2, 0, sizeof(x2));
memset(&y1, 0, sizeof(y1));
memset(&y2, 0, sizeof(y2));
memset(&rs, 0, sizeof(rs));
_decisionforest_init(&df1, _state, ae_true);
_decisionforest_init(&df2, _state, ae_true);
_decisionforestbuilder_init(&builder, _state, ae_true);
_dfreport_init(&rep, _state, ae_true);
_decisionforestbuffer_init(&buf, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
passcount = 100;
hqrndrandomize(&rs, _state);
/*
* Main cycle
*/
for(pass=1; pass<=passcount; pass++)
{
/*
* initialize parameters
*/
nvars = 1+hqrnduniformi(&rs, 5, _state);
nclasses = 1+hqrnduniformi(&rs, 3, _state);
ntrees = 1+hqrnduniformi(&rs, 4, _state);
foresttype = hqrnduniformi(&rs, 3, _state);
/*
* Initialize arrays and data
*/
npoints = 10+ae_randominteger(50, _state);
ae_vector_set_length(&x1, nvars, _state);
ae_vector_set_length(&x2, nvars, _state);
ae_vector_set_length(&y1, nclasses, _state);
ae_vector_set_length(&y2, nclasses, _state);
ae_matrix_set_length(&xy, npoints, nvars+1, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
if( j%2==0 )
{
xy.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
else
{
xy.ptr.pp_double[i][j] = (double)(ae_randominteger(2, _state));
}
}
if( nclasses==1 )
{
xy.ptr.pp_double[i][nvars] = 2*ae_randomreal(_state)-1;
}
else
{
xy.ptr.pp_double[i][nvars] = (double)(ae_randominteger(nclasses, _state));
}
}
/*
* create forest
*/
dfbuildercreate(&builder, _state);
dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state);
dfbuildersetrdfalgo(&builder, ae_randominteger(testdforestunit_algomax+1, _state), _state);
dfbuildersetrdfsplitstrength(&builder, ae_randominteger(testdforestunit_splitmax+1, _state), _state);
if( foresttype==0 )
{
/*
* Build uncompressed random forest
*/
dfbuilderbuildrandomforest(&builder, ntrees, &df1, &rep, _state);
}
if( foresttype==1 )
{
/*
* Build uncompressed random forest, then perform 16-bit compression
*/
dfbuilderbuildrandomforest(&builder, ntrees, &df1, &rep, _state);
dfbinarycompression(&df1, _state);
}
if( foresttype==2 )
{
/*
* Build uncompressed random forest, then perform 8-bit compression
*/
dfbuilderbuildrandomforest(&builder, ntrees, &df1, &rep, _state);
dfbinarycompression8(&df1, _state);
}
dfcreatebuffer(&df1, &buf, _state);
/*
* Same inputs leads to same outputs
*/
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
for(i=0; i<=nclasses-1; i++)
{
y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
dfprocess(&df1, &x1, &y1, _state);
dfprocess(&df1, &x2, &y2, _state);
allsame = ae_true;
for(i=0; i<=nclasses-1; i++)
{
allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]);
}
*err = *err||!allsame;
/*
* DFProcess0 works as expected
*/
ae_vector_set_length(&x1, nvars, _state);
ae_vector_set_length(&x2, nvars, _state);
ae_vector_set_length(&y1, nclasses, _state);
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = hqrndnormal(&rs, _state);
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
for(i=0; i<=nclasses-1; i++)
{
y1.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
dfprocess(&df1, &x1, &y1, _state);
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y1.ptr.p_double[0]-dfprocess0(&df1, &x2, _state), _state),100*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:225");
/*
* DFClassify works as expected
*/
ae_vector_set_length(&x1, nvars, _state);
ae_vector_set_length(&x2, nvars, _state);
ae_vector_set_length(&y1, nclasses, _state);
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = hqrndnormal(&rs, _state);
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
if( nclasses>1 )
{
for(i=0; i<=nclasses-1; i++)
{
y1.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
dfprocess(&df1, &x1, &y1, _state);
j = dfclassify(&df1, &x2, _state);
for(i=0; i<=nclasses-1; i++)
{
ae_set_error_flag(err, ae_fp_greater(y1.ptr.p_double[i],y1.ptr.p_double[j]), __FILE__, __LINE__, "testdforestunit.ap:248");
}
}
else
{
ae_set_error_flag(err, dfclassify(&df1, &x2, _state)!=-1, __FILE__, __LINE__, "testdforestunit.ap:251");
}
/*
* DFTsProcess() works as expected
*/
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
for(i=0; i<=nclasses-1; i++)
{
y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
dfprocess(&df1, &x1, &y1, _state);
dftsprocess(&df1, &buf, &x2, &y2, _state);
allsame = ae_true;
for(i=0; i<=nclasses-1; i++)
{
allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]);
}
ae_set_error_flag(err, !allsame, __FILE__, __LINE__, "testdforestunit.ap:272");
/*
* Same inputs on original forest leads to same outputs
* on copy created using DFCopy
*/
testdforestunit_unsetdf(&df2, _state);
dfcopy(&df1, &df2, _state);
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
for(i=0; i<=nclasses-1; i++)
{
y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
dfprocess(&df1, &x1, &y1, _state);
dfprocess(&df2, &x2, &y2, _state);
allsame = ae_true;
for(i=0; i<=nclasses-1; i++)
{
allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]);
}
*err = *err||!allsame;
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(dfprocess0(&df1, &x1, _state)-dfprocess0(&df2, &x2, _state), _state),100*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:303");
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
ae_set_error_flag(err, dfclassify(&df1, &x1, _state)!=dfclassify(&df2, &x2, _state), __FILE__, __LINE__, "testdforestunit.ap:309");
/*
* Same inputs on original forest leads to same outputs
* on copy created using DFSerialize
*/
testdforestunit_unsetdf(&df2, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
dfalloc(&_local_serializer, &df1, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
dfserialize(&_local_serializer, &df1, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
dfunserialize(&_local_serializer, &df2, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
for(i=0; i<=nclasses-1; i++)
{
y1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
y2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
dfprocess(&df1, &x1, &y1, _state);
dfprocess(&df2, &x2, &y2, _state);
allsame = ae_true;
for(i=0; i<=nclasses-1; i++)
{
allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]);
}
*err = *err||!allsame;
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(dfprocess0(&df1, &x1, _state)-dfprocess0(&df2, &x2, _state), _state),100*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:339");
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
ae_set_error_flag(err, dfclassify(&df1, &x1, _state)!=dfclassify(&df2, &x2, _state), __FILE__, __LINE__, "testdforestunit.ap:345");
/*
* Normalization properties
*/
if( nclasses>1 )
{
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
dfprocess(&df1, &x1, &y1, _state);
v = (double)(0);
for(i=0; i<=nclasses-1; i++)
{
v = v+y1.ptr.p_double[i];
*err = *err||ae_fp_less(y1.ptr.p_double[i],(double)(0));
}
*err = *err||ae_fp_greater(ae_fabs(v-1, _state),1000*ae_machineepsilon);
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Basic test: one-tree uncompressed forest built using full sample must
remember all training cases.
Special relaxed testing is performed for compressed forests.
*************************************************************************/
static void testdforestunit_basictest1(ae_bool* err, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t pass;
ae_matrix xy;
ae_int_t npoints;
ae_int_t ntrees;
ae_int_t i;
ae_int_t j;
double s;
ae_int_t info;
decisionforestbuilder builder;
decisionforest df;
decisionforest df1;
ae_vector x;
ae_vector y;
dfreport rep;
ae_int_t nvars;
ae_int_t nclasses;
ae_int_t passcount;
hqrndstate rs;
double tol16;
double tol8;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
memset(&builder, 0, sizeof(builder));
memset(&df, 0, sizeof(df));
memset(&df1, 0, sizeof(df1));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&rep, 0, sizeof(rep));
memset(&rs, 0, sizeof(rs));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_decisionforestbuilder_init(&builder, _state, ae_true);
_decisionforest_init(&df, _state, ae_true);
_decisionforest_init(&df1, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
_dfreport_init(&rep, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
tol16 = 0.0001;
tol8 = 0.01;
/*
* Test uncompressed forest
*/
passcount = 10;
for(nvars=1; nvars<=4; nvars++)
{
for(nclasses=1; nclasses<=3; nclasses++)
{
for(pass=0; pass<=passcount-1; pass++)
{
/*
* select number of points
*/
if( pass<3&&passcount>3 )
{
npoints = 1+pass;
}
else
{
npoints = 100+hqrnduniformi(&rs, 100, _state);
}
/*
* Prepare task
*/
ae_matrix_set_length(&xy, npoints, nvars+1, _state);
ae_vector_set_length(&x, nvars, _state);
ae_vector_set_length(&y, nclasses, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = (double)(i);
for(j=1; j<=nvars-1; j++)
{
xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
if( nclasses>1 )
{
xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nclasses, _state));
}
else
{
xy.ptr.pp_double[i][nvars] = hqrndnormal(&rs, _state);
}
}
/*
* Train
*
* NOTE: we also test obsolete forest construction functions
*/
ae_assert(passcount>=2, "RDF: test integrity failed", _state);
ntrees = 1;
if( pass>0 )
{
/*
* Test new interface
*/
dfbuildercreate(&builder, _state);
dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state);
dfbuildersetsubsampleratio(&builder, 1.0, _state);
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
dfbuildersetrndvars(&builder, nvars, _state);
}
else
{
dfbuildersetrndvarsratio(&builder, 1.0, _state);
}
dfbuildersetrdfalgo(&builder, ae_randominteger(testdforestunit_algomax+1, _state), _state);
dfbuildersetrdfsplitstrength(&builder, ae_randominteger(testdforestunit_splitmax+1, _state), _state);
dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state);
}
else
{
/*
* Test old interface
*/
if( hqrnduniformi(&rs, 2, _state)==0 )
{
dfbuildrandomdecisionforest(&xy, npoints, nvars, nclasses, ntrees, 1.0, &info, &df, &rep, _state);
}
else
{
dfbuildrandomdecisionforestx1(&xy, npoints, nvars, nclasses, ntrees, 1, 1.0, &info, &df, &rep, _state);
}
if( info<=0 )
{
ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testdforestunit.ap:467");
ae_frame_leave(_state);
return;
}
}
/*
* Test
*/
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.rmserror, _state),1.0E-9), __FILE__, __LINE__, "testdforestunit.ap:475");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgerror, _state),1.0E-9), __FILE__, __LINE__, "testdforestunit.ap:476");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgrelerror, _state),1.0E-9), __FILE__, __LINE__, "testdforestunit.ap:477");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.relclserror, _state),(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:478");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgce, _state),(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:479");
for(i=0; i<=npoints-1; i++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xy.ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
dfprocess(&df, &x, &y, _state);
if( nclasses>1 )
{
/*
* Checks for classification tasks
*/
s = (double)(0);
for(j=0; j<=nclasses-1; j++)
{
ae_set_error_flag(err, ae_fp_less(y.ptr.p_double[j],(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:492");
s = s+y.ptr.p_double[j];
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(s-1, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:495");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[ae_round(xy.ptr.pp_double[i][nvars], _state)]-1, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:496");
}
else
{
/*
* Regression problem
*/
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[0]-xy.ptr.pp_double[i][nvars], _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:503");
}
}
}
}
}
/*
* Test compressed forest
*/
nvars = 1;
npoints = 100;
for(nclasses=1; nclasses<=3; nclasses++)
{
for(pass=0; pass<=passcount-1; pass++)
{
/*
* Dataset
*/
ae_matrix_set_length(&xy, npoints, nvars+1, _state);
ae_vector_set_length(&x, nvars, _state);
ae_vector_set_length(&y, nclasses, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = (double)(i);
if( nclasses>1 )
{
xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nclasses, _state));
}
else
{
xy.ptr.pp_double[i][nvars] = hqrnduniformr(&rs, _state)-0.5;
}
}
/*
* Train
*/
ntrees = 1;
dfbuildercreate(&builder, _state);
dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state);
dfbuildersetsubsampleratio(&builder, 1.0, _state);
dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state);
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.rmserror, _state),1.0E-9), __FILE__, __LINE__, "testdforestunit.ap:541");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgerror, _state),1.0E-9), __FILE__, __LINE__, "testdforestunit.ap:542");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgrelerror, _state),1.0E-9), __FILE__, __LINE__, "testdforestunit.ap:543");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.relclserror, _state),(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:544");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgce, _state),(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:545");
/*
* Test 16-bit compression
*/
dfcopy(&df, &df1, _state);
dfbinarycompression(&df1, _state);
for(i=0; i<=npoints-1; i++)
{
x.ptr.p_double[0] = xy.ptr.pp_double[i][0];
dfprocess(&df1, &x, &y, _state);
if( nclasses>1 )
{
/*
* Checks for classification tasks
*/
s = (double)(0);
for(j=0; j<=nclasses-1; j++)
{
ae_set_error_flag(err, ae_fp_less(y.ptr.p_double[j],(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:564");
s = s+y.ptr.p_double[j];
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(s-1, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:567");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[ae_round(xy.ptr.pp_double[i][nvars], _state)]-1, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:568");
}
else
{
/*
* Regression problem
*/
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[0]-xy.ptr.pp_double[i][nvars], _state),tol16), __FILE__, __LINE__, "testdforestunit.ap:575");
}
}
/*
* Test 8-bit compression
*/
dfcopy(&df, &df1, _state);
dfbinarycompression8(&df1, _state);
for(i=0; i<=npoints-1; i++)
{
x.ptr.p_double[0] = xy.ptr.pp_double[i][0];
dfprocess(&df1, &x, &y, _state);
if( nclasses>1 )
{
/*
* Checks for classification tasks
*/
s = (double)(0);
for(j=0; j<=nclasses-1; j++)
{
ae_set_error_flag(err, ae_fp_less(y.ptr.p_double[j],(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:596");
s = s+y.ptr.p_double[j];
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(s-1, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:599");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[ae_round(xy.ptr.pp_double[i][nvars], _state)]-1, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:600");
}
else
{
/*
* Regression problem
*/
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[0]-xy.ptr.pp_double[i][nvars], _state),tol8), __FILE__, __LINE__, "testdforestunit.ap:607");
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Basic test: tests generalization ability on a simple noisy classification
task:
* 00.25 - P(class=0)=0
*************************************************************************/
static void testdforestunit_basictest3(ae_bool* err, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t pass;
ae_int_t passcount;
ae_matrix xy;
ae_int_t npoints;
ae_int_t ntrees;
ae_int_t i;
ae_int_t j;
ae_int_t info;
decisionforestbuilder builder;
decisionforest df;
ae_vector x;
ae_vector y;
dfreport rep;
ae_int_t testgridsize;
double r;
hqrndstate rs;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
memset(&builder, 0, sizeof(builder));
memset(&df, 0, sizeof(df));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&rep, 0, sizeof(rep));
memset(&rs, 0, sizeof(rs));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_decisionforestbuilder_init(&builder, _state, ae_true);
_decisionforest_init(&df, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
_dfreport_init(&rep, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
passcount = 2;
testgridsize = 50;
for(pass=0; pass<=passcount-1; pass++)
{
/*
* select npoints and ntrees
*/
npoints = 2000;
ntrees = 100;
/*
* Prepare task
*/
ae_matrix_set_length(&xy, npoints, 3, _state);
ae_vector_set_length(&x, 2, _state);
ae_vector_set_length(&y, 2, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = 2*hqrnduniformr(&rs, _state)-1;
xy.ptr.pp_double[i][1] = 2*hqrnduniformr(&rs, _state)-1;
if( ae_fp_less_eq(ae_sqr(xy.ptr.pp_double[i][0], _state)+ae_sqr(xy.ptr.pp_double[i][1], _state),0.25) )
{
xy.ptr.pp_double[i][2] = (double)(0);
}
else
{
xy.ptr.pp_double[i][2] = (double)(1);
}
}
/*
* Build forest
*
* NOTE: we also test obsolete forest construction functions
*/
ae_assert(passcount>=2, "RDF: test integrity failed", _state);
if( pass>0 )
{
/*
* Test new interface
*/
dfbuildercreate(&builder, _state);
dfbuildersetdataset(&builder, &xy, npoints, 2, 2, _state);
dfbuildersetsubsampleratio(&builder, 0.10, _state);
dfbuildersetrdfalgo(&builder, ae_randominteger(testdforestunit_algomax+1, _state), _state);
dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state);
}
else
{
/*
* Test old interface
*/
if( hqrnduniformi(&rs, 2, _state)==0 )
{
dfbuildrandomdecisionforest(&xy, npoints, 2, 2, ntrees, 0.10, &info, &df, &rep, _state);
}
else
{
dfbuildrandomdecisionforestx1(&xy, npoints, 2, 2, ntrees, 1, 0.10, &info, &df, &rep, _state);
}
if( info<=0 )
{
ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testdforestunit.ap:806");
ae_frame_leave(_state);
return;
}
}
/*
* Test
*/
for(i=-testgridsize/2; i<=testgridsize/2; i++)
{
for(j=-testgridsize/2; j<=testgridsize/2; j++)
{
x.ptr.p_double[0] = (double)i/(double)(testgridsize/2);
x.ptr.p_double[1] = (double)j/(double)(testgridsize/2);
dfprocess(&df, &x, &y, _state);
/*
* Test for basic properties
*/
ae_set_error_flag(err, ae_fp_less(y.ptr.p_double[0],(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:824");
ae_set_error_flag(err, ae_fp_less(y.ptr.p_double[1],(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:825");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[0]+y.ptr.p_double[1]-1, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:826");
/*
* test for good correlation with results
*/
r = ae_sqrt(ae_sqr(x.ptr.p_double[0], _state)+ae_sqr(x.ptr.p_double[1], _state), _state);
if( ae_fp_less(r,0.66*0.5) )
{
ae_set_error_flag(err, ae_fp_less(y.ptr.p_double[0],0.66), __FILE__, __LINE__, "testdforestunit.ap:833");
}
if( ae_fp_greater(r,1.33*0.5) )
{
ae_set_error_flag(err, ae_fp_less(y.ptr.p_double[1],0.66), __FILE__, __LINE__, "testdforestunit.ap:835");
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Basic test: simple regression task without noise:
* |x|<1, |y|<1
* F(x,y) = x^2+y
*************************************************************************/
static void testdforestunit_basictest4(ae_bool* err, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t pass;
ae_int_t passcount;
ae_matrix xy;
ae_int_t npoints;
ae_int_t ntrees;
ae_int_t i;
ae_int_t j;
ae_int_t info;
decisionforest df;
ae_vector x;
ae_vector y;
dfreport rep;
ae_int_t testgridsize;
decisionforestbuilder builder;
double maxerr;
double avgerr;
ae_int_t cnt;
double ey;
hqrndstate rs;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
memset(&df, 0, sizeof(df));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&rep, 0, sizeof(rep));
memset(&builder, 0, sizeof(builder));
memset(&rs, 0, sizeof(rs));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_decisionforest_init(&df, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
_dfreport_init(&rep, _state, ae_true);
_decisionforestbuilder_init(&builder, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
passcount = 2;
testgridsize = 50;
for(pass=0; pass<=passcount-1; pass++)
{
/*
* select npoints and ntrees
*/
npoints = 5000;
ntrees = 100;
/*
* Prepare task
*/
ae_matrix_set_length(&xy, npoints, 3, _state);
ae_vector_set_length(&x, 2, _state);
ae_vector_set_length(&y, 1, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = 2*hqrnduniformr(&rs, _state)-1;
xy.ptr.pp_double[i][1] = 2*hqrnduniformr(&rs, _state)-1;
xy.ptr.pp_double[i][2] = ae_sqr(xy.ptr.pp_double[i][0], _state)+xy.ptr.pp_double[i][1];
}
/*
* Build forest
*
* NOTE: we also test obsolete forest construction functions
*/
ae_assert(passcount>=2, "RDF: test integrity failed", _state);
if( pass>0 )
{
/*
* Test new interface
*/
dfbuildercreate(&builder, _state);
dfbuildersetdataset(&builder, &xy, npoints, 2, 1, _state);
dfbuildersetsubsampleratio(&builder, 0.10, _state);
dfbuildersetrdfalgo(&builder, ae_randominteger(testdforestunit_algomax+1, _state), _state);
dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state);
}
else
{
/*
* Test old interface
*/
if( hqrnduniformi(&rs, 2, _state)==0 )
{
dfbuildrandomdecisionforest(&xy, npoints, 2, 1, ntrees, 0.10, &info, &df, &rep, _state);
}
else
{
dfbuildrandomdecisionforestx1(&xy, npoints, 2, 1, ntrees, 1, 0.10, &info, &df, &rep, _state);
}
if( info<=0 )
{
ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testdforestunit.ap:924");
ae_frame_leave(_state);
return;
}
}
/*
* Check report fields
*/
ae_set_error_flag(err, ae_fp_neq(rep.relclserror,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:932");
ae_set_error_flag(err, ae_fp_neq(rep.avgce,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:933");
ae_set_error_flag(err, ae_fp_neq(rep.oobrelclserror,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:934");
ae_set_error_flag(err, ae_fp_neq(rep.oobavgce,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:935");
ae_set_error_flag(err, ae_fp_greater_eq(rep.rmserror,rep.oobrmserror), __FILE__, __LINE__, "testdforestunit.ap:936");
ae_set_error_flag(err, ae_fp_greater_eq(rep.avgerror,rep.oobavgerror), __FILE__, __LINE__, "testdforestunit.ap:937");
ae_set_error_flag(err, ae_fp_greater_eq(rep.avgrelerror,rep.oobavgrelerror), __FILE__, __LINE__, "testdforestunit.ap:938");
ae_set_error_flag(err, ae_fp_greater(rep.oobrmserror,0.05), __FILE__, __LINE__, "testdforestunit.ap:939");
ae_set_error_flag(err, ae_fp_greater(rep.oobavgerror,0.05), __FILE__, __LINE__, "testdforestunit.ap:940");
ae_set_error_flag(err, ae_fp_less(rep.oobrmserror,0.001), __FILE__, __LINE__, "testdforestunit.ap:941");
ae_set_error_flag(err, ae_fp_less(rep.oobavgerror,0.001), __FILE__, __LINE__, "testdforestunit.ap:942");
/*
* Test
*/
maxerr = (double)(0);
avgerr = (double)(0);
cnt = 0;
for(i=ae_round(-0.7*testgridsize/2, _state); i<=ae_round(0.7*testgridsize/2, _state); i++)
{
for(j=ae_round(-0.7*testgridsize/2, _state); j<=ae_round(0.7*testgridsize/2, _state); j++)
{
x.ptr.p_double[0] = (double)i/(double)(testgridsize/2);
x.ptr.p_double[1] = (double)j/(double)(testgridsize/2);
ey = ae_sqr(x.ptr.p_double[0], _state)+x.ptr.p_double[1];
dfprocess(&df, &x, &y, _state);
maxerr = ae_maxreal(maxerr, ae_fabs(y.ptr.p_double[0]-ey, _state), _state);
avgerr = avgerr+ae_fabs(y.ptr.p_double[0]-ey, _state);
cnt = cnt+1;
}
}
avgerr = avgerr/cnt;
ae_set_error_flag(err, ae_fp_greater(maxerr,0.15), __FILE__, __LINE__, "testdforestunit.ap:962");
ae_set_error_flag(err, ae_fp_greater(avgerr,0.05), __FILE__, __LINE__, "testdforestunit.ap:963");
}
ae_frame_leave(_state);
}
/*************************************************************************
Basic test: extended variable selection leads to better results.
Next task CAN be solved without EVS but it is very unlikely. With EVS
it can be easily and exactly solved.
Task matrix:
1 0 0 0 ... 0 0
0 1 0 0 ... 0 1
0 0 1 0 ... 0 2
0 0 0 1 ... 0 3
0 0 0 0 ... 1 N-1
*************************************************************************/
static void testdforestunit_basictest5(ae_bool* err, ae_state *_state)
{
ae_frame _frame_block;
ae_matrix xy;
ae_int_t nvars;
ae_int_t npoints;
ae_int_t ntrees;
ae_int_t i;
ae_int_t j;
decisionforestbuilder builder;
decisionforest df;
ae_vector x;
ae_vector y;
dfreport rep;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
memset(&builder, 0, sizeof(builder));
memset(&df, 0, sizeof(df));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&rep, 0, sizeof(rep));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_decisionforestbuilder_init(&builder, _state, ae_true);
_decisionforest_init(&df, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
_dfreport_init(&rep, _state, ae_true);
/*
* select npoints and ntrees
*/
npoints = 50;
nvars = npoints;
ntrees = 1;
/*
* Prepare task
*/
ae_matrix_set_length(&xy, npoints, nvars+1, _state);
ae_vector_set_length(&x, nvars, _state);
ae_vector_set_length(&y, 1, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
xy.ptr.pp_double[i][j] = (double)(0);
}
xy.ptr.pp_double[i][i] = (double)(1);
xy.ptr.pp_double[i][nvars] = (double)(i);
}
/*
* Build forest
*/
dfbuildercreate(&builder, _state);
dfbuildersetdataset(&builder, &xy, npoints, nvars, 1, _state);
dfbuildersetsubsampleratio(&builder, 1.00, _state);
dfbuildersetrdfalgo(&builder, ae_randominteger(testdforestunit_algomax+1, _state), _state);
dfbuildersetrdfsplitstrength(&builder, ae_randominteger(testdforestunit_splitmax+1, _state), _state);
dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state);
/*
* Test
*/
ae_set_error_flag(err, ae_fp_greater_eq(rep.rmserror,rep.oobrmserror), __FILE__, __LINE__, "testdforestunit.ap:1032");
ae_set_error_flag(err, ae_fp_greater_eq(rep.avgerror,rep.oobavgerror), __FILE__, __LINE__, "testdforestunit.ap:1033");
ae_set_error_flag(err, ae_fp_greater_eq(rep.avgrelerror,rep.oobavgrelerror), __FILE__, __LINE__, "testdforestunit.ap:1034");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.rmserror, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:1035");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgerror, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:1036");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgrelerror, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:1037");
for(i=0; i<=npoints-1; i++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xy.ptr.pp_double[i][0], 1, ae_v_len(0,nvars-1));
dfprocess(&df, &x, &y, _state);
if( ae_fp_greater(ae_fabs(y.ptr.p_double[0]-xy.ptr.pp_double[i][nvars], _state),1000*ae_machineepsilon) )
{
ae_set_error_flag(err, ae_true, __FILE__, __LINE__, "testdforestunit.ap:1043");
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Basic test: test correctness of error reports on completely random problem;
test that OOB errors are roughly unbiased.
*************************************************************************/
static void testdforestunit_basictestrandom(ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix xy;
ae_int_t nvars;
ae_int_t npoints;
ae_int_t ntrees;
ae_int_t nclasses;
ae_int_t i;
ae_int_t j;
ae_int_t factor;
decisionforestbuilder builder;
decisionforest df;
ae_vector x;
ae_vector y;
dfreport rep;
hqrndstate rs;
double meanlevel;
double sigma;
double v;
double refavgce;
double refrms;
double refavg;
double refavgrel;
ae_int_t relcnt;
double oobtol;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
memset(&builder, 0, sizeof(builder));
memset(&df, 0, sizeof(df));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&rep, 0, sizeof(rep));
memset(&rs, 0, sizeof(rs));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_decisionforestbuilder_init(&builder, _state, ae_true);
_decisionforest_init(&df, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
_dfreport_init(&rep, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
npoints = 200;
nvars = 10;
ntrees = 1000;
oobtol = 0.20;
for(nclasses=1; nclasses<=3; nclasses++)
{
/*
* Prepare task
*/
ae_matrix_set_length(&xy, npoints, nvars+1, _state);
meanlevel = 10*hqrndnormal(&rs, _state);
sigma = ae_pow((double)(10), hqrndnormal(&rs, _state), _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
xy.ptr.pp_double[i][j] = (double)(0);
if( j%3==0 )
{
xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
if( j%3==1&&ae_fp_less(hqrnduniformr(&rs, _state),0.05) )
{
xy.ptr.pp_double[i][j] = (double)(1);
}
if( j%3==2&&ae_fp_less(hqrnduniformr(&rs, _state),0.05) )
{
xy.ptr.pp_double[i][j] = (double)(1+hqrnduniformi(&rs, 3, _state));
}
}
if( nclasses==1 )
{
xy.ptr.pp_double[i][nvars] = meanlevel+sigma*hqrndnormal(&rs, _state);
if( ae_fp_less(hqrnduniformr(&rs, _state),0.05) )
{
xy.ptr.pp_double[i][nvars] = (double)(0);
}
}
else
{
xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nclasses, _state));
}
}
ae_vector_set_length(&x, nvars, _state);
ae_vector_set_length(&y, nclasses, _state);
/*
* Build forest using 50% and 66% of the samples.
* Check TRN and OOB errors (OOB should be 2x and 3x larger in these cases)
*/
for(factor=2; factor<=3; factor++)
{
j = hqrnduniformi(&rs, 3, _state);
dfbuildercreate(&builder, _state);
dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state);
dfbuildersetsubsampleratio(&builder, 1-(double)1/(double)factor, _state);
if( j>0 )
{
dfbuildersetrndvars(&builder, 1+hqrnduniformi(&rs, 5, _state), _state);
}
if( j==0 )
{
dfbuildersetrndvarsauto(&builder, _state);
}
if( j<0 )
{
dfbuildersetrndvarsratio(&builder, hqrnduniformr(&rs, _state), _state);
}
dfbuildersetrdfalgo(&builder, ae_randominteger(testdforestunit_algomax+1, _state), _state);
dfbuildersetrdfsplitstrength(&builder, ae_randominteger(testdforestunit_splitmax+1, _state), _state);
ae_set_error_flag(err, ae_fp_neq(dfbuildergetprogress(&builder, _state),0.0), __FILE__, __LINE__, "testdforestunit.ap:1132");
ae_set_error_flag(err, ae_fp_neq(dfbuilderpeekprogress(&builder, _state),0.0), __FILE__, __LINE__, "testdforestunit.ap:1133");
dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state);
ae_set_error_flag(err, ae_fp_neq(dfbuildergetprogress(&builder, _state),1.0), __FILE__, __LINE__, "testdforestunit.ap:1135");
ae_set_error_flag(err, ae_fp_neq(dfbuilderpeekprogress(&builder, _state),1.0), __FILE__, __LINE__, "testdforestunit.ap:1136");
refavgce = (double)(0);
refrms = (double)(0);
refavg = (double)(0);
refavgrel = (double)(0);
relcnt = 0;
if( nclasses==1 )
{
/*
* Check training set errors
*/
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
x.ptr.p_double[j] = xy.ptr.pp_double[i][j];
}
dfprocess(&df, &x, &y, _state);
v = y.ptr.p_double[0]-xy.ptr.pp_double[i][nvars];
refrms = refrms+ae_sqr(v, _state);
refavg = refavg+ae_fabs(v, _state);
if( ae_fp_neq(xy.ptr.pp_double[i][nvars],(double)(0)) )
{
refavgrel = refavgrel+ae_fabs(v/xy.ptr.pp_double[i][nvars], _state);
relcnt = relcnt+1;
}
}
refrms = ae_sqrt(refrms/npoints, _state);
refavg = refavg/npoints;
refavgrel = refavgrel/coalesce((double)(relcnt), (double)(1), _state);
ae_set_error_flag(err, ae_fp_neq(rep.relclserror,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1164");
ae_set_error_flag(err, ae_fp_neq(rep.avgce,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1165");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state)/refrms,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1166");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state)/refavg,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1167");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state)/refavgrel,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1168");
ae_set_error_flag(err, ae_fp_neq(dfrelclserror(&df, &xy, npoints, _state),(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1169");
ae_set_error_flag(err, ae_fp_neq(dfavgce(&df, &xy, npoints, _state),(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1170");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(dfrmserror(&df, &xy, npoints, _state)-refrms, _state)/refrms,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1171");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(dfavgerror(&df, &xy, npoints, _state)-refavg, _state)/refavg,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1172");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(dfavgrelerror(&df, &xy, npoints, _state)-refavgrel, _state)/refavgrel,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1173");
/*
* Check OOB errors against training set errors:
* * RelCLS and AvgCE are not calculated for regression problems
* * RMS and AVG should be roughly FACTOR times larger
* * AVG-REL should be just larger (it is more prone to sampling noise than previous two)
*/
ae_set_error_flag(err, ae_fp_neq(rep.oobrelclserror,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1181");
ae_set_error_flag(err, ae_fp_neq(rep.oobavgce,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1182");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.oobrmserror/rep.rmserror-factor, _state),oobtol), __FILE__, __LINE__, "testdforestunit.ap:1183");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.oobavgerror/rep.avgerror-factor, _state),oobtol), __FILE__, __LINE__, "testdforestunit.ap:1184");
ae_set_error_flag(err, ae_fp_less(rep.oobavgrelerror,rep.avgrelerror), __FILE__, __LINE__, "testdforestunit.ap:1185");
}
else
{
/*
* Check training set errors
*/
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
x.ptr.p_double[j] = xy.ptr.pp_double[i][j];
}
dfprocess(&df, &x, &y, _state);
for(j=0; j<=nclasses-1; j++)
{
v = y.ptr.p_double[j];
if( ae_fp_eq((double)(j),xy.ptr.pp_double[i][nvars]) )
{
v = v-1;
}
refrms = refrms+ae_sqr(v, _state);
refavg = refavg+ae_fabs(v, _state);
if( ae_fp_eq((double)(j),xy.ptr.pp_double[i][nvars]) )
{
refavgrel = refavgrel+ae_fabs(v, _state);
refavgce = refavgce-ae_log(v, _state);
}
}
}
refrms = ae_sqrt(refrms/(npoints*nclasses), _state);
refavg = refavg/(npoints*nclasses);
refavgrel = refavgrel/npoints;
refavgce = refavgce/npoints;
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgce-refavgce, _state)/refavgce,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1215");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state)/refrms,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1216");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state)/refavg,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1217");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state)/refavgrel,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1218");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(dfrelclserror(&df, &xy, npoints, _state)-rep.relclserror, _state)*npoints,(double)(5)), __FILE__, __LINE__, "testdforestunit.ap:1220");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(dfavgce(&df, &xy, npoints, _state)-refavgce, _state)/refavgce,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1221");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(dfrmserror(&df, &xy, npoints, _state)-refrms, _state)/refrms,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1222");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(dfavgerror(&df, &xy, npoints, _state)-refavg, _state)/refavg,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1223");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(dfavgrelerror(&df, &xy, npoints, _state)-refavgrel, _state)/refavgrel,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1224");
/*
* Check OOB errors against training set errors
* * RelCLS, AvgCE and AvgRel should be just larger (too prone to sampling noise to perform more sensitive tests)
* * RMS and AVG should be roughly FACTOR times larger
*
*/
ae_set_error_flag(err, ae_fp_less(rep.oobrelclserror,rep.relclserror), __FILE__, __LINE__, "testdforestunit.ap:1232");
ae_set_error_flag(err, ae_fp_less(rep.oobavgce,rep.avgce), __FILE__, __LINE__, "testdforestunit.ap:1233");
ae_set_error_flag(err, ae_fp_less(rep.oobavgrelerror,rep.avgrelerror), __FILE__, __LINE__, "testdforestunit.ap:1234");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.oobrmserror/rep.rmserror-factor, _state),oobtol), __FILE__, __LINE__, "testdforestunit.ap:1235");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.oobavgerror/rep.avgerror-factor, _state),oobtol), __FILE__, __LINE__, "testdforestunit.ap:1236");
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Test behavior of the RDF algorithm on problem where all values of variables
are same
*************************************************************************/
static void testdforestunit_basictestallsame(ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix xy;
ae_int_t nvars;
ae_int_t npoints;
ae_int_t ntrees;
ae_int_t nclasses;
ae_int_t i;
ae_int_t j;
ae_int_t k;
decisionforestbuilder builder;
decisionforest df;
ae_vector x;
ae_vector y;
dfreport rep;
hqrndstate rs;
double v;
double refavgce;
double refrms;
double refavg;
double refavgrel;
ae_int_t relcnt;
double oobtol;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
memset(&builder, 0, sizeof(builder));
memset(&df, 0, sizeof(df));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&rep, 0, sizeof(rep));
memset(&rs, 0, sizeof(rs));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_decisionforestbuilder_init(&builder, _state, ae_true);
_decisionforest_init(&df, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
_dfreport_init(&rep, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
npoints = 100;
nvars = 10;
ntrees = 100;
oobtol = 0.25;
for(nclasses=1; nclasses<=3; nclasses++)
{
/*
* Prepare task
*/
ae_matrix_set_length(&xy, npoints, nvars+1, _state);
k = hqrnduniformi(&rs, 11, _state)-5;
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
xy.ptr.pp_double[i][j] = (double)(k);
}
if( nclasses==1 )
{
xy.ptr.pp_double[i][nvars] = hqrndnormal(&rs, _state);
}
else
{
xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nclasses, _state));
}
}
ae_vector_set_length(&x, nvars, _state);
ae_vector_set_length(&y, nclasses, _state);
/*
* Build forest.
* Check TRN and OOB errors.
*/
j = hqrnduniformi(&rs, 3, _state);
dfbuildercreate(&builder, _state);
dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state);
dfbuildersetsubsampleratio(&builder, 0.5, _state);
if( j>0 )
{
dfbuildersetrndvars(&builder, 1+hqrnduniformi(&rs, 5, _state), _state);
}
if( j==0 )
{
dfbuildersetrndvarsauto(&builder, _state);
}
if( j<0 )
{
dfbuildersetrndvarsratio(&builder, hqrnduniformr(&rs, _state), _state);
}
dfbuildersetrdfalgo(&builder, ae_randominteger(testdforestunit_algomax+1, _state), _state);
dfbuildersetrdfsplitstrength(&builder, ae_randominteger(testdforestunit_splitmax+1, _state), _state);
dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state);
refavgce = (double)(0);
refrms = (double)(0);
refavg = (double)(0);
refavgrel = (double)(0);
relcnt = 0;
if( nclasses==1 )
{
/*
* Check training set errors
*/
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
x.ptr.p_double[j] = xy.ptr.pp_double[i][j];
}
dfprocess(&df, &x, &y, _state);
v = y.ptr.p_double[0]-xy.ptr.pp_double[i][nvars];
refrms = refrms+ae_sqr(v, _state);
refavg = refavg+ae_fabs(v, _state);
if( ae_fp_neq(xy.ptr.pp_double[i][nvars],(double)(0)) )
{
refavgrel = refavgrel+ae_fabs(v/xy.ptr.pp_double[i][nvars], _state);
relcnt = relcnt+1;
}
}
refrms = ae_sqrt(refrms/npoints, _state);
refavg = refavg/npoints;
refavgrel = refavgrel/coalesce((double)(relcnt), (double)(1), _state);
ae_set_error_flag(err, ae_fp_neq(rep.relclserror,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1339");
ae_set_error_flag(err, ae_fp_neq(rep.avgce,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1340");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state)/refrms,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1341");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state)/refavg,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1342");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state)/refavgrel,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1343");
/*
* Check OOB errors against training set errors:
* * RelCLS and AvgCE are not calculated for regression problems
* * RMS and AVG should be roughly same
*/
ae_set_error_flag(err, ae_fp_neq(rep.oobrelclserror,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1350");
ae_set_error_flag(err, ae_fp_neq(rep.oobavgce,(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1351");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.oobrmserror/rep.rmserror-1, _state),oobtol), __FILE__, __LINE__, "testdforestunit.ap:1352");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.oobavgerror/rep.avgerror-1, _state),oobtol), __FILE__, __LINE__, "testdforestunit.ap:1353");
}
else
{
/*
* Check training set errors
*/
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
x.ptr.p_double[j] = xy.ptr.pp_double[i][j];
}
dfprocess(&df, &x, &y, _state);
for(j=0; j<=nclasses-1; j++)
{
v = y.ptr.p_double[j];
if( ae_fp_eq((double)(j),xy.ptr.pp_double[i][nvars]) )
{
v = v-1;
}
refrms = refrms+ae_sqr(v, _state);
refavg = refavg+ae_fabs(v, _state);
if( ae_fp_eq((double)(j),xy.ptr.pp_double[i][nvars]) )
{
refavgrel = refavgrel+ae_fabs(v, _state);
refavgce = refavgce-ae_log(v, _state);
}
}
}
refrms = ae_sqrt(refrms/(npoints*nclasses), _state);
refavg = refavg/(npoints*nclasses);
refavgrel = refavgrel/npoints;
refavgce = refavgce/npoints;
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgce-refavgce, _state)/refavgce,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1383");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state)/refrms,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1384");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state)/refavg,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1385");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state)/refavgrel,1.0E-6), __FILE__, __LINE__, "testdforestunit.ap:1386");
/*
* Check OOB errors against training set errors
* * RMS and AVG should be roughly same
*
*/
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.oobrmserror/rep.rmserror-1, _state),oobtol), __FILE__, __LINE__, "testdforestunit.ap:1393");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.oobavgerror/rep.avgerror-1, _state),oobtol), __FILE__, __LINE__, "testdforestunit.ap:1394");
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Test model compression - that it works and generates forests which correctly
reproduce original one
*************************************************************************/
static void testdforestunit_testcompression(ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t pass;
ae_matrix xy;
ae_int_t npoints;
ae_int_t ntrees;
ae_int_t i;
ae_int_t j;
ae_int_t k;
double s;
ae_int_t info;
decisionforestbuilder builder;
decisionforest dfraw;
decisionforest df16;
decisionforest df8;
ae_vector x;
ae_vector y0;
ae_vector y1;
dfreport rep;
ae_int_t nvars;
ae_int_t nclasses;
ae_int_t passcount;
hqrndstate rs;
double tol16;
double tol8;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
memset(&builder, 0, sizeof(builder));
memset(&dfraw, 0, sizeof(dfraw));
memset(&df16, 0, sizeof(df16));
memset(&df8, 0, sizeof(df8));
memset(&x, 0, sizeof(x));
memset(&y0, 0, sizeof(y0));
memset(&y1, 0, sizeof(y1));
memset(&rep, 0, sizeof(rep));
memset(&rs, 0, sizeof(rs));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_decisionforestbuilder_init(&builder, _state, ae_true);
_decisionforest_init(&dfraw, _state, ae_true);
_decisionforest_init(&df16, _state, ae_true);
_decisionforest_init(&df8, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y1, 0, DT_REAL, _state, ae_true);
_dfreport_init(&rep, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
tol16 = 0.0001;
tol8 = 0.01;
/*
* Test compression on small-scale problems:
* * a K-dimensional input, with 3^K distinct points located at integer grid
* * we test that compressed model produces roughly same results as uncompressed
* one (predicts same class / predicts same scalar output subject to small
* truncation error)
*/
for(nvars=1; nvars<=5; nvars++)
{
for(nclasses=1; nclasses<=3; nclasses++)
{
ae_vector_set_length(&x, nvars, _state);
ae_vector_set_length(&y0, nclasses, _state);
ae_vector_set_length(&y1, nclasses, _state);
/*
* Generate dataset
*/
npoints = ae_round(ae_pow((double)(3), (double)(nvars), _state), _state);
ae_matrix_set_length(&xy, npoints, nvars+1, _state);
for(i=0; i<=npoints-1; i++)
{
k = i;
for(j=0; j<=nvars-1; j++)
{
xy.ptr.pp_double[i][j] = (double)(k%3-1);
k = k/3;
}
if( nclasses==1 )
{
xy.ptr.pp_double[i][nvars] = hqrnduniformr(&rs, _state)-0.5;
}
else
{
xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nclasses, _state));
}
}
/*
* Train uncompressed
*/
ntrees = 1+hqrnduniformi(&rs, 10, _state);
dfbuildercreate(&builder, _state);
dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state);
dfbuildersetsubsampleratio(&builder, 0.66, _state);
dfbuilderbuildrandomforest(&builder, ntrees, &dfraw, &rep, _state);
/*
* Test 16-bit compression
*/
dfcopy(&dfraw, &df16, _state);
dfbinarycompression(&df16, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
x.ptr.p_double[j] = xy.ptr.pp_double[i][j];
}
dfprocess(&dfraw, &x, &y0, _state);
dfprocess(&df16, &x, &y1, _state);
if( nclasses>1 )
{
/*
* Compare output probabilities for classification problem
*/
for(j=0; j<=nclasses-1; j++)
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y0.ptr.p_double[j]-y1.ptr.p_double[j], _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:1491");
}
}
else
{
/*
* Compare output values for regression problem
*/
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y0.ptr.p_double[0]-y1.ptr.p_double[0], _state),tol16), __FILE__, __LINE__, "testdforestunit.ap:1498");
}
}
/*
* Test 8-bit compression
*/
dfcopy(&dfraw, &df8, _state);
dfbinarycompression8(&df8, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
x.ptr.p_double[j] = xy.ptr.pp_double[i][j];
}
dfprocess(&dfraw, &x, &y0, _state);
dfprocess(&df8, &x, &y1, _state);
if( nclasses>1 )
{
/*
* Compare output probabilities for classification problem
*/
for(j=0; j<=nclasses-1; j++)
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y0.ptr.p_double[j]-y1.ptr.p_double[j], _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:1519");
}
}
else
{
/*
* Compare output values for regression problem
*/
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y0.ptr.p_double[0]-y1.ptr.p_double[0], _state),tol8), __FILE__, __LINE__, "testdforestunit.ap:1526");
}
}
}
}
/*
* Test compression on large-scale problems:
* * NVars=500, NPoints=500, I-th point is zero except for I-th position
* * NClasses=1 (random output) or NClasses=400
* * NTrees is in 1...5
*/
for(pass=0; pass<=1; pass++)
{
/*
* Set up problem
*/
ae_assert(pass==0||pass==1, "DF: integrity check failed", _state);
nvars = 500;
npoints = 500;
nclasses = 1;
if( pass==1 )
{
nclasses = 400;
}
ae_matrix_set_length(&xy, npoints, nvars+1, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
xy.ptr.pp_double[i][j] = (double)(0);
}
xy.ptr.pp_double[i][i] = (double)(1);
if( nclasses==1 )
{
xy.ptr.pp_double[i][nvars] = hqrnduniformr(&rs, _state)-0.5;
}
else
{
xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nclasses, _state));
}
}
ae_vector_set_length(&x, nvars, _state);
ae_vector_set_length(&y0, nclasses, _state);
ae_vector_set_length(&y1, nclasses, _state);
/*
* Train uncompressed
*/
ntrees = 1+hqrnduniformi(&rs, 5, _state);
dfbuildercreate(&builder, _state);
dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state);
dfbuildersetsubsampleratio(&builder, 0.66, _state);
dfbuilderbuildrandomforest(&builder, ntrees, &dfraw, &rep, _state);
/*
* Test 16-bit compression
*/
dfcopy(&dfraw, &df16, _state);
dfbinarycompression(&df16, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
x.ptr.p_double[j] = xy.ptr.pp_double[i][j];
}
dfprocess(&dfraw, &x, &y0, _state);
dfprocess(&df16, &x, &y1, _state);
if( nclasses>1 )
{
/*
* Compare output probabilities for classification problem
*/
for(j=0; j<=nclasses-1; j++)
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y0.ptr.p_double[j]-y1.ptr.p_double[j], _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:1589");
}
}
else
{
/*
* Compare output values for regression problem
*/
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y0.ptr.p_double[0]-y1.ptr.p_double[0], _state),tol16), __FILE__, __LINE__, "testdforestunit.ap:1596");
}
}
/*
* Test 8-bit compression
*/
dfcopy(&dfraw, &df8, _state);
dfbinarycompression8(&df8, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
x.ptr.p_double[j] = xy.ptr.pp_double[i][j];
}
dfprocess(&dfraw, &x, &y0, _state);
dfprocess(&df8, &x, &y1, _state);
if( nclasses>1 )
{
/*
* Compare output probabilities for classification problem
*/
for(j=0; j<=nclasses-1; j++)
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y0.ptr.p_double[j]-y1.ptr.p_double[j], _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testdforestunit.ap:1617");
}
}
else
{
/*
* Compare output values for regression problem
*/
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y0.ptr.p_double[0]-y1.ptr.p_double[0], _state),tol8), __FILE__, __LINE__, "testdforestunit.ap:1624");
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Test variable importance
*************************************************************************/
static void testdforestunit_testimportance(ae_bool* err, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t i1;
ae_matrix xy;
ae_matrix xy2;
ae_matrix xyp;
ae_vector c;
ae_vector vloss;
ae_vector tmp;
ae_int_t npoints;
ae_int_t npoints2;
ae_int_t nvars;
ae_int_t nclasses;
ae_int_t ntrees;
decisionforestbuilder builder;
decisionforest df;
dfreport rep;
double v;
double unimportantlo;
double unimportanthi;
double importantlo;
double importanthi;
hqrndstate rs;
ae_int_t ntype;
ae_int_t ntypes;
ae_int_t stype;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
memset(&xy2, 0, sizeof(xy2));
memset(&xyp, 0, sizeof(xyp));
memset(&c, 0, sizeof(c));
memset(&vloss, 0, sizeof(vloss));
memset(&tmp, 0, sizeof(tmp));
memset(&builder, 0, sizeof(builder));
memset(&df, 0, sizeof(df));
memset(&rep, 0, sizeof(rep));
memset(&rs, 0, sizeof(rs));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xyp, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&c, 0, DT_REAL, _state, ae_true);
ae_vector_init(&vloss, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
_decisionforestbuilder_init(&builder, _state, ae_true);
_decisionforest_init(&df, _state, ae_true);
_dfreport_init(&rep, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
ntypes = 3;
hqrndrandomize(&rs, _state);
/*
* Test that default state of importance estimation is off
*/
npoints = 50;
ntrees = 50;
for(nclasses=1; nclasses<=3; nclasses++)
{
/*
* Generate dataset
*/
nvars = 1+hqrnduniformi(&rs, 3, _state);
ae_matrix_set_length(&xy, npoints, nvars+1, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
if( nclasses==1 )
{
xy.ptr.pp_double[i][nvars] = hqrnduniformr(&rs, _state)-0.5;
}
else
{
xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nclasses, _state));
}
}
/*
* Train with default settings, check that variable importances reported are zero
*/
dfbuildercreate(&builder, _state);
dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state);
dfbuildersetsubsampleratio(&builder, 0.66, _state);
dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state);
ae_set_error_flag(err, rep.varimportances.cnt!=nvars, __FILE__, __LINE__, "testdforestunit.ap:1690");
ae_set_error_flag(err, rep.topvars.cnt!=nvars, __FILE__, __LINE__, "testdforestunit.ap:1691");
if( *err )
{
ae_frame_leave(_state);
return;
}
for(j=0; j<=nvars-1; j++)
{
ae_set_error_flag(err, ae_fp_neq(rep.varimportances.ptr.p_double[j],(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1696");
ae_set_error_flag(err, rep.topvars.ptr.p_int[j]!=j, __FILE__, __LINE__, "testdforestunit.ap:1697");
}
}
/*
* Test that degenerate cases are handled correctly
*/
npoints = 50;
ntrees = 50;
for(nclasses=1; nclasses<=3; nclasses++)
{
for(npoints=1; npoints<=2; npoints++)
{
for(stype=0; stype<=1; stype++)
{
for(ntype=0; ntype<=ntypes-1; ntype++)
{
/*
* Generate dataset
*/
nvars = 1+hqrnduniformi(&rs, 3, _state);
ae_matrix_set_length(&xy, npoints, nvars+1, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
if( nclasses==1 )
{
xy.ptr.pp_double[i][nvars] = hqrnduniformr(&rs, _state)-0.5;
}
else
{
xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nclasses, _state));
}
}
/*
* Train
*/
dfbuildercreate(&builder, _state);
dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state);
dfbuildersetsubsampleratio(&builder, 1.0-stype*0.5, _state);
ae_assert(ntype<=2, "integrity check in the test", _state);
if( ntype==0 )
{
dfbuildersetimportanceoobgini(&builder, _state);
}
if( ntype==1 )
{
dfbuildersetimportancepermutation(&builder, _state);
}
if( ntype==2 )
{
dfbuildersetimportancetrngini(&builder, _state);
}
dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state);
ae_set_error_flag(err, rep.varimportances.cnt!=nvars, __FILE__, __LINE__, "testdforestunit.ap:1740");
ae_set_error_flag(err, rep.topvars.cnt!=nvars, __FILE__, __LINE__, "testdforestunit.ap:1741");
if( *err )
{
ae_frame_leave(_state);
return;
}
if( npoints==1||stype==1 )
{
for(j=0; j<=nvars-1; j++)
{
ae_set_error_flag(err, ae_fp_neq(rep.varimportances.ptr.p_double[j],(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1748");
ae_set_error_flag(err, rep.topvars.ptr.p_int[j]!=j, __FILE__, __LINE__, "testdforestunit.ap:1749");
}
}
}
}
}
}
/*
* Test various importance types
*/
for(ntype=0; ntype<=ntypes-1; ntype++)
{
/*
* Select variables count
*/
nvars = 1+hqrnduniformi(&rs, 3, _state);
/*
* Select preferred problem metrics for this importance type
*/
npoints = -1;
ntrees = -1;
unimportantlo = (double)(-1);
unimportanthi = (double)(-1);
importantlo = (double)(-1);
importanthi = (double)(-1);
if( ntype==0 )
{
/*
* OOB Gini importance averages individual importances between multiple trees,
* so its variance is inversely proportional to the tree count. Tasks with large number
* of trees are preferred.
*/
npoints = 250;
ntrees = 1000;
unimportantlo = 0.00;
unimportanthi = 0.25;
importantlo = 0.75*((double)1/(double)nvars);
importanthi = ae_minreal(1.25*((double)1/(double)nvars), 1.00, _state);
}
if( ntype==1 )
{
/*
* Variance of permutation importance estimate is inversely proportional to the
* dataset size. Tasks with large number of points are preferred, trees count
* does not matter much here.
*/
npoints = 5000;
ntrees = 10;
unimportantlo = 0.00;
unimportanthi = 0.15;
importantlo = 0.85;
importanthi = 1.00;
}
if( ntype==2 )
{
/*
* TRN Gini importance averages individual importances between multiple trees,
* so its variance is inversely proportional to the tree count. Tasks with large number
* of trees are preferred.
*/
npoints = 250;
ntrees = 1000;
unimportantlo = 0.75*((double)1/(double)nvars);
unimportanthi = ae_minreal(1.25*((double)1/(double)nvars), 1.00, _state);
importantlo = 0.75*((double)1/(double)nvars);
importanthi = ae_minreal(1.25*((double)1/(double)nvars), 1.00, _state);
}
/*
* Test on a problem with completely random outputs
*/
for(nclasses=1; nclasses<=3; nclasses++)
{
/*
* Generate dataset
*/
ae_matrix_set_length(&xy, npoints, nvars+1, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
if( nclasses==1 )
{
xy.ptr.pp_double[i][nvars] = hqrnduniformr(&rs, _state)-0.5;
}
else
{
xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nclasses, _state));
}
}
testdforestunit_randomlyrearrange(&xy, npoints, nvars, &rs, _state);
/*
* Train
*/
dfbuildercreate(&builder, _state);
dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state);
dfbuildersetsubsampleratio(&builder, 0.66, _state);
dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state);
ae_assert(ntype<=2, "integrity check in the test", _state);
if( ntype==0 )
{
dfbuildersetimportanceoobgini(&builder, _state);
}
if( ntype==1 )
{
dfbuildersetimportancepermutation(&builder, _state);
}
if( ntype==2 )
{
dfbuildersetimportancetrngini(&builder, _state);
}
dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state);
ae_set_error_flag(err, rep.varimportances.cnt!=nvars, __FILE__, __LINE__, "testdforestunit.ap:1851");
ae_set_error_flag(err, rep.topvars.cnt!=nvars, __FILE__, __LINE__, "testdforestunit.ap:1852");
if( *err )
{
ae_frame_leave(_state);
return;
}
for(j=0; j<=nvars-1; j++)
{
ae_set_error_flag(err, ae_fp_less(rep.varimportances.ptr.p_double[j],unimportantlo), __FILE__, __LINE__, "testdforestunit.ap:1859");
ae_set_error_flag(err, ae_fp_greater(rep.varimportances.ptr.p_double[j],unimportanthi), __FILE__, __LINE__, "testdforestunit.ap:1860");
}
setlengthzero(&tmp, nvars, _state);
for(j=0; j<=nvars-1; j++)
{
ae_set_error_flag(err, rep.topvars.ptr.p_int[j]<0, __FILE__, __LINE__, "testdforestunit.ap:1865");
ae_set_error_flag(err, rep.topvars.ptr.p_int[j]>=nvars, __FILE__, __LINE__, "testdforestunit.ap:1866");
if( *err )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(err, ae_fp_neq(tmp.ptr.p_double[rep.topvars.ptr.p_int[j]],(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1869");
tmp.ptr.p_double[rep.topvars.ptr.p_int[j]] = tmp.ptr.p_double[rep.topvars.ptr.p_int[j]]+1;
}
for(j=0; j<=nvars-2; j++)
{
ae_set_error_flag(err, ae_fp_less(rep.varimportances.ptr.p_double[rep.topvars.ptr.p_int[j]],rep.varimportances.ptr.p_double[rep.topvars.ptr.p_int[j+1]]), __FILE__, __LINE__, "testdforestunit.ap:1873");
}
if( ntype==2 )
{
/*
* TRN-Gini importances sum to 1.0
*/
v = (double)(0);
for(j=0; j<=nvars-1; j++)
{
v = v+rep.varimportances.ptr.p_double[j];
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-1, _state),1.0e-6), __FILE__, __LINE__, "testdforestunit.ap:1882");
}
}
/*
* Test that on a problem where:
* * every variable matters
* * every variable is critical
* * result is completely predictable.
*/
for(nclasses=1; nclasses<=3; nclasses++)
{
/*
* Generate dataset
*/
ae_matrix_set_length(&xy, npoints, nvars+1, _state);
for(i=0; i<=npoints-1; i++)
{
if( nclasses==1 )
{
xy.ptr.pp_double[i][nvars] = (double)(0);
k = i;
for(j=0; j<=nvars-1; j++)
{
xy.ptr.pp_double[i][j] = (double)(k%3);
xy.ptr.pp_double[i][nvars] = xy.ptr.pp_double[i][nvars]+ae_round(xy.ptr.pp_double[i][j], _state);
k = k/3;
}
xy.ptr.pp_double[i][nvars] = (double)(ae_round(xy.ptr.pp_double[i][nvars], _state)%3-1);
}
else
{
xy.ptr.pp_double[i][nvars] = (double)(0);
k = i;
for(j=0; j<=nvars-1; j++)
{
xy.ptr.pp_double[i][j] = (double)(k%nclasses);
xy.ptr.pp_double[i][nvars] = xy.ptr.pp_double[i][nvars]+ae_round(xy.ptr.pp_double[i][j], _state);
k = k/nclasses;
}
xy.ptr.pp_double[i][nvars] = (double)(ae_round(xy.ptr.pp_double[i][nvars], _state)%nclasses);
}
}
testdforestunit_randomlyrearrange(&xy, npoints, nvars, &rs, _state);
/*
* Train
*/
dfbuildercreate(&builder, _state);
dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state);
dfbuildersetsubsampleratio(&builder, 0.5, _state);
dfbuildersetrndvars(&builder, nvars, _state);
ae_assert(ntype<=2, "integrity check in the test", _state);
if( ntype==0 )
{
dfbuildersetimportanceoobgini(&builder, _state);
}
if( ntype==1 )
{
dfbuildersetimportancepermutation(&builder, _state);
}
if( ntype==2 )
{
dfbuildersetimportancetrngini(&builder, _state);
}
dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state);
ae_set_error_flag(err, rep.varimportances.cnt!=nvars, __FILE__, __LINE__, "testdforestunit.ap:1942");
ae_set_error_flag(err, rep.topvars.cnt!=nvars, __FILE__, __LINE__, "testdforestunit.ap:1943");
if( *err )
{
ae_frame_leave(_state);
return;
}
for(j=0; j<=nvars-1; j++)
{
ae_set_error_flag(err, ae_fp_less(rep.varimportances.ptr.p_double[j],importantlo), __FILE__, __LINE__, "testdforestunit.ap:1950");
ae_set_error_flag(err, ae_fp_greater(rep.varimportances.ptr.p_double[j],importanthi), __FILE__, __LINE__, "testdforestunit.ap:1951");
}
setlengthzero(&tmp, nvars, _state);
for(j=0; j<=nvars-1; j++)
{
ae_set_error_flag(err, rep.topvars.ptr.p_int[j]<0, __FILE__, __LINE__, "testdforestunit.ap:1956");
ae_set_error_flag(err, rep.topvars.ptr.p_int[j]>=nvars, __FILE__, __LINE__, "testdforestunit.ap:1957");
if( *err )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(err, ae_fp_neq(tmp.ptr.p_double[rep.topvars.ptr.p_int[j]],(double)(0)), __FILE__, __LINE__, "testdforestunit.ap:1960");
tmp.ptr.p_double[rep.topvars.ptr.p_int[j]] = tmp.ptr.p_double[rep.topvars.ptr.p_int[j]]+1;
}
for(j=0; j<=nvars-2; j++)
{
ae_set_error_flag(err, ae_fp_less(rep.varimportances.ptr.p_double[rep.topvars.ptr.p_int[j]],rep.varimportances.ptr.p_double[rep.topvars.ptr.p_int[j+1]]), __FILE__, __LINE__, "testdforestunit.ap:1964");
}
if( ntype==2 )
{
/*
* TRN-Gini importances sum to 1.0
*/
v = (double)(0);
for(j=0; j<=nvars-1; j++)
{
v = v+rep.varimportances.ptr.p_double[j];
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-1, _state),1.0e-6), __FILE__, __LINE__, "testdforestunit.ap:1973");
}
}
}
/*
* Test values computed by the fast MDA (permutation) algorithm against
* ones computed by definition (by simply running model on permuted dataset).
*
* We solve regression and 2-class classification problems.
*
* Large "reference" dataset is used to compute reference importances in order
* to reduce variance of at least one component in the difference |I_reference-I_computed|
*/
npoints = 5000;
ntrees = 10;
npoints2 = npoints;
for(nclasses=1; nclasses<=2; nclasses++)
{
/*
* Generate dataset
*/
nvars = 3;
ae_vector_set_length(&c, nvars, _state);
for(j=0; j<=nvars-1; j++)
{
c.ptr.p_double[j] = ae_pow((double)(2), (double)(-j), _state);
}
ae_matrix_set_length(&xy2, npoints+npoints2, nvars+1, _state);
for(i=0; i<=npoints+npoints2-1; i++)
{
xy2.ptr.pp_double[i][nvars] = 0.01*hqrndnormal(&rs, _state);
for(j=0; j<=nvars-1; j++)
{
xy2.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)-0.5;
xy2.ptr.pp_double[i][nvars] = xy2.ptr.pp_double[i][nvars]+xy2.ptr.pp_double[i][j]*c.ptr.p_double[j];
}
if( nclasses==2 )
{
if( ae_fp_greater(xy2.ptr.pp_double[i][nvars],(double)(0)) )
{
xy2.ptr.pp_double[i][nvars] = (double)(0);
}
else
{
xy2.ptr.pp_double[i][nvars] = (double)(1);
}
}
}
ae_matrix_set_length(&xy, npoints, nvars+1, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars; j++)
{
xy.ptr.pp_double[i][j] = xy2.ptr.pp_double[npoints2+i][j];
}
}
rmatrixresize(&xy2, npoints2, nvars+1, _state);
testdforestunit_randomlyrearrange(&xy, npoints, nvars, &rs, _state);
/*
* Train model
*/
dfbuildercreate(&builder, _state);
dfbuildersetdataset(&builder, &xy, npoints, nvars, nclasses, _state);
dfbuildersetsubsampleratio(&builder, 0.5, _state);
dfbuildersetimportancepermutation(&builder, _state);
dfbuildersetrndvars(&builder, nvars, _state);
dfbuilderbuildrandomforest(&builder, ntrees, &df, &rep, _state);
ae_set_error_flag(err, rep.varimportances.cnt!=nvars, __FILE__, __LINE__, "testdforestunit.ap:2032");
ae_set_error_flag(err, rep.topvars.cnt!=nvars, __FILE__, __LINE__, "testdforestunit.ap:2033");
if( *err )
{
ae_frame_leave(_state);
return;
}
/*
* Compute importances by definition
*/
ae_matrix_set_length(&xyp, npoints2, nvars+1, _state);
ae_vector_set_length(&vloss, nvars+2, _state);
for(k=0; k<=nvars+1; k++)
{
for(i=0; i<=npoints2-1; i++)
{
for(j=0; j<=nvars; j++)
{
xyp.ptr.pp_double[i][j] = xy2.ptr.pp_double[i][j];
}
}
if( kptr.pp_double[i][kind];
}
tagsort(&y, npoints, &p1, &p2, _state);
for(i=0; i<=npoints-1; i++)
{
swaprows(xy, i, p2.ptr.p_int[i], nvars+1, _state);
}
ae_frame_leave(_state);
}
static void testknnunit_testknnalgo(ae_bool* err, ae_state *_state);
static void testknnunit_unsetknn(knnmodel* model, ae_state *_state);
static void testknnunit_testseterrors(knnmodel* model,
ae_int_t nvars,
ae_int_t nout,
ae_bool iscls,
/* Real */ ae_matrix* xy,
ae_int_t npoints,
double* avgce,
double* relcls0,
double* relcls1,
double* rms,
double* avg,
double* avgrel,
ae_state *_state);
ae_bool testknn(ae_bool silent, ae_state *_state)
{
ae_bool waserrors;
ae_bool knnerrors;
ae_bool result;
/*
* Primary settings
*/
knnerrors = ae_false;
waserrors = ae_false;
/*
* Tests
*/
testknnunit_testknnalgo(&knnerrors, _state);
/*
* Final report
*/
waserrors = knnerrors;
if( !silent )
{
printf("KNN CLASSIFIER/REGRESSION TEST\n");
printf("TOTAL RESULTS: ");
if( !waserrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* KNN (AKNN) ALGORITHM ");
if( !knnerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST SUMMARY: FAILED\n");
}
else
{
printf("TEST SUMMARY: PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
return result;
}
/*************************************************************************
Processing functions test
*************************************************************************/
static void testknnunit_testknnalgo(ae_bool* err, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t nvars;
ae_int_t nout;
ae_bool iscls;
ae_int_t ny;
ae_int_t k;
double eps;
knnmodel model1;
knnmodel model2;
knnmodel modelus;
knnbuilder builder;
knnreport rep;
knnreport rep2;
knnreport tstrep;
knnbuffer buf;
ae_matrix xy;
ae_int_t npoints;
ae_matrix testxy;
ae_int_t testnpoints;
ae_int_t pass;
ae_int_t i;
ae_int_t j;
ae_bool allsame;
ae_vector x1;
ae_vector x2;
ae_vector y1;
ae_vector y2;
ae_vector y3;
double v;
double refavgce;
double refcls0;
double refcls1;
double refrms;
double refavg;
double refavgrel;
double maxerr;
double avgerr;
ae_int_t cnt;
hqrndstate rs;
ae_frame_make(_state, &_frame_block);
memset(&model1, 0, sizeof(model1));
memset(&model2, 0, sizeof(model2));
memset(&modelus, 0, sizeof(modelus));
memset(&builder, 0, sizeof(builder));
memset(&rep, 0, sizeof(rep));
memset(&rep2, 0, sizeof(rep2));
memset(&tstrep, 0, sizeof(tstrep));
memset(&buf, 0, sizeof(buf));
memset(&xy, 0, sizeof(xy));
memset(&testxy, 0, sizeof(testxy));
memset(&x1, 0, sizeof(x1));
memset(&x2, 0, sizeof(x2));
memset(&y1, 0, sizeof(y1));
memset(&y2, 0, sizeof(y2));
memset(&y3, 0, sizeof(y3));
memset(&rs, 0, sizeof(rs));
_knnmodel_init(&model1, _state, ae_true);
_knnmodel_init(&model2, _state, ae_true);
_knnmodel_init(&modelus, _state, ae_true);
_knnbuilder_init(&builder, _state, ae_true);
_knnreport_init(&rep, _state, ae_true);
_knnreport_init(&rep2, _state, ae_true);
_knnreport_init(&tstrep, _state, ae_true);
_knnbuffer_init(&buf, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&testxy, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y3, 0, DT_REAL, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Test on randomly generated sets with randomly generated algo settings
*
* We test:
* * process
* * processi
* * process0
* * classify
* * serialization/unserialization
* * reports and test set error evaluation
* * knnrewritekeps()
*/
for(pass=1; pass<=100; pass++)
{
/*
* initialize parameters
*/
nvars = 1+hqrnduniformi(&rs, 5, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
iscls = ae_true;
nout = 2+hqrnduniformi(&rs, 3, _state);
ny = 1;
}
else
{
iscls = ae_false;
nout = 1+hqrnduniformi(&rs, 3, _state);
ny = nout;
}
k = 1+hqrnduniformi(&rs, 3, _state);
eps = hqrnduniformi(&rs, 2, _state)*0.1*hqrnduniformr(&rs, _state);
/*
* Initialize arrays and data: training and test sets
*/
npoints = 10+hqrnduniformi(&rs, 100, _state);
ae_matrix_set_length(&xy, npoints, nvars+ny, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
if( j%2==0 )
{
xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
else
{
xy.ptr.pp_double[i][j] = (double)(hqrnduniformi(&rs, 2, _state));
}
}
if( iscls )
{
xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nout, _state));
}
else
{
for(j=0; j<=nout-1; j++)
{
xy.ptr.pp_double[i][nvars+j] = hqrndnormal(&rs, _state);
}
}
}
testnpoints = 10+hqrnduniformi(&rs, 100, _state);
ae_matrix_set_length(&testxy, testnpoints, nvars+ny, _state);
for(i=0; i<=testnpoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
if( j%2==0 )
{
testxy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
else
{
testxy.ptr.pp_double[i][j] = (double)(hqrnduniformi(&rs, 2, _state));
}
}
if( iscls )
{
testxy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nout, _state));
}
else
{
for(j=0; j<=nout-1; j++)
{
testxy.ptr.pp_double[i][nvars+j] = hqrndnormal(&rs, _state);
}
}
}
/*
* create model
*/
testknnunit_unsetknn(&model1, _state);
knnbuildercreate(&builder, _state);
if( iscls )
{
knnbuildersetdatasetcls(&builder, &xy, npoints, nvars, nout, _state);
}
else
{
knnbuildersetdatasetreg(&builder, &xy, npoints, nvars, nout, _state);
}
knnbuildersetnorm(&builder, hqrnduniformi(&rs, 3, _state), _state);
knnbuilderbuildknnmodel(&builder, k, eps, &model1, &rep, _state);
knncreatebuffer(&model1, &buf, _state);
/*
* Check that:
* * knnprocess() does not shrink output array, only increases
* * knntsprocess() does not shrink output array, only increases
* * knnprocessi() fits length exactly to NOut
*/
ae_vector_set_length(&x1, nvars, _state);
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&y1, nout+1, _state);
knnprocess(&model1, &x1, &y1, _state);
ae_set_error_flag(err, y1.cnt!=nout+1, __FILE__, __LINE__, "testknnunit.ap:200");
ae_vector_set_length(&y1, nout-1, _state);
knnprocess(&model1, &x1, &y1, _state);
ae_set_error_flag(err, y1.cnt!=nout, __FILE__, __LINE__, "testknnunit.ap:203");
ae_vector_set_length(&y1, nout+1, _state);
knntsprocess(&model1, &buf, &x1, &y1, _state);
ae_set_error_flag(err, y1.cnt!=nout+1, __FILE__, __LINE__, "testknnunit.ap:207");
ae_vector_set_length(&y1, nout-1, _state);
knntsprocess(&model1, &buf, &x1, &y1, _state);
ae_set_error_flag(err, y1.cnt!=nout, __FILE__, __LINE__, "testknnunit.ap:210");
ae_vector_set_length(&y1, nout+1, _state);
knnprocessi(&model1, &x1, &y1, _state);
ae_set_error_flag(err, y1.cnt!=nout, __FILE__, __LINE__, "testknnunit.ap:214");
ae_vector_set_length(&y1, nout-1, _state);
knnprocessi(&model1, &x1, &y1, _state);
ae_set_error_flag(err, y1.cnt!=nout, __FILE__, __LINE__, "testknnunit.ap:217");
if( *err )
{
ae_frame_leave(_state);
return;
}
/*
* knnprocess(), knnprocessi() and knntsprocess() return same results
*/
ae_vector_set_length(&x1, nvars, _state);
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
knnprocess(&model1, &x1, &y1, _state);
knnprocessi(&model1, &x1, &y2, _state);
knntsprocess(&model1, &buf, &x1, &y3, _state);
for(i=0; i<=nout-1; i++)
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y2.ptr.p_double[i]-y1.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testknnunit.ap:232");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y3.ptr.p_double[i]-y1.ptr.p_double[i], _state),100*ae_machineepsilon), __FILE__, __LINE__, "testknnunit.ap:233");
}
/*
* Same inputs leads to same outputs
*/
ae_vector_set_length(&x1, nvars, _state);
ae_vector_set_length(&x2, nvars, _state);
ae_vector_set_length(&y1, nout, _state);
ae_vector_set_length(&y2, nout, _state);
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = hqrndnormal(&rs, _state);
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
for(i=0; i<=nout-1; i++)
{
y1.ptr.p_double[i] = hqrndnormal(&rs, _state);
y2.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
knnprocess(&model1, &x1, &y1, _state);
knnprocess(&model1, &x2, &y2, _state);
allsame = ae_true;
for(i=0; i<=nout-1; i++)
{
allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]);
}
ae_set_error_flag(err, !allsame, __FILE__, __LINE__, "testknnunit.ap:259");
/*
* Same inputs on original forest leads to same outputs
* on copy created using KNNSerialize
*/
ae_vector_set_length(&x1, nvars, _state);
ae_vector_set_length(&x2, nvars, _state);
ae_vector_set_length(&y1, nout, _state);
ae_vector_set_length(&y2, nout, _state);
testknnunit_unsetknn(&modelus, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
knnalloc(&_local_serializer, &model1, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
knnserialize(&_local_serializer, &model1, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
knnunserialize(&_local_serializer, &modelus, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = hqrndnormal(&rs, _state);
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
for(i=0; i<=nout-1; i++)
{
y1.ptr.p_double[i] = hqrndnormal(&rs, _state);
y2.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
knnprocess(&model1, &x1, &y1, _state);
knnprocess(&modelus, &x2, &y2, _state);
allsame = ae_true;
for(i=0; i<=nout-1; i++)
{
allsame = allsame&&ae_fp_eq(y1.ptr.p_double[i],y2.ptr.p_double[i]);
}
ae_set_error_flag(err, !allsame, __FILE__, __LINE__, "testknnunit.ap:287");
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = hqrndnormal(&rs, _state);
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(knnprocess0(&model1, &x1, _state)-knnprocess0(&modelus, &x2, _state), _state),100*ae_machineepsilon), __FILE__, __LINE__, "testknnunit.ap:293");
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = hqrndnormal(&rs, _state);
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
ae_set_error_flag(err, knnclassify(&model1, &x1, _state)!=knnclassify(&modelus, &x2, _state), __FILE__, __LINE__, "testknnunit.ap:299");
/*
* KNNProcess0 works as expected
*/
ae_vector_set_length(&x1, nvars, _state);
ae_vector_set_length(&x2, nvars, _state);
ae_vector_set_length(&y1, nout, _state);
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = hqrndnormal(&rs, _state);
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
for(i=0; i<=nout-1; i++)
{
y1.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
knnprocess(&model1, &x1, &y1, _state);
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y1.ptr.p_double[0]-knnprocess0(&model1, &x2, _state), _state),100*ae_machineepsilon), __FILE__, __LINE__, "testknnunit.ap:318");
/*
* KNNClassify works as expected
*/
ae_vector_set_length(&x1, nvars, _state);
ae_vector_set_length(&x2, nvars, _state);
ae_vector_set_length(&y1, nout, _state);
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = hqrndnormal(&rs, _state);
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
if( iscls )
{
for(i=0; i<=nout-1; i++)
{
y1.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
knnprocess(&model1, &x1, &y1, _state);
j = knnclassify(&model1, &x2, _state);
for(i=0; i<=nout-1; i++)
{
ae_set_error_flag(err, ae_fp_greater(y1.ptr.p_double[i],y1.ptr.p_double[j]), __FILE__, __LINE__, "testknnunit.ap:341");
}
}
else
{
ae_set_error_flag(err, knnclassify(&model1, &x2, _state)!=-1, __FILE__, __LINE__, "testknnunit.ap:344");
}
/*
* Normalization properties
*/
if( iscls )
{
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&y1, 0, _state);
knnprocess(&model1, &x1, &y1, _state);
v = (double)(0);
for(i=0; i<=nout-1; i++)
{
v = v+y1.ptr.p_double[i];
ae_set_error_flag(err, ae_fp_less(y1.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testknnunit.ap:359");
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(v-1, _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testknnunit.ap:361");
}
/*
* Test various error metrics reported by algorithm:
* * training set errors included in the report
* * errors on the test set
*
* NOTE: cross-entropy metric is tested only for training set.
* because model can produce exactly zero probabilities
* for completely unknown values
*/
testknnunit_testseterrors(&model1, nvars, nout, iscls, &xy, npoints, &refavgce, &refcls0, &refcls1, &refrms, &refavg, &refavgrel, _state);
if( iscls )
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgce-refavgce, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:377");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(knnavgce(&model1, &xy, npoints, _state)-refavgce, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:378");
ae_set_error_flag(err, ae_fp_less(rep.relclserror,refcls0-1.0E-6), __FILE__, __LINE__, "testknnunit.ap:381");
ae_set_error_flag(err, ae_fp_greater(rep.relclserror,refcls1+1.0E-6), __FILE__, __LINE__, "testknnunit.ap:382");
ae_set_error_flag(err, ae_fp_less(knnrelclserror(&model1, &xy, npoints, _state),refcls0-1.0E-6), __FILE__, __LINE__, "testknnunit.ap:383");
ae_set_error_flag(err, ae_fp_greater(knnrelclserror(&model1, &xy, npoints, _state),refcls1+1.0E-6), __FILE__, __LINE__, "testknnunit.ap:384");
}
else
{
ae_set_error_flag(err, ae_fp_neq(rep.avgce,(double)(0)), __FILE__, __LINE__, "testknnunit.ap:389");
ae_set_error_flag(err, ae_fp_neq(knnavgce(&model1, &xy, npoints, _state),(double)(0)), __FILE__, __LINE__, "testknnunit.ap:390");
ae_set_error_flag(err, ae_fp_neq(rep.relclserror,(double)(0)), __FILE__, __LINE__, "testknnunit.ap:393");
ae_set_error_flag(err, ae_fp_neq(knnrelclserror(&model1, &xy, npoints, _state),(double)(0)), __FILE__, __LINE__, "testknnunit.ap:394");
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:396");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:397");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:398");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(knnrmserror(&model1, &xy, npoints, _state)-refrms, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:399");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(knnavgerror(&model1, &xy, npoints, _state)-refavg, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:400");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(knnavgrelerror(&model1, &xy, npoints, _state)-refavgrel, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:401");
testknnunit_testseterrors(&model1, nvars, nout, iscls, &testxy, testnpoints, &refavgce, &refcls0, &refcls1, &refrms, &refavg, &refavgrel, _state);
knnallerrors(&model1, &testxy, testnpoints, &tstrep, _state);
if( iscls )
{
ae_set_error_flag(err, ae_fp_less(tstrep.relclserror,refcls0-1.0E-6), __FILE__, __LINE__, "testknnunit.ap:406");
ae_set_error_flag(err, ae_fp_greater(tstrep.relclserror,refcls1+1.0E-6), __FILE__, __LINE__, "testknnunit.ap:407");
}
else
{
ae_set_error_flag(err, ae_fp_neq(tstrep.avgce,(double)(0)), __FILE__, __LINE__, "testknnunit.ap:411");
ae_set_error_flag(err, ae_fp_neq(tstrep.relclserror,(double)(0)), __FILE__, __LINE__, "testknnunit.ap:412");
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(tstrep.rmserror-refrms, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:414");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(tstrep.avgerror-refavg, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:415");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(tstrep.avgrelerror-refavgrel, _state),1.0E-6), __FILE__, __LINE__, "testknnunit.ap:416");
}
/*
* Test that model built with K=1 and Eps=0 remembers all training cases
*/
for(nvars=1; nvars<=4; nvars++)
{
for(pass=0; pass<=10; pass++)
{
/*
* Prepare task
*/
npoints = 1+hqrnduniformi(&rs, 20, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
iscls = ae_true;
nout = 2+hqrnduniformi(&rs, 3, _state);
ny = 1;
}
else
{
iscls = ae_false;
nout = 1+hqrnduniformi(&rs, 3, _state);
ny = nout;
}
ae_matrix_set_length(&xy, npoints, nvars+ny, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = i*0.000001;
for(j=1; j<=nvars-1; j++)
{
xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
if( iscls )
{
xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nout, _state));
}
else
{
for(j=0; j<=nout-1; j++)
{
xy.ptr.pp_double[i][nvars+j] = hqrndnormal(&rs, _state);
}
}
}
/*
* Create model
*/
testknnunit_unsetknn(&model1, _state);
knnbuildercreate(&builder, _state);
if( iscls )
{
knnbuildersetdatasetcls(&builder, &xy, npoints, nvars, nout, _state);
}
else
{
knnbuildersetdatasetreg(&builder, &xy, npoints, nvars, nout, _state);
}
knnbuildersetnorm(&builder, hqrnduniformi(&rs, 3, _state), _state);
knnbuilderbuildknnmodel(&builder, 1, 0.0, &model1, &rep, _state);
ae_set_error_flag(err, ae_fp_greater(rep.avgce,(double)(0)), __FILE__, __LINE__, "testknnunit.ap:467");
ae_set_error_flag(err, ae_fp_greater(rep.relclserror,(double)(0)), __FILE__, __LINE__, "testknnunit.ap:468");
ae_set_error_flag(err, ae_fp_greater(rep.rmserror,1.0E-6), __FILE__, __LINE__, "testknnunit.ap:469");
ae_set_error_flag(err, ae_fp_greater(rep.avgerror,1.0E-6), __FILE__, __LINE__, "testknnunit.ap:470");
ae_set_error_flag(err, ae_fp_greater(rep.avgrelerror,1.0E-6), __FILE__, __LINE__, "testknnunit.ap:471");
ae_vector_set_length(&x1, nvars, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
x1.ptr.p_double[j] = xy.ptr.pp_double[i][j];
}
knnprocess(&model1, &x1, &y1, _state);
if( iscls )
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y1.ptr.p_double[ae_round(xy.ptr.pp_double[i][nvars], _state)]-1, _state),10*ae_machineepsilon), __FILE__, __LINE__, "testknnunit.ap:479");
}
else
{
for(j=0; j<=nout-1; j++)
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y1.ptr.p_double[j]-xy.ptr.pp_double[i][nvars+j], _state),10*ae_machineepsilon), __FILE__, __LINE__, "testknnunit.ap:483");
}
}
}
}
}
/*
* Test that model rewrite works as expected
*/
for(nvars=1; nvars<=20; nvars++)
{
/*
* Prepare task
*/
npoints = 50+5*nvars;
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
iscls = ae_true;
nout = 2+hqrnduniformi(&rs, 3, _state);
ny = 1;
}
else
{
iscls = ae_false;
nout = 1+hqrnduniformi(&rs, 3, _state);
ny = nout;
}
ae_matrix_set_length(&xy, npoints, nvars+ny, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
if( iscls )
{
xy.ptr.pp_double[i][nvars] = (double)(hqrnduniformi(&rs, nout, _state));
}
else
{
for(j=0; j<=nout-1; j++)
{
xy.ptr.pp_double[i][nvars+j] = hqrndnormal(&rs, _state);
}
}
}
/*
* Select K, Eps
*/
k = 1+hqrnduniformi(&rs, 10, _state);
eps = hqrnduniformi(&rs, 2, _state)*(1+3*hqrnduniformr(&rs, _state));
/*
* Create model 1 using K, EPS.
* Create model 2 using other (K,Eps), then rewrite search settings
*/
knnbuildercreate(&builder, _state);
if( iscls )
{
knnbuildersetdatasetcls(&builder, &xy, npoints, nvars, nout, _state);
}
else
{
knnbuildersetdatasetreg(&builder, &xy, npoints, nvars, nout, _state);
}
testknnunit_unsetknn(&model1, _state);
knnbuilderbuildknnmodel(&builder, k, eps, &model1, &rep, _state);
testknnunit_unsetknn(&model2, _state);
knnbuilderbuildknnmodel(&builder, 1+hqrnduniformi(&rs, 10, _state), hqrnduniformi(&rs, 2, _state)*(1+3*hqrnduniformr(&rs, _state)), &model2, &rep2, _state);
knnrewritekeps(&model2, k, eps, _state);
ae_vector_set_length(&x1, nvars, _state);
ae_vector_set_length(&x2, nvars, _state);
for(i=0; i<=nvars-1; i++)
{
x1.ptr.p_double[i] = hqrndnormal(&rs, _state);
x2.ptr.p_double[i] = x1.ptr.p_double[i];
}
knnprocess(&model1, &x1, &y1, _state);
knnprocess(&model2, &x2, &y2, _state);
for(i=0; i<=nout-1; i++)
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y1.ptr.p_double[i]-y2.ptr.p_double[i], _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testknnunit.ap:553");
}
}
/*
* Test generalization ability on a simple noisy classification task:
* * 00 results in worse error metrics, but not too bad
*/
/*
* Prepare task
*/
npoints = 5000;
ae_matrix_set_length(&xy, npoints, 3, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = 2*hqrnduniformr(&rs, _state)-1;
xy.ptr.pp_double[i][1] = 2*hqrnduniformr(&rs, _state)-1;
xy.ptr.pp_double[i][2] = ae_sqr(xy.ptr.pp_double[i][0], _state)+xy.ptr.pp_double[i][1];
}
/*
* Build model with Eps=0, check model quality
*/
k = 50;
testknnunit_unsetknn(&model1, _state);
knnbuildercreate(&builder, _state);
knnbuildersetdatasetreg(&builder, &xy, npoints, 2, 1, _state);
knnbuildersetnorm(&builder, hqrnduniformi(&rs, 3, _state), _state);
knnbuilderbuildknnmodel(&builder, k, 0.0, &model1, &rep, _state);
ae_vector_set_length(&x1, 2, _state);
maxerr = (double)(0);
avgerr = (double)(0);
cnt = 0;
for(i=0; i<=1000; i++)
{
/*
* NOTE: we test model in the inner points, it deteriorates near the bounds
*/
x1.ptr.p_double[0] = 0.8*(2*hqrnduniformr(&rs, _state)-1);
x1.ptr.p_double[1] = 0.8*(2*hqrnduniformr(&rs, _state)-1);
v = ae_sqr(x1.ptr.p_double[0], _state)+x1.ptr.p_double[1];
knnprocess(&model1, &x1, &y1, _state);
v = ae_fabs(y1.ptr.p_double[0]-v, _state);
maxerr = ae_maxreal(maxerr, v, _state);
avgerr = avgerr+v;
cnt = cnt+1;
}
avgerr = avgerr/cnt;
ae_set_error_flag(err, ae_fp_greater(maxerr,0.15), __FILE__, __LINE__, "testknnunit.ap:669");
ae_set_error_flag(err, ae_fp_greater(avgerr,0.05), __FILE__, __LINE__, "testknnunit.ap:670");
/*
* Build model with Eps=1.0, compare error metrics with Eps=0
*/
knnbuilderbuildknnmodel(&builder, k, 1.0, &model2, &rep2, _state);
ae_set_error_flag(err, ae_fp_less_eq(rep2.rmserror,rep.rmserror), __FILE__, __LINE__, "testknnunit.ap:676");
ae_set_error_flag(err, ae_fp_less_eq(rep2.rmserror,rep.rmserror+0.001), __FILE__, __LINE__, "testknnunit.ap:677");
ae_set_error_flag(err, ae_fp_greater_eq(rep2.rmserror,rep.rmserror+0.020), __FILE__, __LINE__, "testknnunit.ap:678");
ae_frame_leave(_state);
}
/*************************************************************************
Unsets model
*************************************************************************/
static void testknnunit_unsetknn(knnmodel* model, ae_state *_state)
{
ae_frame _frame_block;
ae_matrix xy;
knnbuilder builder;
knnreport rep;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
memset(&builder, 0, sizeof(builder));
memset(&rep, 0, sizeof(rep));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_knnbuilder_init(&builder, _state, ae_true);
_knnreport_init(&rep, _state, ae_true);
ae_matrix_set_length(&xy, 1, 2, _state);
xy.ptr.pp_double[0][0] = (double)(0);
xy.ptr.pp_double[0][1] = ae_randomreal(_state)-0.5;
knnbuildercreate(&builder, _state);
knnbuildersetdatasetreg(&builder, &xy, 1, 1, 1, _state);
knnbuilderbuildknnmodel(&builder, 1, (double)(0), model, &rep, _state);
model->nvars = -1;
model->nout = -1;
model->k = -1;
model->eps = (double)(0);
model->isdummy = ae_true;
ae_frame_leave(_state);
}
/*************************************************************************
Test set errors.
Computes test set errors:
* average cross-entropy
* relative classification error (a range [RelCls0,RelCls1] is returned
because classification error can be computed differently in the presence
of the ties). All possible values of the classification error, no matter
how ties are resolved, are guaranteed to be within [RelCls0,RelCls1].
*************************************************************************/
static void testknnunit_testseterrors(knnmodel* model,
ae_int_t nvars,
ae_int_t nout,
ae_bool iscls,
/* Real */ ae_matrix* xy,
ae_int_t npoints,
double* avgce,
double* relcls0,
double* relcls1,
double* rms,
double* avg,
double* avgrel,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector x;
ae_vector y;
ae_vector ey;
ae_int_t relcnt;
ae_int_t i;
ae_int_t j;
double v;
double mxy;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&ey, 0, sizeof(ey));
*avgce = 0;
*relcls0 = 0;
*relcls1 = 0;
*rms = 0;
*avg = 0;
*avgrel = 0;
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ey, 0, DT_REAL, _state, ae_true);
ae_vector_set_length(&x, nvars, _state);
ae_vector_set_length(&y, nout, _state);
ae_vector_set_length(&ey, nout, _state);
*avgce = (double)(0);
*relcls0 = (double)(0);
*relcls1 = (double)(0);
*rms = (double)(0);
*avg = (double)(0);
*avgrel = (double)(0);
relcnt = 0;
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nvars-1; j++)
{
x.ptr.p_double[j] = xy->ptr.pp_double[i][j];
}
knnprocess(model, &x, &y, _state);
if( iscls )
{
for(j=0; j<=nout-1; j++)
{
ey.ptr.p_double[j] = (double)(0);
}
ey.ptr.p_double[ae_round(xy->ptr.pp_double[i][nvars], _state)] = (double)(1);
}
else
{
for(j=0; j<=nout-1; j++)
{
ey.ptr.p_double[j] = xy->ptr.pp_double[i][nvars+j];
}
}
for(j=0; j<=nout-1; j++)
{
v = y.ptr.p_double[j]-ey.ptr.p_double[j];
if( iscls )
{
*avgce = *avgce-ey.ptr.p_double[j]*ae_log(y.ptr.p_double[j]+ae_minrealnumber, _state);
}
*rms = *rms+ae_sqr(v, _state);
*avg = *avg+ae_fabs(v, _state);
if( ae_fp_neq(ey.ptr.p_double[j],(double)(0)) )
{
*avgrel = *avgrel+ae_fabs(v/ey.ptr.p_double[j], _state);
relcnt = relcnt+1;
}
}
if( iscls )
{
mxy = (double)(0);
for(j=0; j<=nout-1; j++)
{
mxy = ae_maxreal(mxy, y.ptr.p_double[j], _state);
}
if( ae_fp_eq(y.ptr.p_double[ae_round(xy->ptr.pp_double[i][nvars], _state)],mxy) )
{
/*
* RelCls0 is NOT increased because correct value achieves maximum.
* However, if ties are present, we have to increase RelCls1, upper bound
* of the uncertainty interval for the classification error.
*/
for(j=0; j<=nout-1; j++)
{
if( j!=ae_round(xy->ptr.pp_double[i][nvars], _state)&&ae_fp_eq(y.ptr.p_double[j],mxy) )
{
*relcls1 = *relcls1+1;
break;
}
}
}
else
{
/*
* Both bounds of the error range are increased by 1
*/
*relcls0 = *relcls0+1;
*relcls1 = *relcls1+1;
}
}
}
*relcls0 = *relcls0/npoints;
*relcls1 = *relcls1/npoints;
*avgce = *avgce/npoints;
*rms = ae_sqrt(*rms/(npoints*nout), _state);
*avg = *avg/(npoints*nout);
*avgrel = *avgrel/coalesce((double)(relcnt), (double)(1), _state);
ae_frame_leave(_state);
}
static double testgqunit_mapkind(ae_int_t k, ae_state *_state);
static void testgqunit_buildgausslegendrequadrature(ae_int_t n,
/* Real */ ae_vector* x,
/* Real */ ae_vector* w,
ae_state *_state);
static void testgqunit_buildgaussjacobiquadrature(ae_int_t n,
double alpha,
double beta,
/* Real */ ae_vector* x,
/* Real */ ae_vector* w,
ae_state *_state);
static void testgqunit_buildgausslaguerrequadrature(ae_int_t n,
double alpha,
/* Real */ ae_vector* x,
/* Real */ ae_vector* w,
ae_state *_state);
static void testgqunit_buildgausshermitequadrature(ae_int_t n,
/* Real */ ae_vector* x,
/* Real */ ae_vector* w,
ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testgq(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_vector alpha;
ae_vector beta;
ae_vector x;
ae_vector w;
ae_vector x2;
ae_vector w2;
double err;
ae_int_t n;
ae_int_t i;
ae_int_t info;
ae_int_t akind;
ae_int_t bkind;
double alphac;
double betac;
double errtol;
double nonstricterrtol;
double stricterrtol;
ae_bool recerrors;
ae_bool specerrors;
ae_bool waserrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&alpha, 0, sizeof(alpha));
memset(&beta, 0, sizeof(beta));
memset(&x, 0, sizeof(x));
memset(&w, 0, sizeof(w));
memset(&x2, 0, sizeof(x2));
memset(&w2, 0, sizeof(w2));
ae_vector_init(&alpha, 0, DT_REAL, _state, ae_true);
ae_vector_init(&beta, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
recerrors = ae_false;
specerrors = ae_false;
waserrors = ae_false;
errtol = 1.0E-12;
nonstricterrtol = 1.0E-6;
stricterrtol = 1000*ae_machineepsilon;
/*
* Three tests for rec-based Gauss quadratures with known weights/nodes:
* 1. Gauss-Legendre with N=2
* 2. Gauss-Legendre with N=5
* 3. Gauss-Chebyshev with N=1, 2, 4, 8, ..., 512
*/
err = (double)(0);
ae_vector_set_length(&alpha, 2, _state);
ae_vector_set_length(&beta, 2, _state);
alpha.ptr.p_double[0] = (double)(0);
alpha.ptr.p_double[1] = (double)(0);
beta.ptr.p_double[1] = (double)1/(double)(4*1*1-1);
gqgeneraterec(&alpha, &beta, 2.0, 2, &info, &x, &w, _state);
if( info>0 )
{
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[0]+ae_sqrt((double)(3), _state)/3, _state), _state);
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[1]-ae_sqrt((double)(3), _state)/3, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[0]-1, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[1]-1, _state), _state);
for(i=0; i<=0; i++)
{
recerrors = recerrors||ae_fp_greater_eq(x.ptr.p_double[i],x.ptr.p_double[i+1]);
}
}
else
{
recerrors = ae_true;
}
ae_vector_set_length(&alpha, 5, _state);
ae_vector_set_length(&beta, 5, _state);
alpha.ptr.p_double[0] = (double)(0);
for(i=1; i<=4; i++)
{
alpha.ptr.p_double[i] = (double)(0);
beta.ptr.p_double[i] = ae_sqr((double)(i), _state)/(4*ae_sqr((double)(i), _state)-1);
}
gqgeneraterec(&alpha, &beta, 2.0, 5, &info, &x, &w, _state);
if( info>0 )
{
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[0]+ae_sqrt(245+14*ae_sqrt((double)(70), _state), _state)/21, _state), _state);
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[0]+x.ptr.p_double[4], _state), _state);
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[1]+ae_sqrt(245-14*ae_sqrt((double)(70), _state), _state)/21, _state), _state);
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[1]+x.ptr.p_double[3], _state), _state);
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[2], _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[0]-(322-13*ae_sqrt((double)(70), _state))/900, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[0]-w.ptr.p_double[4], _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[1]-(322+13*ae_sqrt((double)(70), _state))/900, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[1]-w.ptr.p_double[3], _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[2]-(double)128/(double)225, _state), _state);
for(i=0; i<=3; i++)
{
recerrors = recerrors||ae_fp_greater_eq(x.ptr.p_double[i],x.ptr.p_double[i+1]);
}
}
else
{
recerrors = ae_true;
}
n = 1;
while(n<=512)
{
ae_vector_set_length(&alpha, n, _state);
ae_vector_set_length(&beta, n, _state);
for(i=0; i<=n-1; i++)
{
alpha.ptr.p_double[i] = (double)(0);
if( i==0 )
{
beta.ptr.p_double[i] = (double)(0);
}
if( i==1 )
{
beta.ptr.p_double[i] = (double)1/(double)2;
}
if( i>1 )
{
beta.ptr.p_double[i] = (double)1/(double)4;
}
}
gqgeneraterec(&alpha, &beta, ae_pi, n, &info, &x, &w, _state);
if( info>0 )
{
for(i=0; i<=n-1; i++)
{
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[i]-ae_cos(ae_pi*(n-i-0.5)/n, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[i]-ae_pi/n, _state), _state);
}
for(i=0; i<=n-2; i++)
{
recerrors = recerrors||ae_fp_greater_eq(x.ptr.p_double[i],x.ptr.p_double[i+1]);
}
}
else
{
recerrors = ae_true;
}
n = n*2;
}
recerrors = recerrors||ae_fp_greater(err,errtol);
/*
* Three tests for rec-based Gauss-Lobatto quadratures with known weights/nodes:
* 1. Gauss-Lobatto with N=3
* 2. Gauss-Lobatto with N=4
* 3. Gauss-Lobatto with N=6
*/
err = (double)(0);
ae_vector_set_length(&alpha, 2, _state);
ae_vector_set_length(&beta, 2, _state);
alpha.ptr.p_double[0] = (double)(0);
alpha.ptr.p_double[1] = (double)(0);
beta.ptr.p_double[0] = (double)(0);
beta.ptr.p_double[1] = (double)(1*1)/(double)(4*1*1-1);
gqgenerategausslobattorec(&alpha, &beta, 2.0, (double)(-1), (double)(1), 3, &info, &x, &w, _state);
if( info>0 )
{
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[0]+1, _state), _state);
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[1], _state), _state);
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[2]-1, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[0]-(double)1/(double)3, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[1]-(double)4/(double)3, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[2]-(double)1/(double)3, _state), _state);
for(i=0; i<=1; i++)
{
recerrors = recerrors||ae_fp_greater_eq(x.ptr.p_double[i],x.ptr.p_double[i+1]);
}
}
else
{
recerrors = ae_true;
}
ae_vector_set_length(&alpha, 3, _state);
ae_vector_set_length(&beta, 3, _state);
alpha.ptr.p_double[0] = (double)(0);
alpha.ptr.p_double[1] = (double)(0);
alpha.ptr.p_double[2] = (double)(0);
beta.ptr.p_double[0] = (double)(0);
beta.ptr.p_double[1] = (double)(1*1)/(double)(4*1*1-1);
beta.ptr.p_double[2] = (double)(2*2)/(double)(4*2*2-1);
gqgenerategausslobattorec(&alpha, &beta, 2.0, (double)(-1), (double)(1), 4, &info, &x, &w, _state);
if( info>0 )
{
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[0]+1, _state), _state);
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[1]+ae_sqrt((double)(5), _state)/5, _state), _state);
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[2]-ae_sqrt((double)(5), _state)/5, _state), _state);
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[3]-1, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[0]-(double)1/(double)6, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[1]-(double)5/(double)6, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[2]-(double)5/(double)6, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[3]-(double)1/(double)6, _state), _state);
for(i=0; i<=2; i++)
{
recerrors = recerrors||ae_fp_greater_eq(x.ptr.p_double[i],x.ptr.p_double[i+1]);
}
}
else
{
recerrors = ae_true;
}
ae_vector_set_length(&alpha, 5, _state);
ae_vector_set_length(&beta, 5, _state);
alpha.ptr.p_double[0] = (double)(0);
alpha.ptr.p_double[1] = (double)(0);
alpha.ptr.p_double[2] = (double)(0);
alpha.ptr.p_double[3] = (double)(0);
alpha.ptr.p_double[4] = (double)(0);
beta.ptr.p_double[0] = (double)(0);
beta.ptr.p_double[1] = (double)(1*1)/(double)(4*1*1-1);
beta.ptr.p_double[2] = (double)(2*2)/(double)(4*2*2-1);
beta.ptr.p_double[3] = (double)(3*3)/(double)(4*3*3-1);
beta.ptr.p_double[4] = (double)(4*4)/(double)(4*4*4-1);
gqgenerategausslobattorec(&alpha, &beta, 2.0, (double)(-1), (double)(1), 6, &info, &x, &w, _state);
if( info>0 )
{
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[0]+1, _state), _state);
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[1]+ae_sqrt((7+2*ae_sqrt((double)(7), _state))/21, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[2]+ae_sqrt((7-2*ae_sqrt((double)(7), _state))/21, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[3]-ae_sqrt((7-2*ae_sqrt((double)(7), _state))/21, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[4]-ae_sqrt((7+2*ae_sqrt((double)(7), _state))/21, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[5]-1, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[0]-(double)1/(double)15, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[1]-(14-ae_sqrt((double)(7), _state))/30, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[2]-(14+ae_sqrt((double)(7), _state))/30, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[3]-(14+ae_sqrt((double)(7), _state))/30, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[4]-(14-ae_sqrt((double)(7), _state))/30, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[5]-(double)1/(double)15, _state), _state);
for(i=0; i<=4; i++)
{
recerrors = recerrors||ae_fp_greater_eq(x.ptr.p_double[i],x.ptr.p_double[i+1]);
}
}
else
{
recerrors = ae_true;
}
recerrors = recerrors||ae_fp_greater(err,errtol);
/*
* Three tests for rec-based Gauss-Radau quadratures with known weights/nodes:
* 1. Gauss-Radau with N=2
* 2. Gauss-Radau with N=3
* 3. Gauss-Radau with N=3 (another case)
*/
err = (double)(0);
ae_vector_set_length(&alpha, 1, _state);
ae_vector_set_length(&beta, 2, _state);
alpha.ptr.p_double[0] = (double)(0);
beta.ptr.p_double[0] = (double)(0);
beta.ptr.p_double[1] = (double)(1*1)/(double)(4*1*1-1);
gqgenerategaussradaurec(&alpha, &beta, 2.0, (double)(-1), 2, &info, &x, &w, _state);
if( info>0 )
{
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[0]+1, _state), _state);
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[1]-(double)1/(double)3, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[0]-0.5, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[1]-1.5, _state), _state);
for(i=0; i<=0; i++)
{
recerrors = recerrors||ae_fp_greater_eq(x.ptr.p_double[i],x.ptr.p_double[i+1]);
}
}
else
{
recerrors = ae_true;
}
ae_vector_set_length(&alpha, 2, _state);
ae_vector_set_length(&beta, 3, _state);
alpha.ptr.p_double[0] = (double)(0);
alpha.ptr.p_double[1] = (double)(0);
for(i=0; i<=2; i++)
{
beta.ptr.p_double[i] = ae_sqr((double)(i), _state)/(4*ae_sqr((double)(i), _state)-1);
}
gqgenerategaussradaurec(&alpha, &beta, 2.0, (double)(-1), 3, &info, &x, &w, _state);
if( info>0 )
{
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[0]+1, _state), _state);
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[1]-(1-ae_sqrt((double)(6), _state))/5, _state), _state);
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[2]-(1+ae_sqrt((double)(6), _state))/5, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[0]-(double)2/(double)9, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[1]-(16+ae_sqrt((double)(6), _state))/18, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[2]-(16-ae_sqrt((double)(6), _state))/18, _state), _state);
for(i=0; i<=1; i++)
{
recerrors = recerrors||ae_fp_greater_eq(x.ptr.p_double[i],x.ptr.p_double[i+1]);
}
}
else
{
recerrors = ae_true;
}
ae_vector_set_length(&alpha, 2, _state);
ae_vector_set_length(&beta, 3, _state);
alpha.ptr.p_double[0] = (double)(0);
alpha.ptr.p_double[1] = (double)(0);
for(i=0; i<=2; i++)
{
beta.ptr.p_double[i] = ae_sqr((double)(i), _state)/(4*ae_sqr((double)(i), _state)-1);
}
gqgenerategaussradaurec(&alpha, &beta, 2.0, (double)(1), 3, &info, &x, &w, _state);
if( info>0 )
{
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[2]-1, _state), _state);
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[1]+(1-ae_sqrt((double)(6), _state))/5, _state), _state);
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[0]+(1+ae_sqrt((double)(6), _state))/5, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[2]-(double)2/(double)9, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[1]-(16+ae_sqrt((double)(6), _state))/18, _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[0]-(16-ae_sqrt((double)(6), _state))/18, _state), _state);
for(i=0; i<=1; i++)
{
recerrors = recerrors||ae_fp_greater_eq(x.ptr.p_double[i],x.ptr.p_double[i+1]);
}
}
else
{
recerrors = ae_true;
}
recerrors = recerrors||ae_fp_greater(err,errtol);
/*
* test recurrence-based special cases (Legendre, Jacobi, Hermite, ...)
* against another implementation (polynomial root-finder)
*/
for(n=1; n<=20; n++)
{
/*
* test gauss-legendre
*/
err = (double)(0);
gqgenerategausslegendre(n, &info, &x, &w, _state);
if( info>0 )
{
testgqunit_buildgausslegendrequadrature(n, &x2, &w2, _state);
for(i=0; i<=n-1; i++)
{
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[i]-x2.ptr.p_double[i], _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[i]-w2.ptr.p_double[i], _state), _state);
}
}
else
{
specerrors = ae_true;
}
specerrors = specerrors||ae_fp_greater(err,errtol);
/*
* Test Gauss-Jacobi.
* Since task is much more difficult we will use less strict
* threshold.
*/
err = (double)(0);
for(akind=0; akind<=9; akind++)
{
for(bkind=0; bkind<=9; bkind++)
{
alphac = testgqunit_mapkind(akind, _state);
betac = testgqunit_mapkind(bkind, _state);
gqgenerategaussjacobi(n, alphac, betac, &info, &x, &w, _state);
if( info>0 )
{
testgqunit_buildgaussjacobiquadrature(n, alphac, betac, &x2, &w2, _state);
for(i=0; i<=n-1; i++)
{
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[i]-x2.ptr.p_double[i], _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[i]-w2.ptr.p_double[i], _state), _state);
}
}
else
{
specerrors = ae_true;
}
}
}
specerrors = specerrors||ae_fp_greater(err,nonstricterrtol);
/*
* special test for Gauss-Jacobi (Chebyshev weight
* function with analytically known nodes/weights)
*/
err = (double)(0);
gqgenerategaussjacobi(n, -0.5, -0.5, &info, &x, &w, _state);
if( info>0 )
{
for(i=0; i<=n-1; i++)
{
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[i]+ae_cos(ae_pi*(i+0.5)/n, _state), _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[i]-ae_pi/n, _state), _state);
}
}
else
{
specerrors = ae_true;
}
specerrors = specerrors||ae_fp_greater(err,stricterrtol);
/*
* Test Gauss-Laguerre
*/
err = (double)(0);
for(akind=0; akind<=9; akind++)
{
alphac = testgqunit_mapkind(akind, _state);
gqgenerategausslaguerre(n, alphac, &info, &x, &w, _state);
if( info>0 )
{
testgqunit_buildgausslaguerrequadrature(n, alphac, &x2, &w2, _state);
for(i=0; i<=n-1; i++)
{
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[i]-x2.ptr.p_double[i], _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[i]-w2.ptr.p_double[i], _state), _state);
}
}
else
{
specerrors = ae_true;
}
}
specerrors = specerrors||ae_fp_greater(err,nonstricterrtol);
/*
* Test Gauss-Hermite
*/
err = (double)(0);
gqgenerategausshermite(n, &info, &x, &w, _state);
if( info>0 )
{
testgqunit_buildgausshermitequadrature(n, &x2, &w2, _state);
for(i=0; i<=n-1; i++)
{
err = ae_maxreal(err, ae_fabs(x.ptr.p_double[i]-x2.ptr.p_double[i], _state), _state);
err = ae_maxreal(err, ae_fabs(w.ptr.p_double[i]-w2.ptr.p_double[i], _state), _state);
}
}
else
{
specerrors = ae_true;
}
specerrors = specerrors||ae_fp_greater(err,nonstricterrtol);
}
/*
* end
*/
waserrors = recerrors||specerrors;
if( !silent )
{
printf("TESTING GAUSS QUADRATURES\n");
printf("FINAL RESULT: ");
if( waserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* SPECIAL CASES (LEGENDRE/JACOBI/..) ");
if( specerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* RECURRENCE-BASED: ");
if( recerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Maps:
0 => -0.9
1 => -0.5
2 => -0.1
3 => 0.0
4 => +0.1
5 => +0.5
6 => +0.9
7 => +1.0
8 => +1.5
9 => +2.0
*************************************************************************/
static double testgqunit_mapkind(ae_int_t k, ae_state *_state)
{
double result;
result = (double)(0);
if( k==0 )
{
result = -0.9;
}
if( k==1 )
{
result = -0.5;
}
if( k==2 )
{
result = -0.1;
}
if( k==3 )
{
result = 0.0;
}
if( k==4 )
{
result = 0.1;
}
if( k==5 )
{
result = 0.5;
}
if( k==6 )
{
result = 0.9;
}
if( k==7 )
{
result = 1.0;
}
if( k==8 )
{
result = 1.5;
}
if( k==9 )
{
result = 2.0;
}
return result;
}
/*************************************************************************
Gauss-Legendre, another variant
*************************************************************************/
static void testgqunit_buildgausslegendrequadrature(ae_int_t n,
/* Real */ ae_vector* x,
/* Real */ ae_vector* w,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
double r;
double r1;
double p1;
double p2;
double p3;
double dp3;
double tmp;
ae_vector_clear(x);
ae_vector_clear(w);
ae_vector_set_length(x, n-1+1, _state);
ae_vector_set_length(w, n-1+1, _state);
for(i=0; i<=(n+1)/2-1; i++)
{
r = ae_cos(ae_pi*(4*i+3)/(4*n+2), _state);
do
{
p2 = (double)(0);
p3 = (double)(1);
for(j=0; j<=n-1; j++)
{
p1 = p2;
p2 = p3;
p3 = ((2*j+1)*r*p2-j*p1)/(j+1);
}
dp3 = n*(r*p3-p2)/(r*r-1);
r1 = r;
r = r-p3/dp3;
}
while(ae_fp_greater_eq(ae_fabs(r-r1, _state),ae_machineepsilon*(1+ae_fabs(r, _state))*100));
x->ptr.p_double[i] = r;
x->ptr.p_double[n-1-i] = -r;
w->ptr.p_double[i] = 2/((1-r*r)*dp3*dp3);
w->ptr.p_double[n-1-i] = 2/((1-r*r)*dp3*dp3);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-2-i; j++)
{
if( ae_fp_greater_eq(x->ptr.p_double[j],x->ptr.p_double[j+1]) )
{
tmp = x->ptr.p_double[j];
x->ptr.p_double[j] = x->ptr.p_double[j+1];
x->ptr.p_double[j+1] = tmp;
tmp = w->ptr.p_double[j];
w->ptr.p_double[j] = w->ptr.p_double[j+1];
w->ptr.p_double[j+1] = tmp;
}
}
}
}
/*************************************************************************
Gauss-Jacobi, another variant
*************************************************************************/
static void testgqunit_buildgaussjacobiquadrature(ae_int_t n,
double alpha,
double beta,
/* Real */ ae_vector* x,
/* Real */ ae_vector* w,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
double r;
double r1;
double t1;
double t2;
double t3;
double p1;
double p2;
double p3;
double pp;
double an;
double bn;
double a;
double b;
double c;
double tmpsgn;
double tmp;
double alfbet;
double temp;
ae_vector_clear(x);
ae_vector_clear(w);
ae_vector_set_length(x, n-1+1, _state);
ae_vector_set_length(w, n-1+1, _state);
r = (double)(0);
for(i=0; i<=n-1; i++)
{
if( i==0 )
{
an = alpha/n;
bn = beta/n;
t1 = (1+alpha)*(2.78/(4+n*n)+0.768*an/n);
t2 = 1+1.48*an+0.96*bn+0.452*an*an+0.83*an*bn;
r = (t2-t1)/t2;
}
else
{
if( i==1 )
{
t1 = (4.1+alpha)/((1+alpha)*(1+0.156*alpha));
t2 = 1+0.06*(n-8)*(1+0.12*alpha)/n;
t3 = 1+0.012*beta*(1+0.25*ae_fabs(alpha, _state))/n;
r = r-t1*t2*t3*(1-r);
}
else
{
if( i==2 )
{
t1 = (1.67+0.28*alpha)/(1+0.37*alpha);
t2 = 1+0.22*(n-8)/n;
t3 = 1+8*beta/((6.28+beta)*n*n);
r = r-t1*t2*t3*(x->ptr.p_double[0]-r);
}
else
{
if( iptr.p_double[i-1]-3*x->ptr.p_double[i-2]+x->ptr.p_double[i-3];
}
else
{
if( i==n-2 )
{
t1 = (1+0.235*beta)/(0.766+0.119*beta);
t2 = 1/(1+0.639*(n-4)/(1+0.71*(n-4)));
t3 = 1/(1+20*alpha/((7.5+alpha)*n*n));
r = r+t1*t2*t3*(r-x->ptr.p_double[i-2]);
}
else
{
if( i==n-1 )
{
t1 = (1+0.37*beta)/(1.67+0.28*beta);
t2 = 1/(1+0.22*(n-8)/n);
t3 = 1/(1+8*alpha/((6.28+alpha)*n*n));
r = r+t1*t2*t3*(r-x->ptr.p_double[i-2]);
}
}
}
}
}
}
alfbet = alpha+beta;
do
{
temp = 2+alfbet;
p1 = (alpha-beta+temp*r)*0.5;
p2 = (double)(1);
for(j=2; j<=n; j++)
{
p3 = p2;
p2 = p1;
temp = 2*j+alfbet;
a = 2*j*(j+alfbet)*(temp-2);
b = (temp-1)*(alpha*alpha-beta*beta+temp*(temp-2)*r);
c = 2*(j-1+alpha)*(j-1+beta)*temp;
p1 = (b*p2-c*p3)/a;
}
pp = (n*(alpha-beta-temp*r)*p1+2*(n+alpha)*(n+beta)*p2)/(temp*(1-r*r));
r1 = r;
r = r1-p1/pp;
}
while(ae_fp_greater_eq(ae_fabs(r-r1, _state),ae_machineepsilon*(1+ae_fabs(r, _state))*100));
x->ptr.p_double[i] = r;
w->ptr.p_double[i] = ae_exp(lngamma(alpha+n, &tmpsgn, _state)+lngamma(beta+n, &tmpsgn, _state)-lngamma((double)(n+1), &tmpsgn, _state)-lngamma(n+alfbet+1, &tmpsgn, _state), _state)*temp*ae_pow((double)(2), alfbet, _state)/(pp*p2);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-2-i; j++)
{
if( ae_fp_greater_eq(x->ptr.p_double[j],x->ptr.p_double[j+1]) )
{
tmp = x->ptr.p_double[j];
x->ptr.p_double[j] = x->ptr.p_double[j+1];
x->ptr.p_double[j+1] = tmp;
tmp = w->ptr.p_double[j];
w->ptr.p_double[j] = w->ptr.p_double[j+1];
w->ptr.p_double[j+1] = tmp;
}
}
}
}
/*************************************************************************
Gauss-Laguerre, another variant
*************************************************************************/
static void testgqunit_buildgausslaguerrequadrature(ae_int_t n,
double alpha,
/* Real */ ae_vector* x,
/* Real */ ae_vector* w,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
double r;
double r1;
double p1;
double p2;
double p3;
double dp3;
double tsg;
double tmp;
ae_vector_clear(x);
ae_vector_clear(w);
ae_vector_set_length(x, n-1+1, _state);
ae_vector_set_length(w, n-1+1, _state);
r = (double)(0);
for(i=0; i<=n-1; i++)
{
if( i==0 )
{
r = (1+alpha)*(3+0.92*alpha)/(1+2.4*n+1.8*alpha);
}
else
{
if( i==1 )
{
r = r+(15+6.25*alpha)/(1+0.9*alpha+2.5*n);
}
else
{
r = r+((1+2.55*(i-1))/(1.9*(i-1))+1.26*(i-1)*alpha/(1+3.5*(i-1)))/(1+0.3*alpha)*(r-x->ptr.p_double[i-2]);
}
}
do
{
p2 = (double)(0);
p3 = (double)(1);
for(j=0; j<=n-1; j++)
{
p1 = p2;
p2 = p3;
p3 = ((-r+2*j+alpha+1)*p2-(j+alpha)*p1)/(j+1);
}
dp3 = (n*p3-(n+alpha)*p2)/r;
r1 = r;
r = r-p3/dp3;
}
while(ae_fp_greater_eq(ae_fabs(r-r1, _state),ae_machineepsilon*(1+ae_fabs(r, _state))*100));
x->ptr.p_double[i] = r;
w->ptr.p_double[i] = -ae_exp(lngamma(alpha+n, &tsg, _state)-lngamma((double)(n), &tsg, _state), _state)/(dp3*n*p2);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-2-i; j++)
{
if( ae_fp_greater_eq(x->ptr.p_double[j],x->ptr.p_double[j+1]) )
{
tmp = x->ptr.p_double[j];
x->ptr.p_double[j] = x->ptr.p_double[j+1];
x->ptr.p_double[j+1] = tmp;
tmp = w->ptr.p_double[j];
w->ptr.p_double[j] = w->ptr.p_double[j+1];
w->ptr.p_double[j+1] = tmp;
}
}
}
}
/*************************************************************************
Gauss-Hermite, another variant
*************************************************************************/
static void testgqunit_buildgausshermitequadrature(ae_int_t n,
/* Real */ ae_vector* x,
/* Real */ ae_vector* w,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
double r;
double r1;
double p1;
double p2;
double p3;
double dp3;
double pipm4;
double tmp;
ae_vector_clear(x);
ae_vector_clear(w);
ae_vector_set_length(x, n-1+1, _state);
ae_vector_set_length(w, n-1+1, _state);
pipm4 = ae_pow(ae_pi, -0.25, _state);
r = (double)(0);
for(i=0; i<=(n+1)/2-1; i++)
{
if( i==0 )
{
r = ae_sqrt((double)(2*n+1), _state)-1.85575*ae_pow((double)(2*n+1), -(double)1/(double)6, _state);
}
else
{
if( i==1 )
{
r = r-1.14*ae_pow((double)(n), 0.426, _state)/r;
}
else
{
if( i==2 )
{
r = 1.86*r-0.86*x->ptr.p_double[0];
}
else
{
if( i==3 )
{
r = 1.91*r-0.91*x->ptr.p_double[1];
}
else
{
r = 2*r-x->ptr.p_double[i-2];
}
}
}
}
do
{
p2 = (double)(0);
p3 = pipm4;
for(j=0; j<=n-1; j++)
{
p1 = p2;
p2 = p3;
p3 = p2*r*ae_sqrt((double)2/(double)(j+1), _state)-p1*ae_sqrt((double)j/(double)(j+1), _state);
}
dp3 = ae_sqrt((double)(2*j), _state)*p2;
r1 = r;
r = r-p3/dp3;
}
while(ae_fp_greater_eq(ae_fabs(r-r1, _state),ae_machineepsilon*(1+ae_fabs(r, _state))*100));
x->ptr.p_double[i] = r;
w->ptr.p_double[i] = 2/(dp3*dp3);
x->ptr.p_double[n-1-i] = -x->ptr.p_double[i];
w->ptr.p_double[n-1-i] = w->ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-2-i; j++)
{
if( ae_fp_greater_eq(x->ptr.p_double[j],x->ptr.p_double[j+1]) )
{
tmp = x->ptr.p_double[j];
x->ptr.p_double[j] = x->ptr.p_double[j+1];
x->ptr.p_double[j+1] = tmp;
tmp = w->ptr.p_double[j];
w->ptr.p_double[j] = w->ptr.p_double[j+1];
w->ptr.p_double[j+1] = tmp;
}
}
}
}
static double testgkqunit_mapkind(ae_int_t k, ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testgkq(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t pkind;
double errtol;
double eps;
ae_int_t n;
ae_int_t i;
ae_int_t k;
ae_int_t info;
double err;
ae_int_t akind;
ae_int_t bkind;
double alphac;
double betac;
ae_vector x1;
ae_vector wg1;
ae_vector wk1;
ae_vector x2;
ae_vector wg2;
ae_vector wk2;
ae_int_t info1;
ae_int_t info2;
ae_bool successatleastonce;
ae_bool intblerrors;
ae_bool vstblerrors;
ae_bool generrors;
ae_bool waserrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&x1, 0, sizeof(x1));
memset(&wg1, 0, sizeof(wg1));
memset(&wk1, 0, sizeof(wk1));
memset(&x2, 0, sizeof(x2));
memset(&wg2, 0, sizeof(wg2));
memset(&wk2, 0, sizeof(wk2));
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&wg1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&wk1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&wg2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&wk2, 0, DT_REAL, _state, ae_true);
intblerrors = ae_false;
vstblerrors = ae_false;
generrors = ae_false;
waserrors = ae_false;
errtol = 10000*ae_machineepsilon;
/*
* test recurrence-based Legendre nodes against the precalculated table
*/
for(pkind=0; pkind<=5; pkind++)
{
n = 0;
if( pkind==0 )
{
n = 15;
}
if( pkind==1 )
{
n = 21;
}
if( pkind==2 )
{
n = 31;
}
if( pkind==3 )
{
n = 41;
}
if( pkind==4 )
{
n = 51;
}
if( pkind==5 )
{
n = 61;
}
gkqlegendrecalc(n, &info, &x1, &wk1, &wg1, _state);
gkqlegendretbl(n, &x2, &wk2, &wg2, &eps, _state);
if( info<=0 )
{
generrors = ae_true;
break;
}
for(i=0; i<=n-1; i++)
{
vstblerrors = vstblerrors||ae_fp_greater(ae_fabs(x1.ptr.p_double[i]-x2.ptr.p_double[i], _state),errtol);
vstblerrors = vstblerrors||ae_fp_greater(ae_fabs(wk1.ptr.p_double[i]-wk2.ptr.p_double[i], _state),errtol);
vstblerrors = vstblerrors||ae_fp_greater(ae_fabs(wg1.ptr.p_double[i]-wg2.ptr.p_double[i], _state),errtol);
}
}
/*
* Test recurrence-baced Gauss-Kronrod nodes against Gauss-only nodes
* calculated with subroutines from GQ unit.
*/
for(k=1; k<=30; k++)
{
n = 2*k+1;
/*
* Gauss-Legendre
*/
err = (double)(0);
gkqgenerategausslegendre(n, &info1, &x1, &wk1, &wg1, _state);
gqgenerategausslegendre(k, &info2, &x2, &wg2, _state);
if( info1>0&&info2>0 )
{
for(i=0; i<=k-1; i++)
{
err = ae_maxreal(err, ae_fabs(x1.ptr.p_double[2*i+1]-x2.ptr.p_double[i], _state), _state);
err = ae_maxreal(err, ae_fabs(wg1.ptr.p_double[2*i+1]-wg2.ptr.p_double[i], _state), _state);
}
}
else
{
generrors = ae_true;
}
generrors = generrors||ae_fp_greater(err,errtol);
}
for(k=1; k<=15; k++)
{
n = 2*k+1;
/*
* Gauss-Jacobi
*/
successatleastonce = ae_false;
err = (double)(0);
for(akind=0; akind<=9; akind++)
{
for(bkind=0; bkind<=9; bkind++)
{
alphac = testgkqunit_mapkind(akind, _state);
betac = testgkqunit_mapkind(bkind, _state);
gkqgenerategaussjacobi(n, alphac, betac, &info1, &x1, &wk1, &wg1, _state);
gqgenerategaussjacobi(k, alphac, betac, &info2, &x2, &wg2, _state);
if( info1>0&&info2>0 )
{
successatleastonce = ae_true;
for(i=0; i<=k-1; i++)
{
err = ae_maxreal(err, ae_fabs(x1.ptr.p_double[2*i+1]-x2.ptr.p_double[i], _state), _state);
err = ae_maxreal(err, ae_fabs(wg1.ptr.p_double[2*i+1]-wg2.ptr.p_double[i], _state), _state);
}
}
else
{
generrors = generrors||info1!=-5;
}
}
}
generrors = (generrors||ae_fp_greater(err,errtol))||!successatleastonce;
}
/*
* end
*/
waserrors = (intblerrors||vstblerrors)||generrors;
if( !silent )
{
printf("TESTING GAUSS-KRONROD QUADRATURES\n");
printf("FINAL RESULT: ");
if( waserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* PRE-CALCULATED TABLE: ");
if( intblerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* CALCULATED AGAINST THE TABLE: ");
if( vstblerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* GENERAL PROPERTIES: ");
if( generrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Maps:
0 => -0.9
1 => -0.5
2 => -0.1
3 => 0.0
4 => +0.1
5 => +0.5
6 => +0.9
7 => +1.0
8 => +1.5
9 => +2.0
*************************************************************************/
static double testgkqunit_mapkind(ae_int_t k, ae_state *_state)
{
double result;
result = (double)(0);
if( k==0 )
{
result = -0.9;
}
if( k==1 )
{
result = -0.5;
}
if( k==2 )
{
result = -0.1;
}
if( k==3 )
{
result = 0.0;
}
if( k==4 )
{
result = 0.1;
}
if( k==5 )
{
result = 0.5;
}
if( k==6 )
{
result = 0.9;
}
if( k==7 )
{
result = 1.0;
}
if( k==8 )
{
result = 1.5;
}
if( k==9 )
{
result = 2.0;
}
return result;
}
/*************************************************************************
Test
*************************************************************************/
ae_bool testautogk(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
double a;
double b;
autogkstate state;
autogkreport rep;
double v;
double exact;
double eabs;
double alpha;
ae_int_t pkind;
double errtol;
ae_bool simpleerrors;
ae_bool sngenderrors;
ae_bool waserrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
_autogkstate_init(&state, _state, ae_true);
_autogkreport_init(&rep, _state, ae_true);
simpleerrors = ae_false;
sngenderrors = ae_false;
waserrors = ae_false;
errtol = 10000*ae_machineepsilon;
/*
* Simple test: integral(exp(x),+-1,+-2), no maximum width requirements
*/
a = (2*ae_randominteger(2, _state)-1)*1.0;
b = (2*ae_randominteger(2, _state)-1)*2.0;
autogksmooth(a, b, &state, _state);
while(autogkiteration(&state, _state))
{
state.f = ae_exp(state.x, _state);
}
autogkresults(&state, &v, &rep, _state);
exact = ae_exp(b, _state)-ae_exp(a, _state);
eabs = ae_fabs(ae_exp(b, _state)-ae_exp(a, _state), _state);
if( rep.terminationtype<=0 )
{
simpleerrors = ae_true;
}
else
{
simpleerrors = simpleerrors||ae_fp_greater(ae_fabs(exact-v, _state),errtol*eabs);
}
/*
* Simple test: integral(exp(x),+-1,+-2), XWidth=0.1
*/
a = (2*ae_randominteger(2, _state)-1)*1.0;
b = (2*ae_randominteger(2, _state)-1)*2.0;
autogksmoothw(a, b, 0.1, &state, _state);
while(autogkiteration(&state, _state))
{
state.f = ae_exp(state.x, _state);
}
autogkresults(&state, &v, &rep, _state);
exact = ae_exp(b, _state)-ae_exp(a, _state);
eabs = ae_fabs(ae_exp(b, _state)-ae_exp(a, _state), _state);
if( rep.terminationtype<=0 )
{
simpleerrors = ae_true;
}
else
{
simpleerrors = simpleerrors||ae_fp_greater(ae_fabs(exact-v, _state),errtol*eabs);
}
/*
* Simple test: integral(cos(100*x),0,2*pi), no maximum width requirements
*/
a = (double)(0);
b = 2*ae_pi;
autogksmooth(a, b, &state, _state);
while(autogkiteration(&state, _state))
{
state.f = ae_cos(100*state.x, _state);
}
autogkresults(&state, &v, &rep, _state);
exact = (double)(0);
eabs = (double)(4);
if( rep.terminationtype<=0 )
{
simpleerrors = ae_true;
}
else
{
simpleerrors = simpleerrors||ae_fp_greater(ae_fabs(exact-v, _state),errtol*eabs);
}
/*
* Simple test: integral(cos(100*x),0,2*pi), XWidth=0.3
*/
a = (double)(0);
b = 2*ae_pi;
autogksmoothw(a, b, 0.3, &state, _state);
while(autogkiteration(&state, _state))
{
state.f = ae_cos(100*state.x, _state);
}
autogkresults(&state, &v, &rep, _state);
exact = (double)(0);
eabs = (double)(4);
if( rep.terminationtype<=0 )
{
simpleerrors = ae_true;
}
else
{
simpleerrors = simpleerrors||ae_fp_greater(ae_fabs(exact-v, _state),errtol*eabs);
}
/*
* singular problem on [a,b] = [0.1, 0.5]
* f2(x) = (1+x)*(b-x)^alpha, -1 < alpha < 1
*/
for(pkind=0; pkind<=6; pkind++)
{
a = 0.1;
b = 0.5;
alpha = 0.0;
if( pkind==0 )
{
alpha = -0.9;
}
if( pkind==1 )
{
alpha = -0.5;
}
if( pkind==2 )
{
alpha = -0.1;
}
if( pkind==3 )
{
alpha = 0.0;
}
if( pkind==4 )
{
alpha = 0.1;
}
if( pkind==5 )
{
alpha = 0.5;
}
if( pkind==6 )
{
alpha = 0.9;
}
/*
* f1(x) = (1+x)*(x-a)^alpha, -1 < alpha < 1
* 1. use singular integrator for [a,b]
* 2. use singular integrator for [b,a]
*/
exact = ae_pow(b-a, alpha+2, _state)/(alpha+2)+(1+a)*ae_pow(b-a, alpha+1, _state)/(alpha+1);
eabs = ae_fabs(exact, _state);
autogksingular(a, b, alpha, 0.0, &state, _state);
while(autogkiteration(&state, _state))
{
if( ae_fp_less(state.xminusa,0.01) )
{
state.f = ae_pow(state.xminusa, alpha, _state)*(1+state.x);
}
else
{
state.f = ae_pow(state.x-a, alpha, _state)*(1+state.x);
}
}
autogkresults(&state, &v, &rep, _state);
if( rep.terminationtype<=0 )
{
sngenderrors = ae_true;
}
else
{
sngenderrors = sngenderrors||ae_fp_greater(ae_fabs(v-exact, _state),errtol*eabs);
}
autogksingular(b, a, 0.0, alpha, &state, _state);
while(autogkiteration(&state, _state))
{
if( ae_fp_greater(state.bminusx,-0.01) )
{
state.f = ae_pow(-state.bminusx, alpha, _state)*(1+state.x);
}
else
{
state.f = ae_pow(state.x-a, alpha, _state)*(1+state.x);
}
}
autogkresults(&state, &v, &rep, _state);
if( rep.terminationtype<=0 )
{
sngenderrors = ae_true;
}
else
{
sngenderrors = sngenderrors||ae_fp_greater(ae_fabs(-v-exact, _state),errtol*eabs);
}
/*
* f1(x) = (1+x)*(b-x)^alpha, -1 < alpha < 1
* 1. use singular integrator for [a,b]
* 2. use singular integrator for [b,a]
*/
exact = (1+b)*ae_pow(b-a, alpha+1, _state)/(alpha+1)-ae_pow(b-a, alpha+2, _state)/(alpha+2);
eabs = ae_fabs(exact, _state);
autogksingular(a, b, 0.0, alpha, &state, _state);
while(autogkiteration(&state, _state))
{
if( ae_fp_less(state.bminusx,0.01) )
{
state.f = ae_pow(state.bminusx, alpha, _state)*(1+state.x);
}
else
{
state.f = ae_pow(b-state.x, alpha, _state)*(1+state.x);
}
}
autogkresults(&state, &v, &rep, _state);
if( rep.terminationtype<=0 )
{
sngenderrors = ae_true;
}
else
{
sngenderrors = sngenderrors||ae_fp_greater(ae_fabs(v-exact, _state),errtol*eabs);
}
autogksingular(b, a, alpha, 0.0, &state, _state);
while(autogkiteration(&state, _state))
{
if( ae_fp_greater(state.xminusa,-0.01) )
{
state.f = ae_pow(-state.xminusa, alpha, _state)*(1+state.x);
}
else
{
state.f = ae_pow(b-state.x, alpha, _state)*(1+state.x);
}
}
autogkresults(&state, &v, &rep, _state);
if( rep.terminationtype<=0 )
{
sngenderrors = ae_true;
}
else
{
sngenderrors = sngenderrors||ae_fp_greater(ae_fabs(-v-exact, _state),errtol*eabs);
}
}
/*
* end
*/
waserrors = simpleerrors||sngenderrors;
if( !silent )
{
printf("TESTING AUTOGK\n");
printf("INTEGRATION WITH GIVEN ACCURACY: ");
if( simpleerrors||sngenderrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* SIMPLE PROBLEMS: ");
if( simpleerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* SINGULAR PROBLEMS (ENDS OF INTERVAL): ");
if( sngenderrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
static void testfftunit_reffftc1d(/* Complex */ ae_vector* a,
ae_int_t n,
ae_state *_state);
static void testfftunit_reffftc1dinv(/* Complex */ ae_vector* a,
ae_int_t n,
ae_state *_state);
static void testfftunit_refinternalcfft(/* Real */ ae_vector* a,
ae_int_t nn,
ae_bool inversefft,
ae_state *_state);
static void testfftunit_refinternalrfft(/* Real */ ae_vector* a,
ae_int_t nn,
/* Complex */ ae_vector* f,
ae_state *_state);
static void testfftunit_quicktest(ae_int_t n,
double* referr,
double* refrerr,
ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testfft(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t i;
ae_int_t k;
ae_vector a1;
ae_vector a2;
ae_vector a3;
ae_vector r1;
ae_vector r2;
ae_vector buf;
fasttransformplan plan;
ae_int_t maxsmalln;
double bidierr;
double bidirerr;
double referr;
double refrerr;
double reinterr;
double errtol;
ae_bool referrors;
ae_bool bidierrors;
ae_bool refrerrors;
ae_bool bidirerrors;
ae_bool reinterrors;
ae_bool waserrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a1, 0, sizeof(a1));
memset(&a2, 0, sizeof(a2));
memset(&a3, 0, sizeof(a3));
memset(&r1, 0, sizeof(r1));
memset(&r2, 0, sizeof(r2));
memset(&buf, 0, sizeof(buf));
memset(&plan, 0, sizeof(plan));
ae_vector_init(&a1, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&a2, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&a3, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&r1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&r2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&buf, 0, DT_REAL, _state, ae_true);
_fasttransformplan_init(&plan, _state, ae_true);
maxsmalln = 128;
errtol = 100000*ae_pow((double)(maxsmalln), (double)3/(double)2, _state)*ae_machineepsilon;
bidierrors = ae_false;
referrors = ae_false;
bidirerrors = ae_false;
refrerrors = ae_false;
reinterrors = ae_false;
waserrors = ae_false;
/*
* Test bi-directional error: norm(x-invFFT(FFT(x)))
*/
bidierr = (double)(0);
bidirerr = (double)(0);
for(n=1; n<=maxsmalln; n++)
{
/*
* Complex FFT/invFFT
*/
ae_vector_set_length(&a1, n, _state);
ae_vector_set_length(&a2, n, _state);
ae_vector_set_length(&a3, n, _state);
for(i=0; i<=n-1; i++)
{
a1.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1;
a1.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1;
a2.ptr.p_complex[i] = a1.ptr.p_complex[i];
a3.ptr.p_complex[i] = a1.ptr.p_complex[i];
}
fftc1d(&a2, n, _state);
fftc1dinv(&a2, n, _state);
fftc1dinv(&a3, n, _state);
fftc1d(&a3, n, _state);
for(i=0; i<=n-1; i++)
{
bidierr = ae_maxreal(bidierr, ae_c_abs(ae_c_sub(a1.ptr.p_complex[i],a2.ptr.p_complex[i]), _state), _state);
bidierr = ae_maxreal(bidierr, ae_c_abs(ae_c_sub(a1.ptr.p_complex[i],a3.ptr.p_complex[i]), _state), _state);
}
/*
* Real
*/
ae_vector_set_length(&r1, n, _state);
ae_vector_set_length(&r2, n, _state);
for(i=0; i<=n-1; i++)
{
r1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
r2.ptr.p_double[i] = r1.ptr.p_double[i];
}
fftr1d(&r2, n, &a1, _state);
ae_v_muld(&r2.ptr.p_double[0], 1, ae_v_len(0,n-1), 0);
fftr1dinv(&a1, n, &r2, _state);
for(i=0; i<=n-1; i++)
{
bidirerr = ae_maxreal(bidirerr, ae_c_abs(ae_complex_from_d(r1.ptr.p_double[i]-r2.ptr.p_double[i]), _state), _state);
}
}
bidierrors = bidierrors||ae_fp_greater(bidierr,errtol);
bidirerrors = bidirerrors||ae_fp_greater(bidirerr,errtol);
/*
* Test against reference O(N^2) implementation for small N's
* (we do not test large N's because reference implementation will be too slow).
*/
referr = (double)(0);
refrerr = (double)(0);
for(n=1; n<=maxsmalln; n++)
{
/*
* Complex FFT
*/
ae_vector_set_length(&a1, n, _state);
ae_vector_set_length(&a2, n, _state);
for(i=0; i<=n-1; i++)
{
a1.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1;
a1.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1;
a2.ptr.p_complex[i] = a1.ptr.p_complex[i];
}
fftc1d(&a1, n, _state);
testfftunit_reffftc1d(&a2, n, _state);
for(i=0; i<=n-1; i++)
{
referr = ae_maxreal(referr, ae_c_abs(ae_c_sub(a1.ptr.p_complex[i],a2.ptr.p_complex[i]), _state), _state);
}
/*
* Complex inverse FFT
*/
ae_vector_set_length(&a1, n, _state);
ae_vector_set_length(&a2, n, _state);
for(i=0; i<=n-1; i++)
{
a1.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1;
a1.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1;
a2.ptr.p_complex[i] = a1.ptr.p_complex[i];
}
fftc1dinv(&a1, n, _state);
testfftunit_reffftc1dinv(&a2, n, _state);
for(i=0; i<=n-1; i++)
{
referr = ae_maxreal(referr, ae_c_abs(ae_c_sub(a1.ptr.p_complex[i],a2.ptr.p_complex[i]), _state), _state);
}
/*
* Real forward/inverse FFT:
* * calculate and check forward FFT
* * use precalculated FFT to check backward FFT
* fill unused parts of frequencies array with random numbers
* to ensure that they are not really used
*/
ae_vector_set_length(&r1, n, _state);
ae_vector_set_length(&r2, n, _state);
for(i=0; i<=n-1; i++)
{
r1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
r2.ptr.p_double[i] = r1.ptr.p_double[i];
}
fftr1d(&r1, n, &a1, _state);
testfftunit_refinternalrfft(&r2, n, &a2, _state);
for(i=0; i<=n-1; i++)
{
refrerr = ae_maxreal(refrerr, ae_c_abs(ae_c_sub(a1.ptr.p_complex[i],a2.ptr.p_complex[i]), _state), _state);
}
ae_vector_set_length(&a3, ae_ifloor((double)n/(double)2, _state)+1, _state);
for(i=0; i<=ae_ifloor((double)n/(double)2, _state); i++)
{
a3.ptr.p_complex[i] = a2.ptr.p_complex[i];
}
a3.ptr.p_complex[0].y = 2*ae_randomreal(_state)-1;
if( n%2==0 )
{
a3.ptr.p_complex[ae_ifloor((double)n/(double)2, _state)].y = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=n-1; i++)
{
r1.ptr.p_double[i] = (double)(0);
}
fftr1dinv(&a3, n, &r1, _state);
for(i=0; i<=n-1; i++)
{
refrerr = ae_maxreal(refrerr, ae_fabs(r2.ptr.p_double[i]-r1.ptr.p_double[i], _state), _state);
}
}
referrors = referrors||ae_fp_greater(referr,errtol);
refrerrors = refrerrors||ae_fp_greater(refrerr,errtol);
/*
* Test for large N's:
* * we perform FFT
* * we selectively calculate K (small number) of DFT components (using reference formula)
* and compare them with ones calculated by fast implementation
* * K components to test are chosen at random (random sampling with possible repetitions)
* * overall complexity of the test is O(N*logN+K*N)
* Several N's are tested, with different kinds of factorizations
*/
referr = (double)(0);
refrerr = (double)(0);
testfftunit_quicktest(1000, &referr, &refrerr, _state);
testfftunit_quicktest(1024, &referr, &refrerr, _state);
testfftunit_quicktest(1025, &referr, &refrerr, _state);
testfftunit_quicktest(2000, &referr, &refrerr, _state);
testfftunit_quicktest(2048, &referr, &refrerr, _state);
testfftunit_quicktest(6535, &referr, &refrerr, _state);
testfftunit_quicktest(65536, &referr, &refrerr, _state);
testfftunit_quicktest(104729, &referr, &refrerr, _state);
testfftunit_quicktest(139129, &referr, &refrerr, _state);
testfftunit_quicktest(141740, &referr, &refrerr, _state);
referrors = referrors||ae_fp_greater(referr,errtol);
refrerrors = refrerrors||ae_fp_greater(refrerr,errtol);
/*
* test internal real even FFT
*/
reinterr = (double)(0);
for(k=1; k<=maxsmalln/2; k++)
{
n = 2*k;
/*
* Real forward FFT
*/
ae_vector_set_length(&r1, n, _state);
ae_vector_set_length(&r2, n, _state);
for(i=0; i<=n-1; i++)
{
r1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
r2.ptr.p_double[i] = r1.ptr.p_double[i];
}
ftcomplexfftplan(n/2, 1, &plan, _state);
ae_vector_set_length(&buf, n, _state);
fftr1dinternaleven(&r1, n, &buf, &plan, _state);
testfftunit_refinternalrfft(&r2, n, &a2, _state);
reinterr = ae_maxreal(reinterr, ae_fabs(r1.ptr.p_double[0]-a2.ptr.p_complex[0].x, _state), _state);
reinterr = ae_maxreal(reinterr, ae_fabs(r1.ptr.p_double[1]-a2.ptr.p_complex[n/2].x, _state), _state);
for(i=1; i<=n/2-1; i++)
{
reinterr = ae_maxreal(reinterr, ae_fabs(r1.ptr.p_double[2*i+0]-a2.ptr.p_complex[i].x, _state), _state);
reinterr = ae_maxreal(reinterr, ae_fabs(r1.ptr.p_double[2*i+1]-a2.ptr.p_complex[i].y, _state), _state);
}
/*
* Real backward FFT
*/
ae_vector_set_length(&r1, n, _state);
for(i=0; i<=n-1; i++)
{
r1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
ae_vector_set_length(&a2, ae_ifloor((double)n/(double)2, _state)+1, _state);
a2.ptr.p_complex[0] = ae_complex_from_d(r1.ptr.p_double[0]);
for(i=1; i<=ae_ifloor((double)n/(double)2, _state)-1; i++)
{
a2.ptr.p_complex[i].x = r1.ptr.p_double[2*i+0];
a2.ptr.p_complex[i].y = r1.ptr.p_double[2*i+1];
}
a2.ptr.p_complex[ae_ifloor((double)n/(double)2, _state)] = ae_complex_from_d(r1.ptr.p_double[1]);
ftcomplexfftplan(n/2, 1, &plan, _state);
ae_vector_set_length(&buf, n, _state);
fftr1dinvinternaleven(&r1, n, &buf, &plan, _state);
fftr1dinv(&a2, n, &r2, _state);
for(i=0; i<=n-1; i++)
{
reinterr = ae_maxreal(reinterr, ae_fabs(r1.ptr.p_double[i]-r2.ptr.p_double[i], _state), _state);
}
}
reinterrors = reinterrors||ae_fp_greater(reinterr,errtol);
/*
* end
*/
waserrors = (((bidierrors||bidirerrors)||referrors)||refrerrors)||reinterrors;
if( !silent )
{
printf("TESTING FFT\n");
printf("FINAL RESULT: ");
if( waserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* BI-DIRECTIONAL COMPLEX TEST: ");
if( bidierrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* AGAINST REFERENCE COMPLEX FFT: ");
if( referrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* BI-DIRECTIONAL REAL TEST: ");
if( bidirerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* AGAINST REFERENCE REAL FFT: ");
if( refrerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* INTERNAL EVEN FFT: ");
if( reinterrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Reference FFT
*************************************************************************/
static void testfftunit_reffftc1d(/* Complex */ ae_vector* a,
ae_int_t n,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector buf;
ae_int_t i;
ae_frame_make(_state, &_frame_block);
memset(&buf, 0, sizeof(buf));
ae_vector_init(&buf, 0, DT_REAL, _state, ae_true);
ae_assert(n>0, "FFTC1D: incorrect N!", _state);
ae_vector_set_length(&buf, 2*n, _state);
for(i=0; i<=n-1; i++)
{
buf.ptr.p_double[2*i+0] = a->ptr.p_complex[i].x;
buf.ptr.p_double[2*i+1] = a->ptr.p_complex[i].y;
}
testfftunit_refinternalcfft(&buf, n, ae_false, _state);
for(i=0; i<=n-1; i++)
{
a->ptr.p_complex[i].x = buf.ptr.p_double[2*i+0];
a->ptr.p_complex[i].y = buf.ptr.p_double[2*i+1];
}
ae_frame_leave(_state);
}
/*************************************************************************
Reference inverse FFT
*************************************************************************/
static void testfftunit_reffftc1dinv(/* Complex */ ae_vector* a,
ae_int_t n,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector buf;
ae_int_t i;
ae_frame_make(_state, &_frame_block);
memset(&buf, 0, sizeof(buf));
ae_vector_init(&buf, 0, DT_REAL, _state, ae_true);
ae_assert(n>0, "FFTC1DInv: incorrect N!", _state);
ae_vector_set_length(&buf, 2*n, _state);
for(i=0; i<=n-1; i++)
{
buf.ptr.p_double[2*i+0] = a->ptr.p_complex[i].x;
buf.ptr.p_double[2*i+1] = a->ptr.p_complex[i].y;
}
testfftunit_refinternalcfft(&buf, n, ae_true, _state);
for(i=0; i<=n-1; i++)
{
a->ptr.p_complex[i].x = buf.ptr.p_double[2*i+0];
a->ptr.p_complex[i].y = buf.ptr.p_double[2*i+1];
}
ae_frame_leave(_state);
}
/*************************************************************************
Internal complex FFT stub.
Uses straightforward formula with O(N^2) complexity.
*************************************************************************/
static void testfftunit_refinternalcfft(/* Real */ ae_vector* a,
ae_int_t nn,
ae_bool inversefft,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector tmp;
ae_int_t i;
ae_int_t k;
double hre;
double him;
double c;
double s;
double re;
double im;
ae_frame_make(_state, &_frame_block);
memset(&tmp, 0, sizeof(tmp));
ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
ae_vector_set_length(&tmp, 2*nn-1+1, _state);
if( !inversefft )
{
for(i=0; i<=nn-1; i++)
{
hre = (double)(0);
him = (double)(0);
for(k=0; k<=nn-1; k++)
{
re = a->ptr.p_double[2*k];
im = a->ptr.p_double[2*k+1];
c = ae_cos(-2*ae_pi*k*i/nn, _state);
s = ae_sin(-2*ae_pi*k*i/nn, _state);
hre = hre+c*re-s*im;
him = him+c*im+s*re;
}
tmp.ptr.p_double[2*i] = hre;
tmp.ptr.p_double[2*i+1] = him;
}
for(i=0; i<=2*nn-1; i++)
{
a->ptr.p_double[i] = tmp.ptr.p_double[i];
}
}
else
{
for(k=0; k<=nn-1; k++)
{
hre = (double)(0);
him = (double)(0);
for(i=0; i<=nn-1; i++)
{
re = a->ptr.p_double[2*i];
im = a->ptr.p_double[2*i+1];
c = ae_cos(2*ae_pi*k*i/nn, _state);
s = ae_sin(2*ae_pi*k*i/nn, _state);
hre = hre+c*re-s*im;
him = him+c*im+s*re;
}
tmp.ptr.p_double[2*k] = hre/nn;
tmp.ptr.p_double[2*k+1] = him/nn;
}
for(i=0; i<=2*nn-1; i++)
{
a->ptr.p_double[i] = tmp.ptr.p_double[i];
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Internal real FFT stub.
Uses straightforward formula with O(N^2) complexity.
*************************************************************************/
static void testfftunit_refinternalrfft(/* Real */ ae_vector* a,
ae_int_t nn,
/* Complex */ ae_vector* f,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector tmp;
ae_int_t i;
ae_frame_make(_state, &_frame_block);
memset(&tmp, 0, sizeof(tmp));
ae_vector_clear(f);
ae_vector_init(&tmp, 0, DT_REAL, _state, ae_true);
ae_vector_set_length(&tmp, 2*nn-1+1, _state);
for(i=0; i<=nn-1; i++)
{
tmp.ptr.p_double[2*i] = a->ptr.p_double[i];
tmp.ptr.p_double[2*i+1] = (double)(0);
}
testfftunit_refinternalcfft(&tmp, nn, ae_false, _state);
ae_vector_set_length(f, nn, _state);
for(i=0; i<=nn-1; i++)
{
f->ptr.p_complex[i].x = tmp.ptr.p_double[2*i+0];
f->ptr.p_complex[i].y = tmp.ptr.p_double[2*i+1];
}
ae_frame_leave(_state);
}
/*************************************************************************
This function performs real/complex FFT of given length on random data,
selects K random components and compares them with values calculated by
DFT definition.
It updates RefErr and RefRErr as follows:
RefErr:= max(RefErr, error_of_complex_FFT)
RefRErr:= max(RefRErr,error_of_real_FFT)
*************************************************************************/
static void testfftunit_quicktest(ae_int_t n,
double* referr,
double* refrerr,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector a0;
ae_vector a1;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t idx;
ae_complex v;
double c;
double s;
double re;
double im;
ae_frame_make(_state, &_frame_block);
memset(&a0, 0, sizeof(a0));
memset(&a1, 0, sizeof(a1));
ae_vector_init(&a0, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&a1, 0, DT_COMPLEX, _state, ae_true);
k = 10;
/*
* Complex FFT - forward and inverse
*/
ae_vector_set_length(&a0, n, _state);
ae_vector_set_length(&a1, n, _state);
for(i=0; i<=n-1; i++)
{
a0.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1;
a0.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1;
a1.ptr.p_complex[i] = a0.ptr.p_complex[i];
}
fftc1d(&a0, n, _state);
for(i=0; i<=k-1; i++)
{
idx = ae_randominteger(n, _state);
v = ae_complex_from_i(0);
for(j=0; j<=n-1; j++)
{
re = a1.ptr.p_complex[j].x;
im = a1.ptr.p_complex[j].y;
c = ae_cos(-2*ae_pi*j*idx/n, _state);
s = ae_sin(-2*ae_pi*j*idx/n, _state);
v.x = v.x+c*re-s*im;
v.y = v.y+c*im+s*re;
}
*referr = ae_maxreal(*referr, ae_c_abs(ae_c_sub(v,a0.ptr.p_complex[idx]), _state), _state);
}
fftc1dinv(&a0, n, _state);
for(i=0; i<=n-1; i++)
{
*referr = ae_maxreal(*referr, ae_c_abs(ae_c_sub(a0.ptr.p_complex[i],a1.ptr.p_complex[i]), _state), _state);
}
ae_frame_leave(_state);
}
static void testfhtunit_reffhtr1d(/* Real */ ae_vector* a,
ae_int_t n,
ae_state *_state);
static void testfhtunit_reffhtr1dinv(/* Real */ ae_vector* a,
ae_int_t n,
ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testfht(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t i;
ae_vector r1;
ae_vector r2;
ae_vector r3;
ae_int_t maxn;
double bidierr;
double referr;
double errtol;
ae_bool referrors;
ae_bool bidierrors;
ae_bool waserrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&r1, 0, sizeof(r1));
memset(&r2, 0, sizeof(r2));
memset(&r3, 0, sizeof(r3));
ae_vector_init(&r1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&r2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&r3, 0, DT_REAL, _state, ae_true);
maxn = 128;
errtol = 100000*ae_pow((double)(maxn), (double)3/(double)2, _state)*ae_machineepsilon;
bidierrors = ae_false;
referrors = ae_false;
waserrors = ae_false;
/*
* Test bi-directional error: norm(x-invFHT(FHT(x)))
*/
bidierr = (double)(0);
for(n=1; n<=maxn; n++)
{
/*
* FHT/invFHT
*/
ae_vector_set_length(&r1, n, _state);
ae_vector_set_length(&r2, n, _state);
ae_vector_set_length(&r3, n, _state);
for(i=0; i<=n-1; i++)
{
r1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
r2.ptr.p_double[i] = r1.ptr.p_double[i];
r3.ptr.p_double[i] = r1.ptr.p_double[i];
}
fhtr1d(&r2, n, _state);
fhtr1dinv(&r2, n, _state);
fhtr1dinv(&r3, n, _state);
fhtr1d(&r3, n, _state);
for(i=0; i<=n-1; i++)
{
bidierr = ae_maxreal(bidierr, ae_fabs(r1.ptr.p_double[i]-r2.ptr.p_double[i], _state), _state);
bidierr = ae_maxreal(bidierr, ae_fabs(r1.ptr.p_double[i]-r3.ptr.p_double[i], _state), _state);
}
}
bidierrors = bidierrors||ae_fp_greater(bidierr,errtol);
/*
* Test against reference O(N^2) implementation
*/
referr = (double)(0);
for(n=1; n<=maxn; n++)
{
/*
* FHT
*/
ae_vector_set_length(&r1, n, _state);
ae_vector_set_length(&r2, n, _state);
for(i=0; i<=n-1; i++)
{
r1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
r2.ptr.p_double[i] = r1.ptr.p_double[i];
}
fhtr1d(&r1, n, _state);
testfhtunit_reffhtr1d(&r2, n, _state);
for(i=0; i<=n-1; i++)
{
referr = ae_maxreal(referr, ae_fabs(r1.ptr.p_double[i]-r2.ptr.p_double[i], _state), _state);
}
/*
* inverse FHT
*/
ae_vector_set_length(&r1, n, _state);
ae_vector_set_length(&r2, n, _state);
for(i=0; i<=n-1; i++)
{
r1.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
r2.ptr.p_double[i] = r1.ptr.p_double[i];
}
fhtr1dinv(&r1, n, _state);
testfhtunit_reffhtr1dinv(&r2, n, _state);
for(i=0; i<=n-1; i++)
{
referr = ae_maxreal(referr, ae_fabs(r1.ptr.p_double[i]-r2.ptr.p_double[i], _state), _state);
}
}
referrors = referrors||ae_fp_greater(referr,errtol);
/*
* end
*/
waserrors = bidierrors||referrors;
if( !silent )
{
printf("TESTING FHT\n");
printf("FINAL RESULT: ");
if( waserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* BI-DIRECTIONAL TEST: ");
if( bidierrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* AGAINST REFERENCE FHT: ");
if( referrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Reference FHT
*************************************************************************/
static void testfhtunit_reffhtr1d(/* Real */ ae_vector* a,
ae_int_t n,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector buf;
ae_int_t i;
ae_int_t j;
double v;
ae_frame_make(_state, &_frame_block);
memset(&buf, 0, sizeof(buf));
ae_vector_init(&buf, 0, DT_REAL, _state, ae_true);
ae_assert(n>0, "RefFHTR1D: incorrect N!", _state);
ae_vector_set_length(&buf, n, _state);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+a->ptr.p_double[j]*(ae_cos(2*ae_pi*i*j/n, _state)+ae_sin(2*ae_pi*i*j/n, _state));
}
buf.ptr.p_double[i] = v;
}
for(i=0; i<=n-1; i++)
{
a->ptr.p_double[i] = buf.ptr.p_double[i];
}
ae_frame_leave(_state);
}
/*************************************************************************
Reference inverse FHT
*************************************************************************/
static void testfhtunit_reffhtr1dinv(/* Real */ ae_vector* a,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
ae_assert(n>0, "RefFHTR1DInv: incorrect N!", _state);
testfhtunit_reffhtr1d(a, n, _state);
for(i=0; i<=n-1; i++)
{
a->ptr.p_double[i] = a->ptr.p_double[i]/n;
}
}
static void testconvunit_refconvc1d(/* Complex */ ae_vector* a,
ae_int_t m,
/* Complex */ ae_vector* b,
ae_int_t n,
/* Complex */ ae_vector* r,
ae_state *_state);
static void testconvunit_refconvc1dcircular(/* Complex */ ae_vector* a,
ae_int_t m,
/* Complex */ ae_vector* b,
ae_int_t n,
/* Complex */ ae_vector* r,
ae_state *_state);
static void testconvunit_refconvr1d(/* Real */ ae_vector* a,
ae_int_t m,
/* Real */ ae_vector* b,
ae_int_t n,
/* Real */ ae_vector* r,
ae_state *_state);
static void testconvunit_refconvr1dcircular(/* Real */ ae_vector* a,
ae_int_t m,
/* Real */ ae_vector* b,
ae_int_t n,
/* Real */ ae_vector* r,
ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testconv(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t m;
ae_int_t n;
ae_int_t i;
ae_int_t rkind;
ae_int_t circkind;
ae_vector ra;
ae_vector rb;
ae_vector rr1;
ae_vector rr2;
ae_vector ca;
ae_vector cb;
ae_vector cr1;
ae_vector cr2;
ae_int_t maxn;
double referr;
double refrerr;
double inverr;
double invrerr;
double errtol;
ae_bool referrors;
ae_bool refrerrors;
ae_bool inverrors;
ae_bool invrerrors;
ae_bool waserrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&ra, 0, sizeof(ra));
memset(&rb, 0, sizeof(rb));
memset(&rr1, 0, sizeof(rr1));
memset(&rr2, 0, sizeof(rr2));
memset(&ca, 0, sizeof(ca));
memset(&cb, 0, sizeof(cb));
memset(&cr1, 0, sizeof(cr1));
memset(&cr2, 0, sizeof(cr2));
ae_vector_init(&ra, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rb, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rr1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rr2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ca, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&cb, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&cr1, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&cr2, 0, DT_COMPLEX, _state, ae_true);
maxn = 32;
errtol = 100000*ae_pow((double)(maxn), (double)3/(double)2, _state)*ae_machineepsilon;
referrors = ae_false;
refrerrors = ae_false;
inverrors = ae_false;
invrerrors = ae_false;
waserrors = ae_false;
/*
* Test against reference O(N^2) implementation.
*
* Automatic ConvC1D() and different algorithms of ConvC1DX() are tested.
*/
referr = (double)(0);
refrerr = (double)(0);
for(m=1; m<=maxn; m++)
{
for(n=1; n<=maxn; n++)
{
for(circkind=0; circkind<=1; circkind++)
{
for(rkind=-3; rkind<=1; rkind++)
{
/*
* skip impossible combinations of parameters:
* * circular convolution, M-3 - internal subroutine does not support M=n )
{
/*
* test internal subroutine:
* * circular/non-circular mode
*/
convc1dx(&ca, m, &cb, n, circkind!=0, rkind, 0, &cr1, _state);
}
else
{
/*
* test internal subroutine - circular mode only
*/
ae_assert(circkind==0, "Convolution test: internal error!", _state);
convc1dx(&cb, n, &ca, m, ae_false, rkind, 0, &cr1, _state);
}
}
if( circkind==0 )
{
testconvunit_refconvc1d(&ca, m, &cb, n, &cr2, _state);
}
else
{
testconvunit_refconvc1dcircular(&ca, m, &cb, n, &cr2, _state);
}
if( circkind==0 )
{
for(i=0; i<=m+n-2; i++)
{
referr = ae_maxreal(referr, ae_c_abs(ae_c_sub(cr1.ptr.p_complex[i],cr2.ptr.p_complex[i]), _state), _state);
}
}
else
{
for(i=0; i<=m-1; i++)
{
referr = ae_maxreal(referr, ae_c_abs(ae_c_sub(cr1.ptr.p_complex[i],cr2.ptr.p_complex[i]), _state), _state);
}
}
/*
* Real convolution
*/
ae_vector_set_length(&ra, m, _state);
for(i=0; i<=m-1; i++)
{
ra.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
ae_vector_set_length(&rb, n, _state);
for(i=0; i<=n-1; i++)
{
rb.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
ae_vector_set_length(&rr1, 1, _state);
if( rkind==-3 )
{
/*
* test wrapper subroutine:
* * circular/non-circular
*/
if( circkind==0 )
{
convr1d(&ra, m, &rb, n, &rr1, _state);
}
else
{
convr1dcircular(&ra, m, &rb, n, &rr1, _state);
}
}
else
{
if( m>=n )
{
/*
* test internal subroutine:
* * circular/non-circular mode
*/
convr1dx(&ra, m, &rb, n, circkind!=0, rkind, 0, &rr1, _state);
}
else
{
/*
* test internal subroutine - non-circular mode only
*/
convr1dx(&rb, n, &ra, m, circkind!=0, rkind, 0, &rr1, _state);
}
}
if( circkind==0 )
{
testconvunit_refconvr1d(&ra, m, &rb, n, &rr2, _state);
}
else
{
testconvunit_refconvr1dcircular(&ra, m, &rb, n, &rr2, _state);
}
if( circkind==0 )
{
for(i=0; i<=m+n-2; i++)
{
refrerr = ae_maxreal(refrerr, ae_fabs(rr1.ptr.p_double[i]-rr2.ptr.p_double[i], _state), _state);
}
}
else
{
for(i=0; i<=m-1; i++)
{
refrerr = ae_maxreal(refrerr, ae_fabs(rr1.ptr.p_double[i]-rr2.ptr.p_double[i], _state), _state);
}
}
}
}
}
}
referrors = referrors||ae_fp_greater(referr,errtol);
refrerrors = refrerrors||ae_fp_greater(refrerr,errtol);
/*
* Test inverse convolution
*/
inverr = (double)(0);
invrerr = (double)(0);
for(m=1; m<=maxn; m++)
{
for(n=1; n<=maxn; n++)
{
/*
* Complex circilar and non-circular
*/
ae_vector_set_length(&ca, m, _state);
for(i=0; i<=m-1; i++)
{
ca.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1;
ca.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1;
}
ae_vector_set_length(&cb, n, _state);
for(i=0; i<=n-1; i++)
{
cb.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1;
cb.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1;
}
ae_vector_set_length(&cr1, 1, _state);
ae_vector_set_length(&cr2, 1, _state);
convc1d(&ca, m, &cb, n, &cr2, _state);
convc1dinv(&cr2, m+n-1, &cb, n, &cr1, _state);
for(i=0; i<=m-1; i++)
{
inverr = ae_maxreal(inverr, ae_c_abs(ae_c_sub(cr1.ptr.p_complex[i],ca.ptr.p_complex[i]), _state), _state);
}
ae_vector_set_length(&cr1, 1, _state);
ae_vector_set_length(&cr2, 1, _state);
convc1dcircular(&ca, m, &cb, n, &cr2, _state);
convc1dcircularinv(&cr2, m, &cb, n, &cr1, _state);
for(i=0; i<=m-1; i++)
{
inverr = ae_maxreal(inverr, ae_c_abs(ae_c_sub(cr1.ptr.p_complex[i],ca.ptr.p_complex[i]), _state), _state);
}
/*
* Real circilar and non-circular
*/
ae_vector_set_length(&ra, m, _state);
for(i=0; i<=m-1; i++)
{
ra.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
ae_vector_set_length(&rb, n, _state);
for(i=0; i<=n-1; i++)
{
rb.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
ae_vector_set_length(&rr1, 1, _state);
ae_vector_set_length(&rr2, 1, _state);
convr1d(&ra, m, &rb, n, &rr2, _state);
convr1dinv(&rr2, m+n-1, &rb, n, &rr1, _state);
for(i=0; i<=m-1; i++)
{
invrerr = ae_maxreal(invrerr, ae_fabs(rr1.ptr.p_double[i]-ra.ptr.p_double[i], _state), _state);
}
ae_vector_set_length(&rr1, 1, _state);
ae_vector_set_length(&rr2, 1, _state);
convr1dcircular(&ra, m, &rb, n, &rr2, _state);
convr1dcircularinv(&rr2, m, &rb, n, &rr1, _state);
for(i=0; i<=m-1; i++)
{
invrerr = ae_maxreal(invrerr, ae_fabs(rr1.ptr.p_double[i]-ra.ptr.p_double[i], _state), _state);
}
}
}
inverrors = inverrors||ae_fp_greater(inverr,errtol);
invrerrors = invrerrors||ae_fp_greater(invrerr,errtol);
/*
* end
*/
waserrors = ((referrors||refrerrors)||inverrors)||invrerrors;
if( !silent )
{
printf("TESTING CONVOLUTION\n");
printf("FINAL RESULT: ");
if( waserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* AGAINST REFERENCE COMPLEX CONV: ");
if( referrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* AGAINST REFERENCE REAL CONV: ");
if( refrerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* COMPLEX INVERSE: ");
if( inverrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* REAL INVERSE: ");
if( invrerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Reference implementation
*************************************************************************/
static void testconvunit_refconvc1d(/* Complex */ ae_vector* a,
ae_int_t m,
/* Complex */ ae_vector* b,
ae_int_t n,
/* Complex */ ae_vector* r,
ae_state *_state)
{
ae_int_t i;
ae_complex v;
ae_vector_clear(r);
ae_vector_set_length(r, m+n-1, _state);
for(i=0; i<=m+n-2; i++)
{
r->ptr.p_complex[i] = ae_complex_from_i(0);
}
for(i=0; i<=m-1; i++)
{
v = a->ptr.p_complex[i];
ae_v_caddc(&r->ptr.p_complex[i], 1, &b->ptr.p_complex[0], 1, "N", ae_v_len(i,i+n-1), v);
}
}
/*************************************************************************
Reference implementation
*************************************************************************/
static void testconvunit_refconvc1dcircular(/* Complex */ ae_vector* a,
ae_int_t m,
/* Complex */ ae_vector* b,
ae_int_t n,
/* Complex */ ae_vector* r,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i1;
ae_int_t i2;
ae_int_t j2;
ae_vector buf;
ae_frame_make(_state, &_frame_block);
memset(&buf, 0, sizeof(buf));
ae_vector_clear(r);
ae_vector_init(&buf, 0, DT_COMPLEX, _state, ae_true);
testconvunit_refconvc1d(a, m, b, n, &buf, _state);
ae_vector_set_length(r, m, _state);
ae_v_cmove(&r->ptr.p_complex[0], 1, &buf.ptr.p_complex[0], 1, "N", ae_v_len(0,m-1));
i1 = m;
while(i1<=m+n-2)
{
i2 = ae_minint(i1+m-1, m+n-2, _state);
j2 = i2-i1;
ae_v_cadd(&r->ptr.p_complex[0], 1, &buf.ptr.p_complex[i1], 1, "N", ae_v_len(0,j2));
i1 = i1+m;
}
ae_frame_leave(_state);
}
/*************************************************************************
Reference FFT
*************************************************************************/
static void testconvunit_refconvr1d(/* Real */ ae_vector* a,
ae_int_t m,
/* Real */ ae_vector* b,
ae_int_t n,
/* Real */ ae_vector* r,
ae_state *_state)
{
ae_int_t i;
double v;
ae_vector_clear(r);
ae_vector_set_length(r, m+n-1, _state);
for(i=0; i<=m+n-2; i++)
{
r->ptr.p_double[i] = (double)(0);
}
for(i=0; i<=m-1; i++)
{
v = a->ptr.p_double[i];
ae_v_addd(&r->ptr.p_double[i], 1, &b->ptr.p_double[0], 1, ae_v_len(i,i+n-1), v);
}
}
/*************************************************************************
Reference implementation
*************************************************************************/
static void testconvunit_refconvr1dcircular(/* Real */ ae_vector* a,
ae_int_t m,
/* Real */ ae_vector* b,
ae_int_t n,
/* Real */ ae_vector* r,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i1;
ae_int_t i2;
ae_int_t j2;
ae_vector buf;
ae_frame_make(_state, &_frame_block);
memset(&buf, 0, sizeof(buf));
ae_vector_clear(r);
ae_vector_init(&buf, 0, DT_REAL, _state, ae_true);
testconvunit_refconvr1d(a, m, b, n, &buf, _state);
ae_vector_set_length(r, m, _state);
ae_v_move(&r->ptr.p_double[0], 1, &buf.ptr.p_double[0], 1, ae_v_len(0,m-1));
i1 = m;
while(i1<=m+n-2)
{
i2 = ae_minint(i1+m-1, m+n-2, _state);
j2 = i2-i1;
ae_v_add(&r->ptr.p_double[0], 1, &buf.ptr.p_double[i1], 1, ae_v_len(0,j2));
i1 = i1+m;
}
ae_frame_leave(_state);
}
static void testcorrunit_refcorrc1d(/* Complex */ ae_vector* signal,
ae_int_t n,
/* Complex */ ae_vector* pattern,
ae_int_t m,
/* Complex */ ae_vector* r,
ae_state *_state);
static void testcorrunit_refcorrc1dcircular(/* Complex */ ae_vector* signal,
ae_int_t n,
/* Complex */ ae_vector* pattern,
ae_int_t m,
/* Complex */ ae_vector* r,
ae_state *_state);
static void testcorrunit_refcorrr1d(/* Real */ ae_vector* signal,
ae_int_t n,
/* Real */ ae_vector* pattern,
ae_int_t m,
/* Real */ ae_vector* r,
ae_state *_state);
static void testcorrunit_refcorrr1dcircular(/* Real */ ae_vector* signal,
ae_int_t n,
/* Real */ ae_vector* pattern,
ae_int_t m,
/* Real */ ae_vector* r,
ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testcorr(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t m;
ae_int_t n;
ae_int_t i;
ae_vector ra;
ae_vector rb;
ae_vector rr1;
ae_vector rr2;
ae_vector ca;
ae_vector cb;
ae_vector cr1;
ae_vector cr2;
ae_int_t maxn;
double referr;
double refrerr;
double errtol;
ae_bool referrors;
ae_bool refrerrors;
ae_bool waserrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&ra, 0, sizeof(ra));
memset(&rb, 0, sizeof(rb));
memset(&rr1, 0, sizeof(rr1));
memset(&rr2, 0, sizeof(rr2));
memset(&ca, 0, sizeof(ca));
memset(&cb, 0, sizeof(cb));
memset(&cr1, 0, sizeof(cr1));
memset(&cr2, 0, sizeof(cr2));
ae_vector_init(&ra, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rb, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rr1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rr2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ca, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&cb, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&cr1, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&cr2, 0, DT_COMPLEX, _state, ae_true);
maxn = 32;
errtol = 100000*ae_pow((double)(maxn), (double)3/(double)2, _state)*ae_machineepsilon;
referrors = ae_false;
refrerrors = ae_false;
waserrors = ae_false;
/*
* Test against reference O(N^2) implementation.
*/
referr = (double)(0);
refrerr = (double)(0);
for(m=1; m<=maxn; m++)
{
for(n=1; n<=maxn; n++)
{
/*
* Complex correlation
*/
ae_vector_set_length(&ca, m, _state);
for(i=0; i<=m-1; i++)
{
ca.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1;
ca.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1;
}
ae_vector_set_length(&cb, n, _state);
for(i=0; i<=n-1; i++)
{
cb.ptr.p_complex[i].x = 2*ae_randomreal(_state)-1;
cb.ptr.p_complex[i].y = 2*ae_randomreal(_state)-1;
}
ae_vector_set_length(&cr1, 1, _state);
corrc1d(&ca, m, &cb, n, &cr1, _state);
testcorrunit_refcorrc1d(&ca, m, &cb, n, &cr2, _state);
for(i=0; i<=m+n-2; i++)
{
referr = ae_maxreal(referr, ae_c_abs(ae_c_sub(cr1.ptr.p_complex[i],cr2.ptr.p_complex[i]), _state), _state);
}
ae_vector_set_length(&cr1, 1, _state);
corrc1dcircular(&ca, m, &cb, n, &cr1, _state);
testcorrunit_refcorrc1dcircular(&ca, m, &cb, n, &cr2, _state);
for(i=0; i<=m-1; i++)
{
referr = ae_maxreal(referr, ae_c_abs(ae_c_sub(cr1.ptr.p_complex[i],cr2.ptr.p_complex[i]), _state), _state);
}
/*
* Real correlation
*/
ae_vector_set_length(&ra, m, _state);
for(i=0; i<=m-1; i++)
{
ra.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
ae_vector_set_length(&rb, n, _state);
for(i=0; i<=n-1; i++)
{
rb.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
ae_vector_set_length(&rr1, 1, _state);
corrr1d(&ra, m, &rb, n, &rr1, _state);
testcorrunit_refcorrr1d(&ra, m, &rb, n, &rr2, _state);
for(i=0; i<=m+n-2; i++)
{
refrerr = ae_maxreal(refrerr, ae_fabs(rr1.ptr.p_double[i]-rr2.ptr.p_double[i], _state), _state);
}
ae_vector_set_length(&rr1, 1, _state);
corrr1dcircular(&ra, m, &rb, n, &rr1, _state);
testcorrunit_refcorrr1dcircular(&ra, m, &rb, n, &rr2, _state);
for(i=0; i<=m-1; i++)
{
refrerr = ae_maxreal(refrerr, ae_fabs(rr1.ptr.p_double[i]-rr2.ptr.p_double[i], _state), _state);
}
}
}
referrors = referrors||ae_fp_greater(referr,errtol);
refrerrors = refrerrors||ae_fp_greater(refrerr,errtol);
/*
* end
*/
waserrors = referrors||refrerrors;
if( !silent )
{
printf("TESTING CORRELATION\n");
printf("FINAL RESULT: ");
if( waserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* AGAINST REFERENCE COMPLEX CORR: ");
if( referrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* AGAINST REFERENCE REAL CORR: ");
if( refrerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Reference implementation
*************************************************************************/
static void testcorrunit_refcorrc1d(/* Complex */ ae_vector* signal,
ae_int_t n,
/* Complex */ ae_vector* pattern,
ae_int_t m,
/* Complex */ ae_vector* r,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_complex v;
ae_vector s;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
ae_vector_clear(r);
ae_vector_init(&s, 0, DT_COMPLEX, _state, ae_true);
ae_vector_set_length(&s, m+n-1, _state);
ae_v_cmove(&s.ptr.p_complex[0], 1, &signal->ptr.p_complex[0], 1, "N", ae_v_len(0,n-1));
for(i=n; i<=m+n-2; i++)
{
s.ptr.p_complex[i] = ae_complex_from_i(0);
}
ae_vector_set_length(r, m+n-1, _state);
for(i=0; i<=n-1; i++)
{
v = ae_complex_from_i(0);
for(j=0; j<=m-1; j++)
{
if( i+j>=n )
{
break;
}
v = ae_c_add(v,ae_c_mul(ae_c_conj(pattern->ptr.p_complex[j], _state),s.ptr.p_complex[i+j]));
}
r->ptr.p_complex[i] = v;
}
for(i=1; i<=m-1; i++)
{
v = ae_complex_from_i(0);
for(j=i; j<=m-1; j++)
{
v = ae_c_add(v,ae_c_mul(ae_c_conj(pattern->ptr.p_complex[j], _state),s.ptr.p_complex[j-i]));
}
r->ptr.p_complex[m+n-1-i] = v;
}
ae_frame_leave(_state);
}
/*************************************************************************
Reference implementation
*************************************************************************/
static void testcorrunit_refcorrc1dcircular(/* Complex */ ae_vector* signal,
ae_int_t n,
/* Complex */ ae_vector* pattern,
ae_int_t m,
/* Complex */ ae_vector* r,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
ae_complex v;
ae_vector_clear(r);
ae_vector_set_length(r, n, _state);
for(i=0; i<=n-1; i++)
{
v = ae_complex_from_i(0);
for(j=0; j<=m-1; j++)
{
v = ae_c_add(v,ae_c_mul(ae_c_conj(pattern->ptr.p_complex[j], _state),signal->ptr.p_complex[(i+j)%n]));
}
r->ptr.p_complex[i] = v;
}
}
/*************************************************************************
Reference implementation
*************************************************************************/
static void testcorrunit_refcorrr1d(/* Real */ ae_vector* signal,
ae_int_t n,
/* Real */ ae_vector* pattern,
ae_int_t m,
/* Real */ ae_vector* r,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
double v;
ae_vector s;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
ae_vector_clear(r);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_set_length(&s, m+n-1, _state);
ae_v_move(&s.ptr.p_double[0], 1, &signal->ptr.p_double[0], 1, ae_v_len(0,n-1));
for(i=n; i<=m+n-2; i++)
{
s.ptr.p_double[i] = (double)(0);
}
ae_vector_set_length(r, m+n-1, _state);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=m-1; j++)
{
if( i+j>=n )
{
break;
}
v = v+pattern->ptr.p_double[j]*s.ptr.p_double[i+j];
}
r->ptr.p_double[i] = v;
}
for(i=1; i<=m-1; i++)
{
v = (double)(0);
for(j=i; j<=m-1; j++)
{
v = v+pattern->ptr.p_double[j]*s.ptr.p_double[-i+j];
}
r->ptr.p_double[m+n-1-i] = v;
}
ae_frame_leave(_state);
}
/*************************************************************************
Reference implementation
*************************************************************************/
static void testcorrunit_refcorrr1dcircular(/* Real */ ae_vector* signal,
ae_int_t n,
/* Real */ ae_vector* pattern,
ae_int_t m,
/* Real */ ae_vector* r,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
double v;
ae_vector_clear(r);
ae_vector_set_length(r, n, _state);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=m-1; j++)
{
v = v+pattern->ptr.p_double[j]*signal->ptr.p_double[(i+j)%n];
}
r->ptr.p_double[i] = v;
}
}
static void testidwunit_testcontinuity(idwmodel* model,
ae_int_t nx,
ae_int_t ny,
/* Real */ ae_vector* x0,
/* Real */ ae_vector* x1,
ae_int_t nsteps,
ae_int_t d,
ae_bool* err,
ae_state *_state);
static void testidwunit_testcommon(ae_bool* err, ae_state *_state);
static void testidwunit_testmstab(ae_bool* err, ae_state *_state);
/*************************************************************************
Testing IDW interpolation
*************************************************************************/
ae_bool testidw(ae_bool silent, ae_state *_state)
{
ae_bool waserrors;
ae_bool commonerrors;
ae_bool mstaberrors;
ae_bool result;
commonerrors = ae_false;
mstaberrors = ae_false;
testidwunit_testcommon(&commonerrors, _state);
testidwunit_testmstab(&mstaberrors, _state);
waserrors = commonerrors||mstaberrors;
if( !silent )
{
printf("TESTING INVERSE DISTANCE WEIGHTING\n");
printf("* common properties ");
if( !commonerrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* MSTAB-specific tests ");
if( !mstaberrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
return result;
}
/*************************************************************************
Testing continuity properties: C0 (D=0) or C1 (D=1) continuity.
Error flag is modified on failure, unchanged on success.
*************************************************************************/
static void testidwunit_testcontinuity(idwmodel* model,
ae_int_t nx,
ae_int_t ny,
/* Real */ ae_vector* x0,
/* Real */ ae_vector* x1,
ae_int_t nsteps,
ae_int_t d,
ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_int_t cidx;
double t;
ae_vector xc;
ae_vector yc;
ae_matrix yy;
double lc1;
double lc2;
ae_frame_make(_state, &_frame_block);
memset(&xc, 0, sizeof(xc));
memset(&yc, 0, sizeof(yc));
memset(&yy, 0, sizeof(yy));
ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&yc, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&yy, 0, 0, DT_REAL, _state, ae_true);
ae_assert(nsteps>=10, "TestContinuity: NSteps is too small", _state);
ae_assert(d==0||d==1, "TestContinuity: incorrect D", _state);
/*
* Compute sequence of function values
*/
ae_vector_set_length(&xc, nx, _state);
ae_matrix_set_length(&yy, nsteps, ny, _state);
for(i=0; i<=nsteps-1; i++)
{
t = (double)i/(double)(nsteps-1);
for(j=0; j<=nx-1; j++)
{
xc.ptr.p_double[j] = x0->ptr.p_double[j]*t+x1->ptr.p_double[j]*(1-t);
}
idwcalcbuf(model, &xc, &yc, _state);
for(j=0; j<=ny-1; j++)
{
yy.ptr.pp_double[i][j] = yc.ptr.p_double[j];
}
}
/*
* Evaluate all differentiability levels (C0, C1) requested by user
*/
for(cidx=0; cidx<=d; cidx++)
{
/*
* Compute Lipschitz constant for original and increased steps
*/
lc1 = (double)(0);
lc2 = (double)(0);
for(i=0; i<=nsteps-3; i++)
{
for(j=0; j<=ny-1; j++)
{
lc1 = ae_maxreal(lc1, ae_fabs(yy.ptr.pp_double[i][j]-yy.ptr.pp_double[i+1][j], _state), _state);
lc2 = ae_maxreal(lc2, ae_fabs(yy.ptr.pp_double[i][j]-yy.ptr.pp_double[i+2][j], _state)/2, _state);
}
}
ae_set_error_flag(err, ae_fp_greater(lc2,1.0E-4)&&ae_fp_greater(lc1,1.750*lc2), __FILE__, __LINE__, "testidwunit.ap:67");
/*
* Differentiate function, repeat one more time
*/
for(i=0; i<=nsteps-2; i++)
{
for(j=0; j<=ny-1; j++)
{
yy.ptr.pp_double[i][j] = yy.ptr.pp_double[i+1][j]-yy.ptr.pp_double[i][j];
}
}
nsteps = nsteps-1;
}
ae_frame_leave(_state);
}
/*************************************************************************
Test MSTAB; Err is set to True on failure, unchanged otherwise.
*************************************************************************/
static void testidwunit_testcommon(ae_bool* err, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t pass;
ae_int_t algotype;
ae_int_t i;
ae_int_t i0;
ae_int_t i1;
ae_int_t j;
ae_int_t k;
ae_int_t n;
ae_matrix xy;
double v;
double vv;
ae_bool initdone;
idwmodel model;
idwmodel model1;
idwbuilder builder;
idwreport rep;
idwcalcbuffer buffer;
double shepardp;
double rbase;
double tol;
double mindistinf;
double refrms;
double refavg;
double refmax;
double refr2;
double refrss;
double reftss;
ae_int_t nx;
ae_int_t ny;
hqrndstate rs;
double x0;
double x1;
double x2;
ae_int_t continuitytesting;
ae_vector x;
ae_vector xx;
ae_vector y;
ae_vector meany;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
memset(&model, 0, sizeof(model));
memset(&model1, 0, sizeof(model1));
memset(&builder, 0, sizeof(builder));
memset(&rep, 0, sizeof(rep));
memset(&buffer, 0, sizeof(buffer));
memset(&rs, 0, sizeof(rs));
memset(&x, 0, sizeof(x));
memset(&xx, 0, sizeof(xx));
memset(&y, 0, sizeof(y));
memset(&meany, 0, sizeof(meany));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_idwmodel_init(&model, _state, ae_true);
_idwmodel_init(&model1, _state, ae_true);
_idwbuilder_init(&builder, _state, ae_true);
_idwreport_init(&rep, _state, ae_true);
_idwcalcbuffer_init(&buffer, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&meany, 0, DT_REAL, _state, ae_true);
hqrndrandomize(&rs, _state);
tol = 1.0E-10;
mindistinf = 0.05;
/*
* Try all algorithms
*/
for(algotype=0; algotype<=2; algotype++)
{
/*
* Test empty dataset
*/
for(nx=1; nx<=5; nx++)
{
for(ny=1; ny<=5; ny++)
{
initdone = ae_false;
idwbuildercreate(nx, ny, &builder, _state);
if( algotype==0 )
{
initdone = ae_true;
shepardp = 1+(nx+1)*hqrnduniformr(&rs, _state);
idwbuildersetalgotextbookshepard(&builder, shepardp, _state);
}
if( algotype==1 )
{
initdone = ae_true;
rbase = ae_pow(2.0, 4*hqrnduniformr(&rs, _state)-2, _state);
idwbuildersetalgotextbookmodshepard(&builder, rbase, _state);
}
if( algotype==2 )
{
initdone = ae_true;
rbase = ae_pow(2.0, 4*hqrnduniformr(&rs, _state)-2, _state);
idwbuildersetalgomstab(&builder, rbase, _state);
}
ae_assert(initdone, "TestCommon: unexpected AlgoType", _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
/*
* Fit and store result directly into the variable
*/
idwfit(&builder, &model, &rep, _state);
}
else
{
/*
* Fit, store result to temporary, pass through the serializer
*/
idwfit(&builder, &model1, &rep, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
idwalloc(&_local_serializer, &model1, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
idwserialize(&_local_serializer, &model1, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
idwunserialize(&_local_serializer, &model, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
}
idwcreatecalcbuffer(&model, &buffer, _state);
/*
* Test report
*/
ae_set_error_flag(err, ae_fp_neq(rep.rmserror,(double)(0)), __FILE__, __LINE__, "testidwunit.ap:169");
ae_set_error_flag(err, ae_fp_neq(rep.avgerror,(double)(0)), __FILE__, __LINE__, "testidwunit.ap:170");
ae_set_error_flag(err, ae_fp_neq(rep.maxerror,(double)(0)), __FILE__, __LINE__, "testidwunit.ap:171");
ae_set_error_flag(err, ae_fp_neq(rep.r2,(double)(1)), __FILE__, __LINE__, "testidwunit.ap:172");
/*
* Test simplified evaluation
*/
x0 = hqrndnormal(&rs, _state);
x1 = hqrndnormal(&rs, _state);
x2 = hqrndnormal(&rs, _state);
if( nx==1&&ny==1 )
{
ae_set_error_flag(err, ae_fp_neq(idwcalc1(&model, x0, _state),(double)(0)), __FILE__, __LINE__, "testidwunit.ap:181");
}
if( nx==2&&ny==1 )
{
ae_set_error_flag(err, ae_fp_neq(idwcalc2(&model, x0, x1, _state),(double)(0)), __FILE__, __LINE__, "testidwunit.ap:183");
}
if( nx==3&&ny==1 )
{
ae_set_error_flag(err, ae_fp_neq(idwcalc3(&model, x0, x1, x2, _state),(double)(0)), __FILE__, __LINE__, "testidwunit.ap:185");
}
/*
* Test generic evaluation
*/
ae_vector_set_length(&x, nx, _state);
for(i=0; i<=nx-1; i++)
{
x.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&y, 0, _state);
idwcalc(&model, &x, &y, _state);
ae_set_error_flag(err, y.cnt!=ny, __FILE__, __LINE__, "testidwunit.ap:195");
if( *err )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=ny-1; i++)
{
ae_set_error_flag(err, ae_fp_neq(y.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testidwunit.ap:199");
}
ae_vector_set_length(&y, 0, _state);
idwcalcbuf(&model, &x, &y, _state);
ae_set_error_flag(err, y.cnt!=ny, __FILE__, __LINE__, "testidwunit.ap:202");
if( *err )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=ny-1; i++)
{
ae_set_error_flag(err, ae_fp_neq(y.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testidwunit.ap:206");
}
ae_vector_set_length(&y, 0, _state);
idwtscalcbuf(&model, &buffer, &x, &y, _state);
ae_set_error_flag(err, y.cnt!=ny, __FILE__, __LINE__, "testidwunit.ap:209");
if( *err )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=ny-1; i++)
{
ae_set_error_flag(err, ae_fp_neq(y.ptr.p_double[i],(double)(0)), __FILE__, __LINE__, "testidwunit.ap:213");
}
}
}
/*
* Generate random dataset with distinct points, test interpolation
* properties (target function is reproduced almost exactly, the model
* is continuous)
*/
for(pass=1; pass<=20; pass++)
{
n = 1+hqrnduniformi(&rs, 25, _state);
nx = 1+hqrnduniformi(&rs, 4, _state);
ny = 1+hqrnduniformi(&rs, 4, _state);
ae_vector_set_length(&x, nx, _state);
ae_vector_set_length(&xx, nx, _state);
ae_vector_set_length(&y, ny, _state);
/*
* Generate dataset with distinct points
*/
ae_matrix_set_length(&xy, n, nx+ny, _state);
ae_vector_set_length(&meany, ny, _state);
for(j=0; j<=ny-1; j++)
{
meany.ptr.p_double[j] = (double)(0);
}
i = 0;
while(i=0 )
{
testidwunit_testcontinuity(&model, nx, ny, &x, &xx, 10000, continuitytesting, err, _state);
}
}
/*
* Test evaluation at remote points
*/
ae_vector_set_length(&x, nx, _state);
for(j=0; j<=nx-1; j++)
{
x.ptr.p_double[j] = 1.0E20*(2*hqrnduniformi(&rs, 2, _state)-1);
}
idwcalc(&model, &x, &y, _state);
for(j=0; j<=ny-1; j++)
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[j]-meany.ptr.p_double[j], _state),tol), __FILE__, __LINE__, "testidwunit.ap:424");
}
}
/*
* Generate random dataset with NONDISTINCT points, test approximation
* properties and error reports.
*/
for(pass=1; pass<=20; pass++)
{
n = 2*(1+hqrnduniformi(&rs, 10, _state));
nx = 1+hqrnduniformi(&rs, 4, _state);
ny = 1+hqrnduniformi(&rs, 4, _state);
ae_vector_set_length(&x, nx, _state);
ae_vector_set_length(&xx, nx, _state);
ae_vector_set_length(&y, ny, _state);
ae_vector_set_length(&meany, ny, _state);
/*
* Generate dataset with nondistinct points, each point is repeated;
* compute reference values of the error metrics
*/
ae_matrix_set_length(&xy, n, nx+ny, _state);
refrms = (double)(0);
refavg = (double)(0);
refmax = (double)(0);
refrss = (double)(0);
reftss = (double)(0);
for(j=0; j<=ny-1; j++)
{
meany.ptr.p_double[j] = (double)(0);
}
i = 0;
while(i<=n/2-1)
{
/*
* Generate two copies of the same point
*/
for(j=0; j<=nx+ny-1; j++)
{
v = hqrndnormal(&rs, _state);
xy.ptr.pp_double[2*i+0][j] = v;
xy.ptr.pp_double[2*i+1][j] = v;
}
/*
* Test distance between newly generated point and other ones.
* Repeat point generation if it is too close to some other point.
*/
v = ae_maxrealnumber;
for(i0=0; i0<=2*i-1; i0++)
{
vv = (double)(0);
for(j=0; j<=nx-1; j++)
{
vv = ae_maxreal(vv, ae_fabs(xy.ptr.pp_double[2*i+0][j]-xy.ptr.pp_double[i0][j], _state), _state);
}
v = ae_minreal(v, vv, _state);
}
if( ae_fp_less(v,mindistinf) )
{
continue;
}
/*
* Update meanY
*/
for(j=0; j<=ny-1; j++)
{
meany.ptr.p_double[j] = meany.ptr.p_double[j]+(xy.ptr.pp_double[2*i+0][nx+j]+xy.ptr.pp_double[2*i+1][nx+j])/n;
}
/*
* Apply perturbation to the target value
*/
for(j=0; j<=ny-1; j++)
{
v = ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
xy.ptr.pp_double[2*i+0][nx+j] = xy.ptr.pp_double[2*i+0][nx+j]+v;
xy.ptr.pp_double[2*i+1][nx+j] = xy.ptr.pp_double[2*i+1][nx+j]-v;
v = ae_fabs(v, _state);
refrms = refrms+2*v*v;
refavg = refavg+2*v;
refmax = ae_maxreal(refmax, v, _state);
refrss = refrss+2*v*v;
}
/*
* Next I
*/
i = i+1;
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=ny-1; j++)
{
reftss = reftss+ae_sqr(xy.ptr.pp_double[i][nx+j]-meany.ptr.p_double[j], _state);
}
}
refrms = ae_sqrt(refrms/(n*ny), _state);
refavg = refavg/(n*ny);
refr2 = 1.0-refrss/coalesce(reftss, (double)(1), _state);
/*
* Build IDW model
*/
initdone = ae_false;
idwbuildercreate(nx, ny, &builder, _state);
if( algotype==0 )
{
initdone = ae_true;
shepardp = nx*(1+hqrnduniformr(&rs, _state));
idwbuildersetalgotextbookshepard(&builder, shepardp, _state);
}
if( algotype==1 )
{
initdone = ae_true;
rbase = ae_pow(2.0, 4*hqrnduniformr(&rs, _state)-2, _state);
idwbuildersetalgotextbookmodshepard(&builder, rbase, _state);
}
if( algotype==2 )
{
initdone = ae_true;
rbase = ae_pow(2.0, 4*hqrnduniformr(&rs, _state)-2, _state);
idwbuildersetalgomstab(&builder, rbase, _state);
}
ae_assert(initdone, "TestCommon: unexpected AlgoType", _state);
idwbuildersetpoints(&builder, &xy, n, _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
/*
* Fit and store result directly into the variable
*/
idwfit(&builder, &model, &rep, _state);
}
else
{
/*
* Fit, store result to temporary, pass through the serializer
*/
idwfit(&builder, &model1, &rep, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
idwalloc(&_local_serializer, &model1, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
idwserialize(&_local_serializer, &model1, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
idwunserialize(&_local_serializer, &model, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
}
idwcreatecalcbuffer(&model, &buffer, _state);
/*
* Test error metrics
*/
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state),tol), __FILE__, __LINE__, "testidwunit.ap:562");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state),tol), __FILE__, __LINE__, "testidwunit.ap:563");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.maxerror-refmax, _state),tol), __FILE__, __LINE__, "testidwunit.ap:564");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rep.r2-refr2, _state),tol), __FILE__, __LINE__, "testidwunit.ap:565");
/*
* Test ability to reproduce mean over non-distinct points
*
* NOTE: we do not test all evaluation functions, just IDWCalc()
*/
for(i=0; i<=n/2-1; i++)
{
for(j=0; j<=nx-1; j++)
{
x.ptr.p_double[j] = xy.ptr.pp_double[2*i+0][j];
}
idwcalc(&model, &x, &y, _state);
for(j=0; j<=ny-1; j++)
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[j]-0.5*(xy.ptr.pp_double[2*i+0][nx+j]+xy.ptr.pp_double[2*i+1][nx+j]), _state),tol), __FILE__, __LINE__, "testidwunit.ap:578");
}
}
/*
* Test continuity properties:
* * continuity is guaranteed for original Shepard's method, MSTAB and MSMOOTH
* * modified Shepard method does not guarantee continuity of the model, but
* we can be sure that model is continuous along line connecting two nearest
* points
*/
for(k=0; k<=1; k++)
{
i0 = hqrnduniformi(&rs, n, _state);
for(j=0; j<=nx-1; j++)
{
x.ptr.p_double[j] = xy.ptr.pp_double[i0][j];
}
i1 = -1;
v = ae_maxrealnumber;
for(i=0; i<=n-1; i++)
{
vv = (double)(0);
for(j=0; j<=nx-1; j++)
{
vv = vv+ae_sqr(x.ptr.p_double[j]-xy.ptr.pp_double[i][j], _state);
}
if( ae_fp_less(vv,v)&&ae_fp_greater(vv,(double)(0)) )
{
i1 = i;
for(j=0; j<=nx-1; j++)
{
xx.ptr.p_double[j] = xy.ptr.pp_double[i][j];
}
v = vv;
}
}
if( i1<0 )
{
i1 = hqrnduniformi(&rs, n, _state);
for(j=0; j<=nx-1; j++)
{
xx.ptr.p_double[j] = xy.ptr.pp_double[i1][j];
}
}
continuitytesting = 1;
if( algotype==0 )
{
continuitytesting = 0;
}
if( algotype==1 )
{
continuitytesting = -1;
}
if( continuitytesting>=0 )
{
testidwunit_testcontinuity(&model, nx, ny, &x, &xx, 10000, continuitytesting, err, _state);
}
}
}
/*
* Test correct handling of the prior term
*/
n = 10;
for(pass=1; pass<=20; pass++)
{
nx = 1+hqrnduniformi(&rs, 4, _state);
ny = 1+hqrnduniformi(&rs, 4, _state);
ae_vector_set_length(&x, nx, _state);
ae_vector_set_length(&y, ny, _state);
ae_matrix_set_length(&xy, n, nx+ny, _state);
ae_vector_set_length(&meany, ny, _state);
for(j=0; j<=ny-1; j++)
{
meany.ptr.p_double[j] = (double)(0);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=nx-1; j++)
{
xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
for(j=0; j<=ny-1; j++)
{
xy.ptr.pp_double[i][nx+j] = hqrndnormal(&rs, _state);
meany.ptr.p_double[j] = meany.ptr.p_double[j]+xy.ptr.pp_double[i][nx+j]/n;
}
}
initdone = ae_false;
idwbuildercreate(nx, ny, &builder, _state);
if( algotype==0 )
{
initdone = ae_true;
shepardp = 1+(nx+1)*hqrnduniformr(&rs, _state);
idwbuildersetalgotextbookshepard(&builder, shepardp, _state);
}
if( algotype==1 )
{
initdone = ae_true;
rbase = ae_pow(2.0, 4*hqrnduniformr(&rs, _state)-2, _state);
idwbuildersetalgotextbookmodshepard(&builder, rbase, _state);
}
if( algotype==2 )
{
initdone = ae_true;
rbase = ae_pow(2.0, 4*hqrnduniformr(&rs, _state)-2, _state);
idwbuildersetalgomstab(&builder, rbase, _state);
}
ae_assert(initdone, "TestCommon: unexpected AlgoType (prior test)", _state);
idwbuildersetpoints(&builder, &xy, n, _state);
/*
* Zero prior (not tested with textbook Shepard method)
*/
if( algotype!=0 )
{
idwbuildersetzeroterm(&builder, _state);
idwfit(&builder, &model, &rep, _state);
for(j=0; j<=nx-1; j++)
{
x.ptr.p_double[j] = 1.0E20*(2*hqrnduniformi(&rs, 2, _state)-1);
}
idwcalc(&model, &x, &y, _state);
for(j=0; j<=ny-1; j++)
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[j], _state),tol), __FILE__, __LINE__, "testidwunit.ap:684");
}
}
/*
* Mean prior
*/
idwbuildersetconstterm(&builder, _state);
idwfit(&builder, &model, &rep, _state);
for(j=0; j<=nx-1; j++)
{
x.ptr.p_double[j] = 1.0E20*(2*hqrnduniformi(&rs, 2, _state)-1);
}
idwcalc(&model, &x, &y, _state);
for(j=0; j<=ny-1; j++)
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[j]-meany.ptr.p_double[j], _state),tol), __FILE__, __LINE__, "testidwunit.ap:696");
}
/*
* User-specified prior (not tested with textbook Shepard method)
*/
if( algotype!=0 )
{
v = hqrndnormal(&rs, _state);
idwbuildersetuserterm(&builder, v, _state);
idwfit(&builder, &model, &rep, _state);
for(j=0; j<=nx-1; j++)
{
x.ptr.p_double[j] = 1.0E20*(2*hqrnduniformi(&rs, 2, _state)-1);
}
idwcalc(&model, &x, &y, _state);
for(j=0; j<=ny-1; j++)
{
ae_set_error_flag(err, ae_fp_greater(ae_fabs(y.ptr.p_double[j]-v, _state),tol), __FILE__, __LINE__, "testidwunit.ap:710");
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Test MSTAB; Err is set to True on failure, unchanged otherwise.
*************************************************************************/
static void testidwunit_testmstab(ae_bool* err, ae_state *_state)
{
ae_frame _frame_block;
ae_matrix xy;
ae_int_t i;
ae_int_t n;
double v;
double vv;
double x0;
double x1;
double rbase;
idwmodel model;
idwbuilder builder;
idwreport rep;
hqrndstate rs;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
memset(&model, 0, sizeof(model));
memset(&builder, 0, sizeof(builder));
memset(&rep, 0, sizeof(rep));
memset(&rs, 0, sizeof(rs));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_idwmodel_init(&model, _state, ae_true);
_idwbuilder_init(&builder, _state, ae_true);
_idwreport_init(&rep, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Basic test #1: nonzero derivative
* * XY = [[-1,-1],[0,0,],[1,1]]
* * RBase>=2
* * derivative at x=0 must be positive and bigger than 0.1
*/
ae_matrix_set_length(&xy, 3, 2, _state);
for(i=0; i<=2; i++)
{
xy.ptr.pp_double[i][0] = (double)(i-1);
xy.ptr.pp_double[i][1] = (double)(i-1);
}
idwbuildercreate(1, 1, &builder, _state);
rbase = ae_pow(2.0, 1.0+hqrnduniformr(&rs, _state), _state);
idwbuildersetalgomstab(&builder, rbase, _state);
idwbuildersetpoints(&builder, &xy, 3, _state);
idwfit(&builder, &model, &rep, _state);
v = 0.01;
ae_set_error_flag(err, ae_fp_less((idwcalc1(&model, v, _state)-idwcalc1(&model, -v, _state))/(2*v),0.1), __FILE__, __LINE__, "testidwunit.ap:758");
/*
* Basic test #2: good smoothness
* * 2D task, dataset is composed from 3 parallel lines
* along y=-0.1, y=0, y=+0.1, with outer lines having
* constant zero target value, inner line having constant
* target equal to 1
* * RBase=1 is used
* * we test that function value does not change significantly
* along the line
*/
n = 100;
ae_matrix_set_length(&xy, 3*n, 3, _state);
for(i=0; i<=n-1; i++)
{
xy.ptr.pp_double[3*i+0][0] = (double)i/(double)(n-1);
xy.ptr.pp_double[3*i+0][1] = -0.1;
xy.ptr.pp_double[3*i+0][2] = (double)(0);
xy.ptr.pp_double[3*i+1][0] = (double)i/(double)(n-1);
xy.ptr.pp_double[3*i+1][1] = (double)(0);
xy.ptr.pp_double[3*i+1][2] = (double)(1);
xy.ptr.pp_double[3*i+2][0] = (double)i/(double)(n-1);
xy.ptr.pp_double[3*i+2][1] = 0.1;
xy.ptr.pp_double[3*i+2][2] = (double)(0);
}
rbase = 1.0;
idwbuildercreate(2, 1, &builder, _state);
idwbuildersetalgomstab(&builder, rbase, _state);
idwbuildersetpoints(&builder, &xy, 3*n, _state);
idwfit(&builder, &model, &rep, _state);
v = (double)(0);
for(i=0; i<=1000; i++)
{
v = ae_maxreal(v, ae_fabs(idwcalc2(&model, hqrnduniformr(&rs, _state), -0.1, _state), _state), _state);
v = ae_maxreal(v, ae_fabs(idwcalc2(&model, hqrnduniformr(&rs, _state), 0.1, _state), _state), _state);
v = ae_maxreal(v, ae_fabs(idwcalc2(&model, hqrnduniformr(&rs, _state), (double)(0), _state)-1, _state), _state);
}
ae_set_error_flag(err, ae_fp_greater(v,0.001), __FILE__, __LINE__, "testidwunit.ap:796");
/*
* Continuity when moving away from the dataset
*/
ae_matrix_set_length(&xy, 1, 2, _state);
xy.ptr.pp_double[0][0] = (double)(0);
xy.ptr.pp_double[0][1] = (double)(1);
rbase = 1.0;
idwbuildercreate(1, 1, &builder, _state);
idwbuildersetalgomstab(&builder, rbase, _state);
idwbuildersetpoints(&builder, &xy, 1, _state);
idwbuildersetzeroterm(&builder, _state);
idwfit(&builder, &model, &rep, _state);
ae_set_error_flag(err, ae_fp_neq(idwcalc1(&model, (double)(100000), _state),(double)(0)), __FILE__, __LINE__, "testidwunit.ap:810");
v = (double)(0);
for(i=0; i<=500; i++)
{
x0 = 1.2*rbase*((double)i/(double)500);
x1 = 1.2*rbase*((double)(i+1)/(double)500);
v = ae_maxreal(v, ae_fabs((idwcalc1(&model, x1, _state)-idwcalc1(&model, x0, _state))/(x1-x0), _state), _state);
}
vv = (double)(0);
for(i=0; i<=1000; i++)
{
x0 = 1.2*rbase*((double)i/(double)1000);
x1 = 1.2*rbase*((double)(i+1)/(double)1000);
vv = ae_maxreal(vv, ae_fabs((idwcalc1(&model, x1, _state)-idwcalc1(&model, x0, _state))/(x1-x0), _state), _state);
}
ae_set_error_flag(err, ae_fp_greater(vv/v,1.333), __FILE__, __LINE__, "testidwunit.ap:825");
ae_frame_leave(_state);
}
static void testratintunit_poldiff2(/* Real */ ae_vector* x,
/* Real */ ae_vector* f,
ae_int_t n,
double t,
double* p,
double* dp,
double* d2p,
ae_state *_state);
static void testratintunit_brcunset(barycentricinterpolant* b,
ae_state *_state);
ae_bool testratint(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_bool waserrors;
ae_bool bcerrors;
ae_bool nperrors;
double threshold;
double lipschitztol;
ae_int_t passcount;
barycentricinterpolant b1;
barycentricinterpolant b2;
ae_vector x;
ae_vector x2;
ae_vector y;
ae_vector y2;
ae_vector w;
ae_vector w2;
ae_vector xc;
ae_vector yc;
ae_vector dc;
double h;
double s1;
double s2;
ae_int_t n;
ae_int_t n2;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t d;
ae_int_t pass;
double maxerr;
double t;
double a;
double b;
double s;
double v0;
double v1;
double v2;
double v3;
double d0;
double d1;
double d2;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&b1, 0, sizeof(b1));
memset(&b2, 0, sizeof(b2));
memset(&x, 0, sizeof(x));
memset(&x2, 0, sizeof(x2));
memset(&y, 0, sizeof(y));
memset(&y2, 0, sizeof(y2));
memset(&w, 0, sizeof(w));
memset(&w2, 0, sizeof(w2));
memset(&xc, 0, sizeof(xc));
memset(&yc, 0, sizeof(yc));
memset(&dc, 0, sizeof(dc));
_barycentricinterpolant_init(&b1, _state, ae_true);
_barycentricinterpolant_init(&b2, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&yc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&dc, 0, DT_INT, _state, ae_true);
nperrors = ae_false;
bcerrors = ae_false;
waserrors = ae_false;
/*
* PassCount number of repeated passes
* Threshold error tolerance
* LipschitzTol Lipschitz constant increase allowed
* when calculating constant on a twice denser grid
*/
passcount = 5;
threshold = 1000000*ae_machineepsilon;
lipschitztol = 1.3;
/*
* Basic barycentric functions
*/
for(n=1; n<=10; n++)
{
/*
* randomized tests
*/
for(pass=1; pass<=passcount; pass++)
{
/*
* generate weights from polynomial interpolation
*/
v0 = 1+0.4*ae_randomreal(_state)-0.2;
v1 = 2*ae_randomreal(_state)-1;
v2 = 2*ae_randomreal(_state)-1;
v3 = 2*ae_randomreal(_state)-1;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
ae_vector_set_length(&w, n, _state);
for(i=0; i<=n-1; i++)
{
if( n==1 )
{
x.ptr.p_double[i] = (double)(0);
}
else
{
x.ptr.p_double[i] = v0*ae_cos(i*ae_pi/(n-1), _state);
}
y.ptr.p_double[i] = ae_sin(v1*x.ptr.p_double[i], _state)+ae_cos(v2*x.ptr.p_double[i], _state)+ae_exp(v3*x.ptr.p_double[i], _state);
}
for(j=0; j<=n-1; j++)
{
w.ptr.p_double[j] = (double)(1);
for(k=0; k<=n-1; k++)
{
if( k!=j )
{
w.ptr.p_double[j] = w.ptr.p_double[j]/(x.ptr.p_double[j]-x.ptr.p_double[k]);
}
}
}
barycentricbuildxyw(&x, &y, &w, n, &b1, _state);
/*
* unpack, then pack again and compare
*/
testratintunit_brcunset(&b2, _state);
barycentricunpack(&b1, &n2, &x2, &y2, &w2, _state);
bcerrors = bcerrors||n2!=n;
barycentricbuildxyw(&x2, &y2, &w2, n2, &b2, _state);
t = 2*ae_randomreal(_state)-1;
bcerrors = bcerrors||ae_fp_greater(ae_fabs(barycentriccalc(&b1, t, _state)-barycentriccalc(&b2, t, _state), _state),threshold);
/*
* copy, compare
*/
testratintunit_brcunset(&b2, _state);
barycentriccopy(&b1, &b2, _state);
t = 2*ae_randomreal(_state)-1;
bcerrors = bcerrors||ae_fp_greater(ae_fabs(barycentriccalc(&b1, t, _state)-barycentriccalc(&b2, t, _state), _state),threshold);
/*
* test interpolation properties
*/
for(i=0; i<=n-1; i++)
{
/*
* test interpolation at nodes
*/
bcerrors = bcerrors||ae_fp_greater(ae_fabs(barycentriccalc(&b1, x.ptr.p_double[i], _state)-y.ptr.p_double[i], _state),threshold*ae_fabs(y.ptr.p_double[i], _state));
/*
* compare with polynomial interpolation
*/
t = 2*ae_randomreal(_state)-1;
testratintunit_poldiff2(&x, &y, n, t, &v0, &v1, &v2, _state);
bcerrors = bcerrors||ae_fp_greater(ae_fabs(barycentriccalc(&b1, t, _state)-v0, _state),threshold*ae_maxreal(ae_fabs(v0, _state), (double)(1), _state));
/*
* test continuity between nodes
* calculate Lipschitz constant on two grids -
* dense and even more dense. If Lipschitz constant
* on a denser grid is significantly increased,
* continuity test is failed
*/
t = 3.0;
k = 100;
s1 = (double)(0);
for(j=0; j<=k-1; j++)
{
v1 = x.ptr.p_double[i]+(t-x.ptr.p_double[i])*j/k;
v2 = x.ptr.p_double[i]+(t-x.ptr.p_double[i])*(j+1)/k;
s1 = ae_maxreal(s1, ae_fabs(barycentriccalc(&b1, v2, _state)-barycentriccalc(&b1, v1, _state), _state)/ae_fabs(v2-v1, _state), _state);
}
k = 2*k;
s2 = (double)(0);
for(j=0; j<=k-1; j++)
{
v1 = x.ptr.p_double[i]+(t-x.ptr.p_double[i])*j/k;
v2 = x.ptr.p_double[i]+(t-x.ptr.p_double[i])*(j+1)/k;
s2 = ae_maxreal(s2, ae_fabs(barycentriccalc(&b1, v2, _state)-barycentriccalc(&b1, v1, _state), _state)/ae_fabs(v2-v1, _state), _state);
}
bcerrors = bcerrors||(ae_fp_greater(s2,lipschitztol*s1)&&ae_fp_greater(s1,threshold*k));
}
/*
* test differentiation properties
*/
for(i=0; i<=n-1; i++)
{
t = 2*ae_randomreal(_state)-1;
testratintunit_poldiff2(&x, &y, n, t, &v0, &v1, &v2, _state);
d0 = (double)(0);
d1 = (double)(0);
d2 = (double)(0);
barycentricdiff1(&b1, t, &d0, &d1, _state);
bcerrors = bcerrors||ae_fp_greater(ae_fabs(v0-d0, _state),threshold*ae_maxreal(ae_fabs(v0, _state), (double)(1), _state));
bcerrors = bcerrors||ae_fp_greater(ae_fabs(v1-d1, _state),threshold*ae_maxreal(ae_fabs(v1, _state), (double)(1), _state));
d0 = (double)(0);
d1 = (double)(0);
d2 = (double)(0);
barycentricdiff2(&b1, t, &d0, &d1, &d2, _state);
bcerrors = bcerrors||ae_fp_greater(ae_fabs(v0-d0, _state),threshold*ae_maxreal(ae_fabs(v0, _state), (double)(1), _state));
bcerrors = bcerrors||ae_fp_greater(ae_fabs(v1-d1, _state),threshold*ae_maxreal(ae_fabs(v1, _state), (double)(1), _state));
bcerrors = bcerrors||ae_fp_greater(ae_fabs(v2-d2, _state),ae_sqrt(threshold, _state)*ae_maxreal(ae_fabs(v2, _state), (double)(1), _state));
}
/*
* test linear translation
*/
t = 2*ae_randomreal(_state)-1;
a = 2*ae_randomreal(_state)-1;
b = 2*ae_randomreal(_state)-1;
testratintunit_brcunset(&b2, _state);
barycentriccopy(&b1, &b2, _state);
barycentriclintransx(&b2, a, b, _state);
bcerrors = bcerrors||ae_fp_greater(ae_fabs(barycentriccalc(&b1, a*t+b, _state)-barycentriccalc(&b2, t, _state), _state),threshold);
a = (double)(0);
b = 2*ae_randomreal(_state)-1;
testratintunit_brcunset(&b2, _state);
barycentriccopy(&b1, &b2, _state);
barycentriclintransx(&b2, a, b, _state);
bcerrors = bcerrors||ae_fp_greater(ae_fabs(barycentriccalc(&b1, a*t+b, _state)-barycentriccalc(&b2, t, _state), _state),threshold);
a = 2*ae_randomreal(_state)-1;
b = 2*ae_randomreal(_state)-1;
testratintunit_brcunset(&b2, _state);
barycentriccopy(&b1, &b2, _state);
barycentriclintransy(&b2, a, b, _state);
bcerrors = bcerrors||ae_fp_greater(ae_fabs(a*barycentriccalc(&b1, t, _state)+b-barycentriccalc(&b2, t, _state), _state),threshold);
}
}
for(pass=0; pass<=3; pass++)
{
/*
* Crash-test: small numbers, large numbers
*/
ae_vector_set_length(&x, 4, _state);
ae_vector_set_length(&y, 4, _state);
ae_vector_set_length(&w, 4, _state);
h = (double)(1);
if( pass%2==0 )
{
h = 100*ae_minrealnumber;
}
if( pass%2==1 )
{
h = 0.01*ae_maxrealnumber;
}
x.ptr.p_double[0] = 0*h;
x.ptr.p_double[1] = 1*h;
x.ptr.p_double[2] = 2*h;
x.ptr.p_double[3] = 3*h;
y.ptr.p_double[0] = 0*h;
y.ptr.p_double[1] = 1*h;
y.ptr.p_double[2] = 2*h;
y.ptr.p_double[3] = 3*h;
w.ptr.p_double[0] = -1/(x.ptr.p_double[1]-x.ptr.p_double[0]);
w.ptr.p_double[1] = 1*(1/(x.ptr.p_double[1]-x.ptr.p_double[0])+1/(x.ptr.p_double[2]-x.ptr.p_double[1]));
w.ptr.p_double[2] = -1*(1/(x.ptr.p_double[2]-x.ptr.p_double[1])+1/(x.ptr.p_double[3]-x.ptr.p_double[2]));
w.ptr.p_double[3] = 1/(x.ptr.p_double[3]-x.ptr.p_double[2]);
v0 = (double)(0);
if( pass/2==0 )
{
v0 = (double)(0);
}
if( pass/2==1 )
{
v0 = 0.6*h;
}
barycentricbuildxyw(&x, &y, &w, 4, &b1, _state);
t = barycentriccalc(&b1, v0, _state);
d0 = (double)(0);
d1 = (double)(0);
d2 = (double)(0);
barycentricdiff1(&b1, v0, &d0, &d1, _state);
bcerrors = bcerrors||ae_fp_greater(ae_fabs(t-v0, _state),threshold*v0);
bcerrors = bcerrors||ae_fp_greater(ae_fabs(d0-v0, _state),threshold*v0);
bcerrors = bcerrors||ae_fp_greater(ae_fabs(d1-1, _state),1000*threshold);
}
/*
* crash test: large abscissas, small argument
*
* test for errors in D0 is not very strict
* because renormalization used in Diff1()
* destroys part of precision.
*/
ae_vector_set_length(&x, 4, _state);
ae_vector_set_length(&y, 4, _state);
ae_vector_set_length(&w, 4, _state);
h = 0.01*ae_maxrealnumber;
x.ptr.p_double[0] = 0*h;
x.ptr.p_double[1] = 1*h;
x.ptr.p_double[2] = 2*h;
x.ptr.p_double[3] = 3*h;
y.ptr.p_double[0] = 0*h;
y.ptr.p_double[1] = 1*h;
y.ptr.p_double[2] = 2*h;
y.ptr.p_double[3] = 3*h;
w.ptr.p_double[0] = -1/(x.ptr.p_double[1]-x.ptr.p_double[0]);
w.ptr.p_double[1] = 1*(1/(x.ptr.p_double[1]-x.ptr.p_double[0])+1/(x.ptr.p_double[2]-x.ptr.p_double[1]));
w.ptr.p_double[2] = -1*(1/(x.ptr.p_double[2]-x.ptr.p_double[1])+1/(x.ptr.p_double[3]-x.ptr.p_double[2]));
w.ptr.p_double[3] = 1/(x.ptr.p_double[3]-x.ptr.p_double[2]);
v0 = 100*ae_minrealnumber;
barycentricbuildxyw(&x, &y, &w, 4, &b1, _state);
t = barycentriccalc(&b1, v0, _state);
d0 = (double)(0);
d1 = (double)(0);
d2 = (double)(0);
barycentricdiff1(&b1, v0, &d0, &d1, _state);
bcerrors = bcerrors||ae_fp_greater(ae_fabs(t, _state),v0*(1+threshold));
bcerrors = bcerrors||ae_fp_greater(ae_fabs(d0, _state),v0*(1+threshold));
bcerrors = bcerrors||ae_fp_greater(ae_fabs(d1-1, _state),1000*threshold);
/*
* crash test: test safe barycentric formula
*/
ae_vector_set_length(&x, 4, _state);
ae_vector_set_length(&y, 4, _state);
ae_vector_set_length(&w, 4, _state);
h = 2*ae_minrealnumber;
x.ptr.p_double[0] = 0*h;
x.ptr.p_double[1] = 1*h;
x.ptr.p_double[2] = 2*h;
x.ptr.p_double[3] = 3*h;
y.ptr.p_double[0] = 0*h;
y.ptr.p_double[1] = 1*h;
y.ptr.p_double[2] = 2*h;
y.ptr.p_double[3] = 3*h;
w.ptr.p_double[0] = -1/(x.ptr.p_double[1]-x.ptr.p_double[0]);
w.ptr.p_double[1] = 1*(1/(x.ptr.p_double[1]-x.ptr.p_double[0])+1/(x.ptr.p_double[2]-x.ptr.p_double[1]));
w.ptr.p_double[2] = -1*(1/(x.ptr.p_double[2]-x.ptr.p_double[1])+1/(x.ptr.p_double[3]-x.ptr.p_double[2]));
w.ptr.p_double[3] = 1/(x.ptr.p_double[3]-x.ptr.p_double[2]);
v0 = ae_minrealnumber;
barycentricbuildxyw(&x, &y, &w, 4, &b1, _state);
t = barycentriccalc(&b1, v0, _state);
bcerrors = bcerrors||ae_fp_greater(ae_fabs(t-v0, _state)/v0,threshold);
/*
* Testing "No Poles" interpolation
*/
maxerr = (double)(0);
for(pass=1; pass<=passcount-1; pass++)
{
ae_vector_set_length(&x, 1, _state);
ae_vector_set_length(&y, 1, _state);
x.ptr.p_double[0] = 2*ae_randomreal(_state)-1;
y.ptr.p_double[0] = 2*ae_randomreal(_state)-1;
barycentricbuildfloaterhormann(&x, &y, 1, 1, &b1, _state);
maxerr = ae_maxreal(maxerr, ae_fabs(barycentriccalc(&b1, 2*ae_randomreal(_state)-1, _state)-y.ptr.p_double[0], _state), _state);
}
for(n=2; n<=10; n++)
{
/*
* compare interpolant built by subroutine
* with interpolant built by hands
*/
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
ae_vector_set_length(&w, n, _state);
ae_vector_set_length(&w2, n, _state);
/*
* D=1, non-equidistant nodes
*/
for(pass=1; pass<=passcount; pass++)
{
/*
* Initialize X, Y, W
*/
a = -1-1*ae_randomreal(_state);
b = 1+1*ae_randomreal(_state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = ae_atan((b-a)*i/(n-1)+a, _state);
}
for(i=0; i<=n-1; i++)
{
y.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
w.ptr.p_double[0] = -1/(x.ptr.p_double[1]-x.ptr.p_double[0]);
s = (double)(1);
for(i=1; i<=n-2; i++)
{
w.ptr.p_double[i] = s*(1/(x.ptr.p_double[i]-x.ptr.p_double[i-1])+1/(x.ptr.p_double[i+1]-x.ptr.p_double[i]));
s = -s;
}
w.ptr.p_double[n-1] = s/(x.ptr.p_double[n-1]-x.ptr.p_double[n-2]);
for(i=0; i<=n-1; i++)
{
k = ae_randominteger(n, _state);
if( k!=i )
{
t = x.ptr.p_double[i];
x.ptr.p_double[i] = x.ptr.p_double[k];
x.ptr.p_double[k] = t;
t = y.ptr.p_double[i];
y.ptr.p_double[i] = y.ptr.p_double[k];
y.ptr.p_double[k] = t;
t = w.ptr.p_double[i];
w.ptr.p_double[i] = w.ptr.p_double[k];
w.ptr.p_double[k] = t;
}
}
/*
* Build and test
*/
barycentricbuildfloaterhormann(&x, &y, n, 1, &b1, _state);
barycentricbuildxyw(&x, &y, &w, n, &b2, _state);
for(i=1; i<=2*n; i++)
{
t = a+(b-a)*ae_randomreal(_state);
maxerr = ae_maxreal(maxerr, ae_fabs(barycentriccalc(&b1, t, _state)-barycentriccalc(&b2, t, _state), _state), _state);
}
}
/*
* D = 0, 1, 2. Equidistant nodes.
*/
for(d=0; d<=2; d++)
{
for(pass=1; pass<=passcount; pass++)
{
/*
* Skip incorrect (N,D) pairs
*/
if( n<2*d )
{
continue;
}
/*
* Initialize X, Y, W
*/
a = -1-1*ae_randomreal(_state);
b = 1+1*ae_randomreal(_state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = (b-a)*i/(n-1)+a;
}
for(i=0; i<=n-1; i++)
{
y.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
s = (double)(1);
if( d==0 )
{
for(i=0; i<=n-1; i++)
{
w.ptr.p_double[i] = s;
s = -s;
}
}
if( d==1 )
{
w.ptr.p_double[0] = -s;
for(i=1; i<=n-2; i++)
{
w.ptr.p_double[i] = 2*s;
s = -s;
}
w.ptr.p_double[n-1] = s;
}
if( d==2 )
{
w.ptr.p_double[0] = s;
w.ptr.p_double[1] = -3*s;
for(i=2; i<=n-3; i++)
{
w.ptr.p_double[i] = 4*s;
s = -s;
}
w.ptr.p_double[n-2] = 3*s;
w.ptr.p_double[n-1] = -s;
}
/*
* Mix
*/
for(i=0; i<=n-1; i++)
{
k = ae_randominteger(n, _state);
if( k!=i )
{
t = x.ptr.p_double[i];
x.ptr.p_double[i] = x.ptr.p_double[k];
x.ptr.p_double[k] = t;
t = y.ptr.p_double[i];
y.ptr.p_double[i] = y.ptr.p_double[k];
y.ptr.p_double[k] = t;
t = w.ptr.p_double[i];
w.ptr.p_double[i] = w.ptr.p_double[k];
w.ptr.p_double[k] = t;
}
}
/*
* Build and test
*/
barycentricbuildfloaterhormann(&x, &y, n, d, &b1, _state);
barycentricbuildxyw(&x, &y, &w, n, &b2, _state);
for(i=1; i<=2*n; i++)
{
t = a+(b-a)*ae_randomreal(_state);
maxerr = ae_maxreal(maxerr, ae_fabs(barycentriccalc(&b1, t, _state)-barycentriccalc(&b2, t, _state), _state), _state);
}
}
}
}
if( ae_fp_greater(maxerr,threshold) )
{
nperrors = ae_true;
}
/*
* report
*/
waserrors = bcerrors||nperrors;
if( !silent )
{
printf("TESTING RATIONAL INTERPOLATION\n");
printf("BASIC BARYCENTRIC FUNCTIONS: ");
if( bcerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("FLOATER-HORMANN: ");
if( nperrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
/*
* end
*/
result = !waserrors;
ae_frame_leave(_state);
return result;
}
static void testratintunit_poldiff2(/* Real */ ae_vector* x,
/* Real */ ae_vector* f,
ae_int_t n,
double t,
double* p,
double* dp,
double* d2p,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector _f;
ae_int_t m;
ae_int_t i;
ae_vector df;
ae_vector d2f;
ae_frame_make(_state, &_frame_block);
memset(&_f, 0, sizeof(_f));
memset(&df, 0, sizeof(df));
memset(&d2f, 0, sizeof(d2f));
ae_vector_init_copy(&_f, f, _state, ae_true);
f = &_f;
*p = 0;
*dp = 0;
*d2p = 0;
ae_vector_init(&df, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d2f, 0, DT_REAL, _state, ae_true);
n = n-1;
ae_vector_set_length(&df, n+1, _state);
ae_vector_set_length(&d2f, n+1, _state);
for(i=0; i<=n; i++)
{
d2f.ptr.p_double[i] = (double)(0);
df.ptr.p_double[i] = (double)(0);
}
for(m=1; m<=n; m++)
{
for(i=0; i<=n-m; i++)
{
d2f.ptr.p_double[i] = ((t-x->ptr.p_double[i+m])*d2f.ptr.p_double[i]+(x->ptr.p_double[i]-t)*d2f.ptr.p_double[i+1]+2*df.ptr.p_double[i]-2*df.ptr.p_double[i+1])/(x->ptr.p_double[i]-x->ptr.p_double[i+m]);
df.ptr.p_double[i] = ((t-x->ptr.p_double[i+m])*df.ptr.p_double[i]+f->ptr.p_double[i]+(x->ptr.p_double[i]-t)*df.ptr.p_double[i+1]-f->ptr.p_double[i+1])/(x->ptr.p_double[i]-x->ptr.p_double[i+m]);
f->ptr.p_double[i] = ((t-x->ptr.p_double[i+m])*f->ptr.p_double[i]+(x->ptr.p_double[i]-t)*f->ptr.p_double[i+1])/(x->ptr.p_double[i]-x->ptr.p_double[i+m]);
}
}
*p = f->ptr.p_double[0];
*dp = df.ptr.p_double[0];
*d2p = d2f.ptr.p_double[0];
ae_frame_leave(_state);
}
static void testratintunit_brcunset(barycentricinterpolant* b,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector x;
ae_vector y;
ae_vector w;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&w, 0, sizeof(w));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
ae_vector_set_length(&x, 1, _state);
ae_vector_set_length(&y, 1, _state);
ae_vector_set_length(&w, 1, _state);
x.ptr.p_double[0] = (double)(0);
y.ptr.p_double[0] = (double)(0);
w.ptr.p_double[0] = (double)(1);
barycentricbuildxyw(&x, &y, &w, 1, b, _state);
ae_frame_leave(_state);
}
static void testfitsphereunit_testspherefittingls(ae_bool* err,
ae_state *_state);
static void testfitsphereunit_testspherefittingns(ae_bool* err,
ae_state *_state);
static void testfitsphereunit_testspherefittingvosswinkel2(ae_bool* err,
ae_state *_state);
static void testfitsphereunit_calcradii(/* Real */ ae_matrix* xy,
ae_int_t npoints,
ae_int_t nx,
/* Real */ ae_vector* cx,
double* rlo,
double* rhi,
ae_state *_state);
static void testfitsphereunit_calclserror(/* Real */ ae_matrix* xy,
ae_int_t npoints,
ae_int_t nx,
/* Real */ ae_vector* cx,
double* err,
ae_state *_state);
static void testfitsphereunit_addvalue(/* Real */ ae_matrix* xy,
ae_int_t* cnt,
double v,
ae_state *_state);
ae_bool testfitsphere(ae_bool silent, ae_state *_state)
{
ae_bool nserrors;
ae_bool lserrors;
ae_bool wereerrors;
ae_bool result;
nserrors = ae_false;
lserrors = ae_false;
/*
* Sphere fitting, several different test suites
*/
testfitsphereunit_testspherefittingls(&lserrors, _state);
testfitsphereunit_testspherefittingns(&nserrors, _state);
testfitsphereunit_testspherefittingvosswinkel2(&nserrors, _state);
/*
* report
*/
wereerrors = nserrors||lserrors;
if( !silent )
{
printf("TESTING FITSPHERE\n");
printf("* LEAST SQUARES CIRCLE FITTING ");
if( lserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* NON-SMOOTH FITTING (MC, MI, MZ) ");
if( nserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( wereerrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !wereerrors;
return result;
}
/*************************************************************************
This function tests least squares (LS) sphere fitting using generic
synthetic datasets
On failure sets Err to True (leaves it unchanged otherwise)
*************************************************************************/
static void testfitsphereunit_testspherefittingls(ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
hqrndstate rs;
ae_matrix xy;
double xtol;
ae_int_t npoints;
ae_int_t nx;
ae_vector cx;
ae_vector cy;
double rlo;
double rhi;
double ftol;
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
double vv;
double v0;
double v1;
ae_int_t problemtype;
ae_frame_make(_state, &_frame_block);
memset(&rs, 0, sizeof(rs));
memset(&xy, 0, sizeof(xy));
memset(&cx, 0, sizeof(cx));
memset(&cy, 0, sizeof(cy));
_hqrndstate_init(&rs, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&cx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&cy, 0, DT_REAL, _state, ae_true);
hqrndrandomize(&rs, _state);
xtol = 1.0E-5;
/*
* Generate random problem
*/
for(nx=1; nx<=4; nx++)
{
/*
* Generate synthetic dataset, at least 5 points
*/
npoints = 5+2*nx+hqrnduniformi(&rs, 50+ae_round(ae_pow((double)(4), (double)(nx), _state), _state), _state);
ae_matrix_set_length(&xy, npoints, nx, _state);
for(i=0; i<=npoints-1; i++)
{
v = (double)(0);
for(j=0; j<=nx-1; j++)
{
vv = hqrndnormal(&rs, _state);
v = v+ae_sqr(vv, _state);
xy.ptr.pp_double[i][j] = vv;
}
ae_assert(ae_fp_greater(v,(double)(0)), "Assertion failed", _state);
v = (1+0.1*hqrnduniformr(&rs, _state))/ae_sqrt(v, _state);
for(j=0; j<=nx-1; j++)
{
xy.ptr.pp_double[i][j] = xy.ptr.pp_double[i][j]*v;
}
}
/*
* Solve with generic solver, check
*/
unsetrealarray(&cx, _state);
rlo = (double)(0);
rhi = (double)(0);
problemtype = 0;
fitspherex(&xy, npoints, nx, problemtype, 0.0, 0, 0.0, &cx, &rlo, &rhi, _state);
ae_set_error_flag(err, ae_fp_neq(rlo,rhi), __FILE__, __LINE__, "testfitsphereunit.ap:109");
vv = 0.0;
for(i=0; i<=npoints-1; i++)
{
v = (double)(0);
for(j=0; j<=nx-1; j++)
{
v = v+ae_sqr(cx.ptr.p_double[j]-xy.ptr.pp_double[i][j], _state);
}
vv = vv+ae_sqrt(v, _state)/npoints;
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(vv-rlo, _state),xtol), __FILE__, __LINE__, "testfitsphereunit.ap:118");
testfitsphereunit_calclserror(&xy, npoints, nx, &cx, &v0, _state);
/*
* Check that small perturbations to center position increase target function
*
* NOTE: in fact, we do allow small increase in target function - but no more
* than FTol=1E-6*XTol. It helps to avoid spurious error reports in
* degenerate cases.
*/
ftol = 1.0E-6*xtol;
ae_vector_set_length(&cy, nx, _state);
for(j=0; j<=nx-1; j++)
{
for(k=0; k<=nx-1; k++)
{
cy.ptr.p_double[k] = cx.ptr.p_double[k];
}
cy.ptr.p_double[j] = cx.ptr.p_double[j]+xtol;
testfitsphereunit_calclserror(&xy, npoints, nx, &cy, &v1, _state);
ae_set_error_flag(err, ae_fp_less(v1,v0-ftol), __FILE__, __LINE__, "testfitsphereunit.ap:137");
for(k=0; k<=nx-1; k++)
{
cy.ptr.p_double[k] = cx.ptr.p_double[k];
}
cy.ptr.p_double[j] = cx.ptr.p_double[j]-xtol;
testfitsphereunit_calclserror(&xy, npoints, nx, &cy, &v1, _state);
ae_set_error_flag(err, ae_fp_less(v1,v0-ftol), __FILE__, __LINE__, "testfitsphereunit.ap:144");
}
/*
* Compare against results returned by specific solver
*/
fitspherels(&xy, npoints, nx, &cy, &v, _state);
ae_set_error_flag(err, ae_fp_neq(v,rlo), __FILE__, __LINE__, "testfitsphereunit.ap:151");
for(j=0; j<=nx-1; j++)
{
ae_set_error_flag(err, ae_fp_neq(cy.ptr.p_double[j],cx.ptr.p_double[j]), __FILE__, __LINE__, "testfitsphereunit.ap:153");
}
}
ae_frame_leave(_state);
}
/*************************************************************************
This function tests sphere fitting using generic synthetic datasets and
non-smooth target functions (MC, MI, MZ fitting)
On failure sets Err to True (leaves it unchanged otherwise)
*************************************************************************/
static void testfitsphereunit_testspherefittingns(ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
hqrndstate rs;
ae_matrix xy;
ae_int_t npoints;
ae_int_t nx;
ae_vector cx;
ae_vector cy;
double rlo;
double rhi;
double rlo2;
double rhi2;
double xtol;
double ftol;
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
double vv;
ae_int_t problemtype;
double vlo;
double vhi;
ae_frame_make(_state, &_frame_block);
memset(&rs, 0, sizeof(rs));
memset(&xy, 0, sizeof(xy));
memset(&cx, 0, sizeof(cx));
memset(&cy, 0, sizeof(cy));
_hqrndstate_init(&rs, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&cx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&cy, 0, DT_REAL, _state, ae_true);
hqrndrandomize(&rs, _state);
xtol = 1.0E-5;
/*
* Generate random problem
*/
for(nx=1; nx<=4; nx++)
{
/*
* Generate synthetic dataset
*/
npoints = 50+ae_round(ae_pow((double)(4), (double)(nx), _state), _state);
ae_matrix_set_length(&xy, npoints, nx, _state);
for(i=0; i<=npoints-1; i++)
{
v = (double)(0);
for(j=0; j<=nx-1; j++)
{
vv = hqrndnormal(&rs, _state);
v = v+ae_sqr(vv, _state);
xy.ptr.pp_double[i][j] = vv;
}
ae_assert(ae_fp_greater(v,(double)(0)), "Assertion failed", _state);
v = (1+0.1*hqrnduniformr(&rs, _state))/ae_sqrt(v, _state);
for(j=0; j<=nx-1; j++)
{
xy.ptr.pp_double[i][j] = xy.ptr.pp_double[i][j]*v;
}
}
/*
* Perform various kinds of fit, NLC solver is used
*/
for(problemtype=1; problemtype<=3; problemtype++)
{
/*
* Solve with generic solver
*/
unsetrealarray(&cx, _state);
rlo = (double)(0);
rhi = (double)(0);
fitspherex(&xy, npoints, nx, problemtype, 0.0, 0, 0.0, &cx, &rlo, &rhi, _state);
/*
* Check that small perturbations to center position increase target function
*
* NOTE: in fact, we do allow small increase in target function - but no more
* than FTol=1E-6*XTol. It helps to avoid spurious error reports in
* degenerate cases.
*/
ftol = 1.0E-6*xtol;
ae_vector_set_length(&cy, nx, _state);
if( problemtype==2||problemtype==3 )
{
vlo = (double)(1);
}
else
{
vlo = (double)(0);
}
if( problemtype==1||problemtype==3 )
{
vhi = (double)(1);
}
else
{
vhi = (double)(0);
}
for(j=0; j<=nx-1; j++)
{
for(k=0; k<=nx-1; k++)
{
cy.ptr.p_double[k] = cx.ptr.p_double[k];
}
cy.ptr.p_double[j] = cx.ptr.p_double[j]+xtol;
testfitsphereunit_calcradii(&xy, npoints, nx, &cy, &rlo2, &rhi2, _state);
ae_set_error_flag(err, ae_fp_less(rhi2*vhi-rlo2*vlo,rhi*vhi-rlo*vlo-ftol), __FILE__, __LINE__, "testfitsphereunit.ap:245");
for(k=0; k<=nx-1; k++)
{
cy.ptr.p_double[k] = cx.ptr.p_double[k];
}
cy.ptr.p_double[j] = cx.ptr.p_double[j]-xtol;
testfitsphereunit_calcradii(&xy, npoints, nx, &cy, &rlo2, &rhi2, _state);
ae_set_error_flag(err, ae_fp_less(rhi2*vhi-rlo2*vlo,rhi*vhi-rlo*vlo-ftol), __FILE__, __LINE__, "testfitsphereunit.ap:252");
}
/*
* Compare against results returned by specific solver
*/
if( problemtype==1 )
{
fitspheremc(&xy, npoints, nx, &cy, &rhi2, _state);
ae_set_error_flag(err, ae_fp_neq(rhi2,rhi), __FILE__, __LINE__, "testfitsphereunit.ap:261");
for(j=0; j<=nx-1; j++)
{
ae_set_error_flag(err, ae_fp_neq(cy.ptr.p_double[j],cx.ptr.p_double[j]), __FILE__, __LINE__, "testfitsphereunit.ap:263");
}
}
if( problemtype==2 )
{
fitspheremi(&xy, npoints, nx, &cy, &rlo2, _state);
ae_set_error_flag(err, ae_fp_neq(rlo2,rlo), __FILE__, __LINE__, "testfitsphereunit.ap:268");
for(j=0; j<=nx-1; j++)
{
ae_set_error_flag(err, ae_fp_neq(cy.ptr.p_double[j],cx.ptr.p_double[j]), __FILE__, __LINE__, "testfitsphereunit.ap:270");
}
}
if( problemtype==3 )
{
fitspheremz(&xy, npoints, nx, &cy, &rlo2, &rhi2, _state);
ae_set_error_flag(err, ae_fp_neq(rlo2,rlo), __FILE__, __LINE__, "testfitsphereunit.ap:275");
ae_set_error_flag(err, ae_fp_neq(rhi2,rhi), __FILE__, __LINE__, "testfitsphereunit.ap:276");
for(j=0; j<=nx-1; j++)
{
ae_set_error_flag(err, ae_fp_neq(cy.ptr.p_double[j],cx.ptr.p_double[j]), __FILE__, __LINE__, "testfitsphereunit.ap:278");
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
This function tests sphere fitting
On failure sets Err to True (leaves it unchanged otherwise)
*************************************************************************/
static void testfitsphereunit_testspherefittingvosswinkel2(ae_bool* err,
ae_state *_state)
{
ae_frame _frame_block;
hqrndstate rs;
ae_matrix xy;
ae_int_t cnt;
ae_vector cx;
double rlo;
double rhi;
double tol;
ae_frame_make(_state, &_frame_block);
memset(&rs, 0, sizeof(rs));
memset(&xy, 0, sizeof(xy));
memset(&cx, 0, sizeof(cx));
_hqrndstate_init(&rs, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&cx, 0, DT_REAL, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Test problem #2 by Vosswinkel GmbH
*/
ae_matrix_set_length(&xy, 40, 2, _state);
cnt = 0;
testfitsphereunit_addvalue(&xy, &cnt, 0.1026, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.000036, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.101119, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.016144, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.096754, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.031654, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.088981, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.045634, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.082056, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.06008, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.074966, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.075647, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.065, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.090471, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.052411, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.104381, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.036436, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.114859, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.019034, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.126577, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.001191, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.139295, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.024689, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.147143, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.049729, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.147861, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.076402, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.145907, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.103928, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.139553, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.133726, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.130429, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.159051, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.112298, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.179496, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.08821, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.194562, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.059989, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.204838, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.029135, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.206971, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.00349, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.206207, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.036427, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.197079, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.06806, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.180492, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.096353, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.158203, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.119891, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.132669, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.138375, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.105652, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.152229, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.078587, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.16316, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.049984, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.167084, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.022067, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.165233, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.004002, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.16075, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.028058, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.151829, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.050088, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.141178, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.067646, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.124169, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.081421, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.10567, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.087305, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.082618, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.094189, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.064399, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.099445, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.047018, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.09936, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.028981, _state);
testfitsphereunit_addvalue(&xy, &cnt, 0.101784, _state);
testfitsphereunit_addvalue(&xy, &cnt, -0.012918, _state);
tol = 1.0E-7;
/*
* MZ problem, NLC solver
*/
unsetrealarray(&cx, _state);
rlo = (double)(0);
rhi = (double)(0);
fitspheremz(&xy, xy.rows, xy.cols, &cx, &rlo, &rhi, _state);
ae_set_error_flag(err, cx.cnt!=2, __FILE__, __LINE__, "testfitsphereunit.ap:395");
if( *err )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[0]+0.050884688, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:398");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[1]+0.011472328, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:399");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rlo-0.150973382, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:400");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rhi-0.164374709, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:401");
unsetrealarray(&cx, _state);
rlo = (double)(0);
rhi = (double)(0);
fitspherex(&xy, xy.rows, xy.cols, 3, 0.0, 0, 0.0, &cx, &rlo, &rhi, _state);
ae_set_error_flag(err, cx.cnt!=2, __FILE__, __LINE__, "testfitsphereunit.ap:406");
if( *err )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[0]+0.050884688, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:409");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[1]+0.011472328, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:410");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rlo-0.150973382, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:411");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rhi-0.164374709, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:412");
/*
* MC problem, NLC solver
*/
unsetrealarray(&cx, _state);
rlo = (double)(0);
rhi = (double)(0);
fitspheremc(&xy, xy.rows, xy.cols, &cx, &rhi, _state);
ae_set_error_flag(err, cx.cnt!=2, __FILE__, __LINE__, "testfitsphereunit.ap:421");
if( *err )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[0]+0.051137580, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:424");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[1]+0.011680985, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:425");
ae_set_error_flag(err, ae_fp_neq(rlo,(double)(0)), __FILE__, __LINE__, "testfitsphereunit.ap:426");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rhi-0.164365735, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:427");
unsetrealarray(&cx, _state);
rlo = (double)(0);
rhi = (double)(0);
fitspherex(&xy, xy.rows, xy.cols, 1, 0.0, 0, 0.0, &cx, &rlo, &rhi, _state);
ae_set_error_flag(err, cx.cnt!=2, __FILE__, __LINE__, "testfitsphereunit.ap:432");
if( *err )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[0]+0.051137580, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:435");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[1]+0.011680985, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:436");
ae_set_error_flag(err, ae_fp_neq(rlo,(double)(0)), __FILE__, __LINE__, "testfitsphereunit.ap:437");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rhi-0.164365735, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:438");
/*
* MI problem, NLC solver
*/
unsetrealarray(&cx, _state);
rlo = (double)(0);
rhi = (double)(0);
fitspheremi(&xy, xy.rows, xy.cols, &cx, &rlo, _state);
ae_set_error_flag(err, cx.cnt!=2, __FILE__, __LINE__, "testfitsphereunit.ap:447");
if( *err )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[0]+0.054593489, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:450");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[1]+0.007459466, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:451");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rlo-0.152429205, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:452");
ae_set_error_flag(err, ae_fp_neq(rhi,(double)(0)), __FILE__, __LINE__, "testfitsphereunit.ap:453");
unsetrealarray(&cx, _state);
rlo = (double)(0);
rhi = (double)(0);
fitspherex(&xy, xy.rows, xy.cols, 2, 0.0, 0, 0.0, &cx, &rlo, &rhi, _state);
ae_set_error_flag(err, cx.cnt!=2, __FILE__, __LINE__, "testfitsphereunit.ap:458");
if( *err )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[0]+0.054593489, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:461");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(cx.ptr.p_double[1]+0.007459466, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:462");
ae_set_error_flag(err, ae_fp_greater(ae_fabs(rlo-0.152429205, _state),tol), __FILE__, __LINE__, "testfitsphereunit.ap:463");
ae_set_error_flag(err, ae_fp_neq(rhi,(double)(0)), __FILE__, __LINE__, "testfitsphereunit.ap:464");
ae_frame_leave(_state);
}
/*************************************************************************
Used to calculate RLo/Rhi given XY and center position
*************************************************************************/
static void testfitsphereunit_calcradii(/* Real */ ae_matrix* xy,
ae_int_t npoints,
ae_int_t nx,
/* Real */ ae_vector* cx,
double* rlo,
double* rhi,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
double v;
*rlo = 0;
*rhi = 0;
*rlo = ae_maxrealnumber;
*rhi = (double)(0);
for(i=0; i<=npoints-1; i++)
{
v = (double)(0);
for(j=0; j<=nx-1; j++)
{
v = v+ae_sqr(xy->ptr.pp_double[i][j]-cx->ptr.p_double[j], _state);
}
v = ae_sqrt(v, _state);
*rhi = ae_maxreal(*rhi, v, _state);
*rlo = ae_minreal(*rlo, v, _state);
}
}
/*************************************************************************
Used to calculate least squares error given XY and center position
*************************************************************************/
static void testfitsphereunit_calclserror(/* Real */ ae_matrix* xy,
ae_int_t npoints,
ae_int_t nx,
/* Real */ ae_vector* cx,
double* err,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
double v;
double rad;
*err = 0;
rad = 0.0;
for(i=0; i<=npoints-1; i++)
{
v = (double)(0);
for(j=0; j<=nx-1; j++)
{
v = v+ae_sqr(cx->ptr.p_double[j]-xy->ptr.pp_double[i][j], _state);
}
rad = rad+ae_sqrt(v, _state)/npoints;
}
*err = 0.0;
for(i=0; i<=npoints-1; i++)
{
v = (double)(0);
for(j=0; j<=nx-1; j++)
{
v = v+ae_sqr(cx->ptr.p_double[j]-xy->ptr.pp_double[i][j], _state);
}
*err = *err+ae_sqr(rad-ae_sqrt(v, _state), _state);
}
}
/*************************************************************************
Used to initialize dynamic array with constant values
*************************************************************************/
static void testfitsphereunit_addvalue(/* Real */ ae_matrix* xy,
ae_int_t* cnt,
double v,
ae_state *_state)
{
xy->ptr.pp_double[*cnt/xy->cols][*cnt%xy->cols] = v;
*cnt = *cnt+1;
}
static void testspline1dunit_lconst(double a,
double b,
spline1dinterpolant* c,
double lstep,
double* l0,
double* l1,
double* l2,
ae_state *_state);
static ae_bool testspline1dunit_enumerateallsplines(/* Real */ ae_vector* x,
/* Real */ ae_vector* y,
ae_int_t n,
ae_int_t* splineindex,
spline1dinterpolant* s,
ae_state *_state);
static ae_bool testspline1dunit_testunpack(spline1dinterpolant* c,
/* Real */ ae_vector* x,
ae_state *_state);
static void testspline1dunit_unsetspline1d(spline1dinterpolant* c,
ae_state *_state);
static void testspline1dunit_unsetreport(spline1dfitreport* rep,
ae_state *_state);
static ae_bool testspline1dunit_testmonotonespline(ae_state *_state);
static void testspline1dunit_testsplinefitting(ae_bool* fiterrors,
ae_state *_state);
ae_bool testspline1d(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_bool waserrors;
ae_bool crserrors;
ae_bool cserrors;
ae_bool hserrors;
ae_bool aserrors;
ae_bool lserrors;
ae_bool dserrors;
ae_bool uperrors;
ae_bool cperrors;
ae_bool lterrors;
ae_bool ierrors;
ae_bool monotoneerr;
ae_bool fiterr;
double threshold;
ae_int_t passcount;
double lstep;
double h;
ae_int_t maxn;
ae_int_t bltype;
ae_int_t brtype;
ae_bool periodiccond;
ae_int_t n;
ae_int_t i;
ae_int_t k;
ae_int_t pass;
ae_vector x;
ae_vector y;
ae_vector yp;
ae_vector w;
ae_vector w2;
ae_vector y2;
ae_vector d;
ae_vector xc;
ae_vector yc;
ae_vector xtest;
ae_int_t n2;
ae_vector tmp0;
ae_vector tmp1;
ae_vector tmp2;
ae_vector tmpx;
ae_vector dc;
spline1dinterpolant c;
spline1dinterpolant c2;
double a;
double b;
double bl;
double br;
double t;
double sa;
double sb;
double v;
double l10;
double l11;
double l12;
double l20;
double l21;
double l22;
double p0;
double p1;
double p2;
double s;
double ds;
double d2s;
double s2;
double ds2;
double d2s2;
double vl;
double vm;
double vr;
double err;
double tension;
double intab;
ae_int_t splineindex;
double lipschitzeps;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&yp, 0, sizeof(yp));
memset(&w, 0, sizeof(w));
memset(&w2, 0, sizeof(w2));
memset(&y2, 0, sizeof(y2));
memset(&d, 0, sizeof(d));
memset(&xc, 0, sizeof(xc));
memset(&yc, 0, sizeof(yc));
memset(&xtest, 0, sizeof(xtest));
memset(&tmp0, 0, sizeof(tmp0));
memset(&tmp1, 0, sizeof(tmp1));
memset(&tmp2, 0, sizeof(tmp2));
memset(&tmpx, 0, sizeof(tmpx));
memset(&dc, 0, sizeof(dc));
memset(&c, 0, sizeof(c));
memset(&c2, 0, sizeof(c2));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&yp, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&yc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xtest, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmpx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&dc, 0, DT_INT, _state, ae_true);
_spline1dinterpolant_init(&c, _state, ae_true);
_spline1dinterpolant_init(&c2, _state, ae_true);
waserrors = ae_false;
passcount = 20;
lstep = 0.005;
h = 0.00001;
maxn = 10;
lipschitzeps = 1.0E-6;
threshold = 10000*ae_machineepsilon;
lserrors = ae_false;
cserrors = ae_false;
crserrors = ae_false;
hserrors = ae_false;
aserrors = ae_false;
dserrors = ae_false;
cperrors = ae_false;
uperrors = ae_false;
lterrors = ae_false;
ierrors = ae_false;
fiterr = ae_false;
/*
* General test: linear, cubic, Hermite, Akima
*/
for(n=2; n<=maxn; n++)
{
ae_vector_set_length(&x, n-1+1, _state);
ae_vector_set_length(&y, n-1+1, _state);
ae_vector_set_length(&yp, n-1+1, _state);
ae_vector_set_length(&d, n-1+1, _state);
for(pass=1; pass<=passcount; pass++)
{
/*
* Prepare task:
* * X contains abscissas from [A,B]
* * Y contains function values
* * YP contains periodic function values
*/
a = -1-ae_randomreal(_state);
b = 1+ae_randomreal(_state);
bl = 2*ae_randomreal(_state)-1;
br = 2*ae_randomreal(_state)-1;
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 0.5*(b+a)+0.5*(b-a)*ae_cos(ae_pi*(2*i+1)/(2*n), _state);
if( i==0 )
{
x.ptr.p_double[i] = a;
}
if( i==n-1 )
{
x.ptr.p_double[i] = b;
}
y.ptr.p_double[i] = ae_cos(1.3*ae_pi*x.ptr.p_double[i]+0.4, _state);
yp.ptr.p_double[i] = y.ptr.p_double[i];
d.ptr.p_double[i] = -1.3*ae_pi*ae_sin(1.3*ae_pi*x.ptr.p_double[i]+0.4, _state);
}
yp.ptr.p_double[n-1] = yp.ptr.p_double[0];
for(i=0; i<=n-1; i++)
{
k = ae_randominteger(n, _state);
if( k!=i )
{
t = x.ptr.p_double[i];
x.ptr.p_double[i] = x.ptr.p_double[k];
x.ptr.p_double[k] = t;
t = y.ptr.p_double[i];
y.ptr.p_double[i] = y.ptr.p_double[k];
y.ptr.p_double[k] = t;
t = yp.ptr.p_double[i];
yp.ptr.p_double[i] = yp.ptr.p_double[k];
yp.ptr.p_double[k] = t;
t = d.ptr.p_double[i];
d.ptr.p_double[i] = d.ptr.p_double[k];
d.ptr.p_double[k] = t;
}
}
/*
* Build linear spline
* Test for general interpolation scheme properties:
* * values at nodes
* * continuous function
* Test for specific properties is implemented below.
*/
spline1dbuildlinear(&x, &y, n, &c, _state);
err = (double)(0);
for(i=0; i<=n-1; i++)
{
err = ae_maxreal(err, ae_fabs(y.ptr.p_double[i]-spline1dcalc(&c, x.ptr.p_double[i], _state), _state), _state);
}
lserrors = lserrors||ae_fp_greater(err,threshold);
testspline1dunit_lconst(a, b, &c, lstep, &l10, &l11, &l12, _state);
testspline1dunit_lconst(a, b, &c, lstep/3, &l20, &l21, &l22, _state);
lserrors = lserrors||ae_fp_greater(l20/l10,1.2);
/*
* Build cubic spline.
* Test for interpolation scheme properties:
* * values at nodes
* * boundary conditions
* * continuous function
* * continuous first derivative
* * continuous second derivative
* * periodicity properties
* * Spline1DGridDiff(), Spline1DGridDiff2() and Spline1DDiff()
* calls must return same results
*/
for(bltype=-1; bltype<=2; bltype++)
{
for(brtype=-1; brtype<=2; brtype++)
{
/*
* skip meaningless combination of boundary conditions
* (one condition is periodic, another is not)
*/
periodiccond = bltype==-1||brtype==-1;
if( periodiccond&&bltype!=brtype )
{
continue;
}
/*
* build
*/
if( periodiccond )
{
spline1dbuildcubic(&x, &yp, n, bltype, bl, brtype, br, &c, _state);
}
else
{
spline1dbuildcubic(&x, &y, n, bltype, bl, brtype, br, &c, _state);
}
/*
* interpolation properties
*/
err = (double)(0);
if( periodiccond )
{
/*
* * check values at nodes; spline is periodic so
* we add random number of periods to nodes
* * we also test for periodicity of derivatives
*/
for(i=0; i<=n-1; i++)
{
v = x.ptr.p_double[i];
vm = v+(b-a)*(ae_randominteger(5, _state)-2);
t = yp.ptr.p_double[i]-spline1dcalc(&c, vm, _state);
err = ae_maxreal(err, ae_fabs(t, _state), _state);
spline1ddiff(&c, v, &s, &ds, &d2s, _state);
spline1ddiff(&c, vm, &s2, &ds2, &d2s2, _state);
err = ae_maxreal(err, ae_fabs(s-s2, _state), _state);
err = ae_maxreal(err, ae_fabs(ds-ds2, _state), _state);
err = ae_maxreal(err, ae_fabs(d2s-d2s2, _state), _state);
}
/*
* periodicity between nodes
*/
v = a+(b-a)*ae_randomreal(_state);
vm = v+(b-a)*(ae_randominteger(5, _state)-2);
err = ae_maxreal(err, ae_fabs(spline1dcalc(&c, v, _state)-spline1dcalc(&c, vm, _state), _state), _state);
spline1ddiff(&c, v, &s, &ds, &d2s, _state);
spline1ddiff(&c, vm, &s2, &ds2, &d2s2, _state);
err = ae_maxreal(err, ae_fabs(s-s2, _state), _state);
err = ae_maxreal(err, ae_fabs(ds-ds2, _state), _state);
err = ae_maxreal(err, ae_fabs(d2s-d2s2, _state), _state);
}
else
{
/*
* * check values at nodes
*/
for(i=0; i<=n-1; i++)
{
err = ae_maxreal(err, ae_fabs(y.ptr.p_double[i]-spline1dcalc(&c, x.ptr.p_double[i], _state), _state), _state);
}
}
ae_set_error_flag(&cserrors, ae_fp_greater(err,threshold), __FILE__, __LINE__, "testspline1dunit.ap:221");
/*
* check boundary conditions
*/
err = (double)(0);
if( bltype==0 )
{
spline1ddiff(&c, a-h, &s, &ds, &d2s, _state);
spline1ddiff(&c, a+h, &s2, &ds2, &d2s2, _state);
t = (d2s2-d2s)/(2*h);
err = ae_maxreal(err, ae_fabs(t, _state), _state);
}
if( bltype==1 )
{
t = (spline1dcalc(&c, a+h, _state)-spline1dcalc(&c, a-h, _state))/(2*h);
err = ae_maxreal(err, ae_fabs(bl-t, _state), _state);
}
if( bltype==2 )
{
t = (spline1dcalc(&c, a+h, _state)-2*spline1dcalc(&c, a, _state)+spline1dcalc(&c, a-h, _state))/ae_sqr(h, _state);
err = ae_maxreal(err, ae_fabs(bl-t, _state), _state);
}
if( brtype==0 )
{
spline1ddiff(&c, b-h, &s, &ds, &d2s, _state);
spline1ddiff(&c, b+h, &s2, &ds2, &d2s2, _state);
t = (d2s2-d2s)/(2*h);
err = ae_maxreal(err, ae_fabs(t, _state), _state);
}
if( brtype==1 )
{
t = (spline1dcalc(&c, b+h, _state)-spline1dcalc(&c, b-h, _state))/(2*h);
err = ae_maxreal(err, ae_fabs(br-t, _state), _state);
}
if( brtype==2 )
{
t = (spline1dcalc(&c, b+h, _state)-2*spline1dcalc(&c, b, _state)+spline1dcalc(&c, b-h, _state))/ae_sqr(h, _state);
err = ae_maxreal(err, ae_fabs(br-t, _state), _state);
}
if( bltype==-1||brtype==-1 )
{
spline1ddiff(&c, a+100*ae_machineepsilon, &s, &ds, &d2s, _state);
spline1ddiff(&c, b-100*ae_machineepsilon, &s2, &ds2, &d2s2, _state);
err = ae_maxreal(err, ae_fabs(s-s2, _state), _state);
err = ae_maxreal(err, ae_fabs(ds-ds2, _state), _state);
err = ae_maxreal(err, ae_fabs(d2s-d2s2, _state), _state);
}
ae_set_error_flag(&cserrors, ae_fp_greater(err,1.0E-3), __FILE__, __LINE__, "testspline1dunit.ap:269");
/*
* Check Lipschitz continuity
*/
testspline1dunit_lconst(a, b, &c, lstep, &l10, &l11, &l12, _state);
testspline1dunit_lconst(a, b, &c, lstep/3, &l20, &l21, &l22, _state);
if( ae_fp_greater(l10,lipschitzeps) )
{
ae_set_error_flag(&cserrors, ae_fp_greater(l20/(l10+lipschitzeps),1.2), __FILE__, __LINE__, "testspline1dunit.ap:277");
}
if( ae_fp_greater(l11,lipschitzeps) )
{
ae_set_error_flag(&cserrors, ae_fp_greater(l21/(l11+lipschitzeps),1.2), __FILE__, __LINE__, "testspline1dunit.ap:279");
}
if( ae_fp_greater(l12,lipschitzeps) )
{
ae_set_error_flag(&cserrors, ae_fp_greater(l22/(l12+lipschitzeps),1.2), __FILE__, __LINE__, "testspline1dunit.ap:281");
}
/*
* compare spline1dgriddiff() and spline1ddiff() results
*/
err = (double)(0);
if( periodiccond )
{
spline1dgriddiffcubic(&x, &yp, n, bltype, bl, brtype, br, &tmp1, _state);
}
else
{
spline1dgriddiffcubic(&x, &y, n, bltype, bl, brtype, br, &tmp1, _state);
}
ae_assert(tmp1.cnt>=n, "Assertion failed", _state);
for(i=0; i<=n-1; i++)
{
spline1ddiff(&c, x.ptr.p_double[i], &s, &ds, &d2s, _state);
err = ae_maxreal(err, ae_fabs(ds-tmp1.ptr.p_double[i], _state), _state);
}
if( periodiccond )
{
spline1dgriddiff2cubic(&x, &yp, n, bltype, bl, brtype, br, &tmp1, &tmp2, _state);
}
else
{
spline1dgriddiff2cubic(&x, &y, n, bltype, bl, brtype, br, &tmp1, &tmp2, _state);
}
for(i=0; i<=n-1; i++)
{
spline1ddiff(&c, x.ptr.p_double[i], &s, &ds, &d2s, _state);
err = ae_maxreal(err, ae_fabs(ds-tmp1.ptr.p_double[i], _state), _state);
err = ae_maxreal(err, ae_fabs(d2s-tmp2.ptr.p_double[i], _state), _state);
}
ae_set_error_flag(&cserrors, ae_fp_greater(err,threshold), __FILE__, __LINE__, "testspline1dunit.ap:307");
/*
* compare spline1dconv()/convdiff()/convdiff2() and spline1ddiff() results
*/
n2 = 2+ae_randominteger(2*n, _state);
ae_vector_set_length(&tmpx, n2, _state);
for(i=0; i<=n2-1; i++)
{
tmpx.ptr.p_double[i] = 0.5*(a+b)+(a-b)*(2*ae_randomreal(_state)-1);
}
err = (double)(0);
if( periodiccond )
{
spline1dconvcubic(&x, &yp, n, bltype, bl, brtype, br, &tmpx, n2, &tmp0, _state);
}
else
{
spline1dconvcubic(&x, &y, n, bltype, bl, brtype, br, &tmpx, n2, &tmp0, _state);
}
for(i=0; i<=n2-1; i++)
{
spline1ddiff(&c, tmpx.ptr.p_double[i], &s, &ds, &d2s, _state);
err = ae_maxreal(err, ae_fabs(s-tmp0.ptr.p_double[i], _state), _state);
}
if( periodiccond )
{
spline1dconvdiffcubic(&x, &yp, n, bltype, bl, brtype, br, &tmpx, n2, &tmp0, &tmp1, _state);
}
else
{
spline1dconvdiffcubic(&x, &y, n, bltype, bl, brtype, br, &tmpx, n2, &tmp0, &tmp1, _state);
}
for(i=0; i<=n2-1; i++)
{
spline1ddiff(&c, tmpx.ptr.p_double[i], &s, &ds, &d2s, _state);
err = ae_maxreal(err, ae_fabs(s-tmp0.ptr.p_double[i], _state), _state);
err = ae_maxreal(err, ae_fabs(ds-tmp1.ptr.p_double[i], _state), _state);
}
if( periodiccond )
{
spline1dconvdiff2cubic(&x, &yp, n, bltype, bl, brtype, br, &tmpx, n2, &tmp0, &tmp1, &tmp2, _state);
}
else
{
spline1dconvdiff2cubic(&x, &y, n, bltype, bl, brtype, br, &tmpx, n2, &tmp0, &tmp1, &tmp2, _state);
}
for(i=0; i<=n2-1; i++)
{
spline1ddiff(&c, tmpx.ptr.p_double[i], &s, &ds, &d2s, _state);
err = ae_maxreal(err, ae_fabs(s-tmp0.ptr.p_double[i], _state), _state);
err = ae_maxreal(err, ae_fabs(ds-tmp1.ptr.p_double[i], _state), _state);
err = ae_maxreal(err, ae_fabs(d2s-tmp2.ptr.p_double[i], _state), _state);
}
ae_set_error_flag(&cserrors, ae_fp_greater(err,threshold), __FILE__, __LINE__, "testspline1dunit.ap:351");
}
}
/*
* Build Catmull-Rom spline.
* Test for interpolation scheme properties:
* * values at nodes
* * boundary conditions
* * continuous function
* * continuous first derivative
* * periodicity properties
*/
for(bltype=-1; bltype<=0; bltype++)
{
periodiccond = bltype==-1;
/*
* select random tension value, then build
*/
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
tension = (double)(0);
}
else
{
tension = (double)(1);
}
}
else
{
tension = ae_randomreal(_state);
}
if( periodiccond )
{
spline1dbuildcatmullrom(&x, &yp, n, bltype, tension, &c, _state);
}
else
{
spline1dbuildcatmullrom(&x, &y, n, bltype, tension, &c, _state);
}
/*
* interpolation properties
*/
err = (double)(0);
if( periodiccond )
{
/*
* * check values at nodes; spline is periodic so
* we add random number of periods to nodes
* * we also test for periodicity of first derivative
*/
for(i=0; i<=n-1; i++)
{
v = x.ptr.p_double[i];
vm = v+(b-a)*(ae_randominteger(5, _state)-2);
t = yp.ptr.p_double[i]-spline1dcalc(&c, vm, _state);
err = ae_maxreal(err, ae_fabs(t, _state), _state);
spline1ddiff(&c, v, &s, &ds, &d2s, _state);
spline1ddiff(&c, vm, &s2, &ds2, &d2s2, _state);
err = ae_maxreal(err, ae_fabs(s-s2, _state), _state);
err = ae_maxreal(err, ae_fabs(ds-ds2, _state), _state);
}
/*
* periodicity between nodes
*/
v = a+(b-a)*ae_randomreal(_state);
vm = v+(b-a)*(ae_randominteger(5, _state)-2);
err = ae_maxreal(err, ae_fabs(spline1dcalc(&c, v, _state)-spline1dcalc(&c, vm, _state), _state), _state);
spline1ddiff(&c, v, &s, &ds, &d2s, _state);
spline1ddiff(&c, vm, &s2, &ds2, &d2s2, _state);
err = ae_maxreal(err, ae_fabs(s-s2, _state), _state);
err = ae_maxreal(err, ae_fabs(ds-ds2, _state), _state);
}
else
{
/*
* * check values at nodes
*/
for(i=0; i<=n-1; i++)
{
err = ae_maxreal(err, ae_fabs(y.ptr.p_double[i]-spline1dcalc(&c, x.ptr.p_double[i], _state), _state), _state);
}
}
crserrors = crserrors||ae_fp_greater(err,threshold);
/*
* check boundary conditions
*/
err = (double)(0);
if( bltype==0 )
{
spline1ddiff(&c, a-h, &s, &ds, &d2s, _state);
spline1ddiff(&c, a+h, &s2, &ds2, &d2s2, _state);
t = (d2s2-d2s)/(2*h);
err = ae_maxreal(err, ae_fabs(t, _state), _state);
spline1ddiff(&c, b-h, &s, &ds, &d2s, _state);
spline1ddiff(&c, b+h, &s2, &ds2, &d2s2, _state);
t = (d2s2-d2s)/(2*h);
err = ae_maxreal(err, ae_fabs(t, _state), _state);
}
if( bltype==-1 )
{
spline1ddiff(&c, a+100*ae_machineepsilon, &s, &ds, &d2s, _state);
spline1ddiff(&c, b-100*ae_machineepsilon, &s2, &ds2, &d2s2, _state);
err = ae_maxreal(err, ae_fabs(s-s2, _state), _state);
err = ae_maxreal(err, ae_fabs(ds-ds2, _state), _state);
}
crserrors = crserrors||ae_fp_greater(err,1.0E-3);
/*
* Check Lipschitz continuity
*/
testspline1dunit_lconst(a, b, &c, lstep, &l10, &l11, &l12, _state);
testspline1dunit_lconst(a, b, &c, lstep/3, &l20, &l21, &l22, _state);
if( ae_fp_greater(l10,1.0E-6) )
{
crserrors = crserrors||ae_fp_greater(l20/l10,1.2);
}
if( ae_fp_greater(l11,1.0E-6) )
{
crserrors = crserrors||ae_fp_greater(l21/l11,1.2);
}
}
/*
* Build Hermite spline.
* Test for interpolation scheme properties:
* * values and derivatives at nodes
* * continuous function
* * continuous first derivative
*/
spline1dbuildhermite(&x, &y, &d, n, &c, _state);
err = (double)(0);
for(i=0; i<=n-1; i++)
{
err = ae_maxreal(err, ae_fabs(y.ptr.p_double[i]-spline1dcalc(&c, x.ptr.p_double[i], _state), _state), _state);
}
hserrors = hserrors||ae_fp_greater(err,threshold);
err = (double)(0);
for(i=0; i<=n-1; i++)
{
t = (spline1dcalc(&c, x.ptr.p_double[i]+h, _state)-spline1dcalc(&c, x.ptr.p_double[i]-h, _state))/(2*h);
err = ae_maxreal(err, ae_fabs(d.ptr.p_double[i]-t, _state), _state);
}
hserrors = hserrors||ae_fp_greater(err,1.0E-3);
testspline1dunit_lconst(a, b, &c, lstep, &l10, &l11, &l12, _state);
testspline1dunit_lconst(a, b, &c, lstep/3, &l20, &l21, &l22, _state);
hserrors = hserrors||ae_fp_greater(l20/l10,1.2);
hserrors = hserrors||ae_fp_greater(l21/l11,1.2);
/*
* Build Akima spline
* Test for general interpolation scheme properties:
* * values at nodes
* * continuous function
* * continuous first derivative
* Test for Akima-specific properties is implemented below.
*/
spline1dbuildakima(&x, &y, n, &c, _state);
err = (double)(0);
for(i=0; i<=n-1; i++)
{
err = ae_maxreal(err, ae_fabs(y.ptr.p_double[i]-spline1dcalc(&c, x.ptr.p_double[i], _state), _state), _state);
}
aserrors = aserrors||ae_fp_greater(err,threshold);
testspline1dunit_lconst(a, b, &c, lstep, &l10, &l11, &l12, _state);
testspline1dunit_lconst(a, b, &c, lstep/3, &l20, &l21, &l22, _state);
hserrors = hserrors||(ae_fp_greater(l10,1.0E-10)&&ae_fp_greater(l20/l10,1.2));
hserrors = hserrors||(ae_fp_greater(l11,1.0E-10)&&ae_fp_greater(l21/l11,1.2));
}
}
/*
* Special linear spline test:
* test for linearity between x[i] and x[i+1]
*/
for(n=2; n<=maxn; n++)
{
ae_vector_set_length(&x, n-1+1, _state);
ae_vector_set_length(&y, n-1+1, _state);
/*
* Prepare task
*/
a = (double)(-1);
b = (double)(1);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = a+(b-a)*i/(n-1);
y.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
spline1dbuildlinear(&x, &y, n, &c, _state);
/*
* Test
*/
err = (double)(0);
for(k=0; k<=n-2; k++)
{
a = x.ptr.p_double[k];
b = x.ptr.p_double[k+1];
for(pass=1; pass<=passcount; pass++)
{
t = a+(b-a)*ae_randomreal(_state);
v = y.ptr.p_double[k]+(t-a)/(b-a)*(y.ptr.p_double[k+1]-y.ptr.p_double[k]);
err = ae_maxreal(err, ae_fabs(spline1dcalc(&c, t, _state)-v, _state), _state);
}
}
lserrors = lserrors||ae_fp_greater(err,threshold);
}
/*
* Special Akima test: test outlier sensitivity
* Spline value at (x[i], x[i+1]) should depend from
* f[i-2], f[i-1], f[i], f[i+1], f[i+2], f[i+3] only.
*/
for(n=5; n<=maxn; n++)
{
ae_vector_set_length(&x, n-1+1, _state);
ae_vector_set_length(&y, n-1+1, _state);
ae_vector_set_length(&y2, n-1+1, _state);
/*
* Prepare unperturbed Akima spline
*/
a = (double)(-1);
b = (double)(1);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = a+(b-a)*i/(n-1);
y.ptr.p_double[i] = ae_cos(1.3*ae_pi*x.ptr.p_double[i]+0.4, _state);
}
spline1dbuildakima(&x, &y, n, &c, _state);
/*
* Process perturbed tasks
*/
err = (double)(0);
for(k=0; k<=n-1; k++)
{
ae_v_move(&y2.ptr.p_double[0], 1, &y.ptr.p_double[0], 1, ae_v_len(0,n-1));
y2.ptr.p_double[k] = (double)(5);
spline1dbuildakima(&x, &y2, n, &c2, _state);
/*
* Test left part independence
*/
if( k-3>=1 )
{
a = (double)(-1);
b = x.ptr.p_double[k-3];
for(pass=1; pass<=passcount; pass++)
{
t = a+(b-a)*ae_randomreal(_state);
err = ae_maxreal(err, ae_fabs(spline1dcalc(&c, t, _state)-spline1dcalc(&c2, t, _state), _state), _state);
}
}
/*
* Test right part independence
*/
if( k+3<=n-2 )
{
a = x.ptr.p_double[k+3];
b = (double)(1);
for(pass=1; pass<=passcount; pass++)
{
t = a+(b-a)*ae_randomreal(_state);
err = ae_maxreal(err, ae_fabs(spline1dcalc(&c, t, _state)-spline1dcalc(&c2, t, _state), _state), _state);
}
}
}
aserrors = aserrors||ae_fp_greater(err,threshold);
}
/*
* Differentiation, copy/unpack test
*/
for(n=2; n<=maxn; n++)
{
ae_vector_set_length(&x, n-1+1, _state);
ae_vector_set_length(&y, n-1+1, _state);
/*
* Prepare cubic spline
*/
a = -1-ae_randomreal(_state);
b = 1+ae_randomreal(_state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = a+(b-a)*i/(n-1);
y.ptr.p_double[i] = ae_cos(1.3*ae_pi*x.ptr.p_double[i]+0.4, _state);
}
spline1dbuildcubic(&x, &y, n, 2, 0.0, 2, 0.0, &c, _state);
/*
* Test diff
*/
err = (double)(0);
for(pass=1; pass<=passcount; pass++)
{
t = a+(b-a)*ae_randomreal(_state);
spline1ddiff(&c, t, &s, &ds, &d2s, _state);
vl = spline1dcalc(&c, t-h, _state);
vm = spline1dcalc(&c, t, _state);
vr = spline1dcalc(&c, t+h, _state);
err = ae_maxreal(err, ae_fabs(s-vm, _state), _state);
err = ae_maxreal(err, ae_fabs(ds-(vr-vl)/(2*h), _state), _state);
err = ae_maxreal(err, ae_fabs(d2s-(vr-2*vm+vl)/ae_sqr(h, _state), _state), _state);
}
dserrors = dserrors||ae_fp_greater(err,0.001);
/*
* Test copy
*/
testspline1dunit_unsetspline1d(&c2, _state);
spline1dcopy(&c, &c2, _state);
err = (double)(0);
for(pass=1; pass<=passcount; pass++)
{
t = a+(b-a)*ae_randomreal(_state);
err = ae_maxreal(err, ae_fabs(spline1dcalc(&c, t, _state)-spline1dcalc(&c2, t, _state), _state), _state);
}
cperrors = cperrors||ae_fp_greater(err,threshold);
/*
* Test unpack
*/
uperrors = uperrors||!testspline1dunit_testunpack(&c, &x, _state);
}
/*
* Linear translation errors
*/
for(n=2; n<=maxn; n++)
{
/*
* Prepare:
* * X, Y - grid points
* * XTest - test points
*/
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
a = -1-ae_randomreal(_state);
b = 1+ae_randomreal(_state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = a+(b-a)*(i+0.2*ae_randomreal(_state)-0.1)/(n-1);
y.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
ae_vector_set_length(&xtest, 5*n+2, _state);
for(i=0; i<=xtest.cnt-1; i++)
{
xtest.ptr.p_double[i] = a+(b-a)*(i-1)/(xtest.cnt-3);
}
splineindex = 0;
while(testspline1dunit_enumerateallsplines(&x, &y, n, &splineindex, &c, _state))
{
/*
* LinTransX, general A
*/
sa = 4*ae_randomreal(_state)-2;
sb = 2*ae_randomreal(_state)-1;
spline1dcopy(&c, &c2, _state);
spline1dlintransx(&c2, sa, sb, _state);
for(i=0; i<=xtest.cnt-1; i++)
{
lterrors = lterrors||ae_fp_greater(ae_fabs(spline1dcalc(&c, xtest.ptr.p_double[i], _state)-spline1dcalc(&c2, (xtest.ptr.p_double[i]-sb)/sa, _state), _state),threshold);
}
/*
* LinTransX, special case: A=0
*/
sb = 2*ae_randomreal(_state)-1;
spline1dcopy(&c, &c2, _state);
spline1dlintransx(&c2, (double)(0), sb, _state);
for(i=0; i<=xtest.cnt-1; i++)
{
lterrors = lterrors||ae_fp_greater(ae_fabs(spline1dcalc(&c, sb, _state)-spline1dcalc(&c2, xtest.ptr.p_double[i], _state), _state),threshold);
}
/*
* LinTransY
*/
sa = 2*ae_randomreal(_state)-1;
sb = 2*ae_randomreal(_state)-1;
spline1dcopy(&c, &c2, _state);
spline1dlintransy(&c2, sa, sb, _state);
for(i=0; i<=xtest.cnt-1; i++)
{
lterrors = lterrors||ae_fp_greater(ae_fabs(sa*spline1dcalc(&c, xtest.ptr.p_double[i], _state)+sb-spline1dcalc(&c2, xtest.ptr.p_double[i], _state), _state),threshold);
}
}
}
/*
* Testing integration.
* Three tests are performed:
*
* * approximate test (well behaved smooth function, many points,
* integration inside [a,b]), non-periodic spline
*
* * exact test (integration of parabola, outside of [a,b], non-periodic spline
*
* * approximate test for periodic splines. F(x)=cos(2*pi*x)+1.
* Period length is equals to 1.0, so all operations with
* multiples of period are done exactly. For each value of PERIOD
* we calculate and test integral at four points:
* - 0 < t0 < PERIOD
* - t1 = PERIOD-eps
* - t2 = PERIOD
* - t3 = PERIOD+eps
*/
err = (double)(0);
for(n=20; n<=35; n++)
{
ae_vector_set_length(&x, n-1+1, _state);
ae_vector_set_length(&y, n-1+1, _state);
for(pass=1; pass<=passcount; pass++)
{
/*
* Prepare cubic spline
*/
a = -1-0.2*ae_randomreal(_state);
b = 1+0.2*ae_randomreal(_state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = a+(b-a)*i/(n-1);
y.ptr.p_double[i] = ae_sin(ae_pi*x.ptr.p_double[i]+0.4, _state)+ae_exp(x.ptr.p_double[i], _state);
}
bl = ae_pi*ae_cos(ae_pi*a+0.4, _state)+ae_exp(a, _state);
br = ae_pi*ae_cos(ae_pi*b+0.4, _state)+ae_exp(b, _state);
spline1dbuildcubic(&x, &y, n, 1, bl, 1, br, &c, _state);
/*
* Test
*/
t = a+(b-a)*ae_randomreal(_state);
v = -ae_cos(ae_pi*a+0.4, _state)/ae_pi+ae_exp(a, _state);
v = -ae_cos(ae_pi*t+0.4, _state)/ae_pi+ae_exp(t, _state)-v;
v = v-spline1dintegrate(&c, t, _state);
err = ae_maxreal(err, ae_fabs(v, _state), _state);
}
}
ierrors = ierrors||ae_fp_greater(err,0.001);
p0 = 2*ae_randomreal(_state)-1;
p1 = 2*ae_randomreal(_state)-1;
p2 = 2*ae_randomreal(_state)-1;
a = -ae_randomreal(_state)-0.5;
b = ae_randomreal(_state)+0.5;
n = 2;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
ae_vector_set_length(&d, n, _state);
x.ptr.p_double[0] = a;
y.ptr.p_double[0] = p0+p1*a+p2*ae_sqr(a, _state);
d.ptr.p_double[0] = p1+2*p2*a;
x.ptr.p_double[1] = b;
y.ptr.p_double[1] = p0+p1*b+p2*ae_sqr(b, _state);
d.ptr.p_double[1] = p1+2*p2*b;
spline1dbuildhermite(&x, &y, &d, n, &c, _state);
bl = ae_minreal(a, b, _state)-ae_fabs(b-a, _state);
br = ae_minreal(a, b, _state)+ae_fabs(b-a, _state);
err = (double)(0);
for(pass=1; pass<=100; pass++)
{
t = bl+(br-bl)*ae_randomreal(_state);
v = p0*t+p1*ae_sqr(t, _state)/2+p2*ae_sqr(t, _state)*t/3-(p0*a+p1*ae_sqr(a, _state)/2+p2*ae_sqr(a, _state)*a/3);
v = v-spline1dintegrate(&c, t, _state);
err = ae_maxreal(err, ae_fabs(v, _state), _state);
}
ierrors = ierrors||ae_fp_greater(err,threshold);
n = 100;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = (double)i/(double)(n-1);
y.ptr.p_double[i] = ae_cos(2*ae_pi*x.ptr.p_double[i], _state)+1;
}
y.ptr.p_double[0] = (double)(2);
y.ptr.p_double[n-1] = (double)(2);
spline1dbuildcubic(&x, &y, n, -1, 0.0, -1, 0.0, &c, _state);
intab = spline1dintegrate(&c, 1.0, _state);
v = ae_randomreal(_state);
vr = spline1dintegrate(&c, v, _state);
ierrors = ierrors||ae_fp_greater(ae_fabs(intab-1, _state),0.001);
for(i=-10; i<=10; i++)
{
ierrors = ierrors||ae_fp_greater(ae_fabs(spline1dintegrate(&c, i+v, _state)-(i*intab+vr), _state),0.001);
ierrors = ierrors||ae_fp_greater(ae_fabs(spline1dintegrate(&c, i-1000*ae_machineepsilon, _state)-i*intab, _state),0.001);
ierrors = ierrors||ae_fp_greater(ae_fabs(spline1dintegrate(&c, (double)(i), _state)-i*intab, _state),0.001);
ierrors = ierrors||ae_fp_greater(ae_fabs(spline1dintegrate(&c, i+1000*ae_machineepsilon, _state)-i*intab, _state),0.001);
}
/*
* Test monotone cubic Hermit interpolation
*/
monotoneerr = testspline1dunit_testmonotonespline(_state);
/*
* Test fitting errors
*/
testspline1dunit_testsplinefitting(&fiterr, _state);
/*
* report
*/
waserrors = ((((((((((lserrors||cserrors)||crserrors)||hserrors)||aserrors)||dserrors)||cperrors)||uperrors)||lterrors)||ierrors)||monotoneerr)||fiterr;
if( !silent )
{
printf("TESTING SPLINE INTERPOLATION\n");
/*
* Normal tests
*/
printf("INTERPOLATION:\n");
printf("* LINEAR SPLINE ");
if( lserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* CUBIC SPLINE ");
if( cserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* CATMULL-ROM SPLINE ");
if( crserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* HERMITE SPLINE ");
if( hserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* AKIMA SPLINE ");
if( aserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* MONOTONE SPLINE ");
if( monotoneerr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("FITTING: ");
if( fiterr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("DIFFERENTIATION TEST: ");
if( dserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("COPY/SERIALIZATION TEST: ");
if( cperrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("UNPACK TEST: ");
if( uperrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("LIN.TRANS. TEST: ");
if( lterrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("INTEGRATION TEST: ");
if( ierrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
/*
* end
*/
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Lipschitz constants for spline itself, first and second derivatives.
*************************************************************************/
static void testspline1dunit_lconst(double a,
double b,
spline1dinterpolant* c,
double lstep,
double* l0,
double* l1,
double* l2,
ae_state *_state)
{
double t;
double vl;
double vm;
double vr;
double prevf;
double prevd;
double prevd2;
double f;
double d;
double d2;
*l0 = 0;
*l1 = 0;
*l2 = 0;
*l0 = (double)(0);
*l1 = (double)(0);
*l2 = (double)(0);
t = a-0.1;
vl = spline1dcalc(c, t-2*lstep, _state);
vm = spline1dcalc(c, t-lstep, _state);
vr = spline1dcalc(c, t, _state);
f = vm;
d = (vr-vl)/(2*lstep);
d2 = (vr-2*vm+vl)/ae_sqr(lstep, _state);
while(ae_fp_less_eq(t,b+0.1))
{
prevf = f;
prevd = d;
prevd2 = d2;
vl = vm;
vm = vr;
vr = spline1dcalc(c, t+lstep, _state);
f = vm;
d = (vr-vl)/(2*lstep);
d2 = (vr-2*vm+vl)/ae_sqr(lstep, _state);
*l0 = ae_maxreal(*l0, ae_fabs((f-prevf)/lstep, _state), _state);
*l1 = ae_maxreal(*l1, ae_fabs((d-prevd)/lstep, _state), _state);
*l2 = ae_maxreal(*l2, ae_fabs((d2-prevd2)/lstep, _state), _state);
t = t+lstep;
}
}
/*************************************************************************
This function is used to enumerate all spline types which can be built
from given dataset. It should be used as follows:
>
> init X, Y, N
> SplineIndex:=0;
> while EnumerateAllSplines(X, Y, N, SplineIndex, S) do
> begin
> do something with S
> end;
>
On initial call EnumerateAllSplines accepts:
* dataset X, Y, number of points N (N>=2)
* SplineIndex, equal to 0
It returns:
* True, in case there is a spline type which corresponds to SplineIndex.
In this case S contains spline which was built using X/Y and spline type,
as specified by input value of SplineIndex. SplineIndex is advanced to
the next value.
* False, in case SplineIndex contains past-the-end value, spline is not built.
This function tries different variants of linear/cubic, periodic/nonperiodic
splines.
*************************************************************************/
static ae_bool testspline1dunit_enumerateallsplines(/* Real */ ae_vector* x,
/* Real */ ae_vector* y,
ae_int_t n,
ae_int_t* splineindex,
spline1dinterpolant* s,
ae_state *_state)
{
ae_int_t idxoffs;
ae_bool result;
_spline1dinterpolant_clear(s);
ae_assert(*splineindex>=0, "Assertion failed", _state);
result = ae_false;
if( *splineindex==0 )
{
/*
* Linear spline
*/
spline1dbuildlinear(x, y, n, s, _state);
*splineindex = *splineindex+1;
result = ae_true;
return result;
}
else
{
if( *splineindex>=1&&*splineindex<11 )
{
/*
* Cubic spline, either periodic or non-periodic
*/
idxoffs = *splineindex-1;
if( idxoffs==9 )
{
/*
* Periodic spline
*/
spline1dbuildcubic(x, y, n, -1, 0.0, -1, 0.0, s, _state);
}
else
{
/*
* Non-periodic spline
*/
spline1dbuildcubic(x, y, n, idxoffs/3, 2*ae_randomreal(_state)-1, idxoffs%3, 2*ae_randomreal(_state)-1, s, _state);
}
*splineindex = *splineindex+1;
result = ae_true;
return result;
}
}
return result;
}
/*************************************************************************
Unpack testing
*************************************************************************/
static ae_bool testspline1dunit_testunpack(spline1dinterpolant* c,
/* Real */ ae_vector* x,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t n;
double err;
double t;
double v1;
double v2;
ae_int_t pass;
ae_int_t passcount;
ae_matrix tbl;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&tbl, 0, sizeof(tbl));
ae_matrix_init(&tbl, 0, 0, DT_REAL, _state, ae_true);
passcount = 20;
err = (double)(0);
spline1dunpack(c, &n, &tbl, _state);
for(i=0; i<=n-2; i++)
{
for(pass=1; pass<=passcount; pass++)
{
t = ae_randomreal(_state)*(tbl.ptr.pp_double[i][1]-tbl.ptr.pp_double[i][0]);
v1 = tbl.ptr.pp_double[i][2]+t*tbl.ptr.pp_double[i][3]+ae_sqr(t, _state)*tbl.ptr.pp_double[i][4]+t*ae_sqr(t, _state)*tbl.ptr.pp_double[i][5];
v2 = spline1dcalc(c, tbl.ptr.pp_double[i][0]+t, _state);
err = ae_maxreal(err, ae_fabs(v1-v2, _state), _state);
}
}
for(i=0; i<=n-2; i++)
{
err = ae_maxreal(err, ae_fabs(x->ptr.p_double[i]-tbl.ptr.pp_double[i][0], _state), _state);
}
for(i=0; i<=n-2; i++)
{
err = ae_maxreal(err, ae_fabs(x->ptr.p_double[i+1]-tbl.ptr.pp_double[i][1], _state), _state);
}
result = ae_fp_less(err,100*ae_machineepsilon);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Unset spline, i.e. initialize it with random garbage
*************************************************************************/
static void testspline1dunit_unsetspline1d(spline1dinterpolant* c,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector x;
ae_vector y;
ae_vector d;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&d, 0, sizeof(d));
_spline1dinterpolant_clear(c);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_set_length(&x, 2, _state);
ae_vector_set_length(&y, 2, _state);
ae_vector_set_length(&d, 2, _state);
x.ptr.p_double[0] = (double)(-1);
y.ptr.p_double[0] = ae_randomreal(_state);
d.ptr.p_double[0] = ae_randomreal(_state);
x.ptr.p_double[1] = (double)(1);
y.ptr.p_double[1] = ae_randomreal(_state);
d.ptr.p_double[1] = ae_randomreal(_state);
spline1dbuildhermite(&x, &y, &d, 2, c, _state);
ae_frame_leave(_state);
}
/*************************************************************************
Unset spline, i.e. initialize it with random garbage
*************************************************************************/
static void testspline1dunit_unsetreport(spline1dfitreport* rep,
ae_state *_state)
{
_spline1dfitreport_clear(rep);
rep->taskrcond = ae_randomreal(_state);
rep->rmserror = ae_randomreal(_state);
rep->avgerror = ae_randomreal(_state);
rep->avgrelerror = ae_randomreal(_state);
rep->maxerror = ae_randomreal(_state);
}
/*************************************************************************
Tests that built spline is monotone.
*************************************************************************/
static ae_bool testspline1dunit_testmonotonespline(ae_state *_state)
{
ae_frame _frame_block;
spline1dinterpolant c;
spline1dinterpolant s2;
double c0;
double c1;
ae_vector x;
ae_vector y;
ae_vector d;
ae_int_t m;
ae_vector n;
ae_int_t alln;
ae_int_t shift;
double sign0;
double sign1;
double r;
double st;
double eps;
double delta;
double v;
double dv;
double d2v;
ae_int_t nseg;
ae_int_t npoints;
ae_int_t tp;
ae_int_t pass;
ae_int_t passcount;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t kmax;
ae_int_t l;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&c, 0, sizeof(c));
memset(&s2, 0, sizeof(s2));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&d, 0, sizeof(d));
memset(&n, 0, sizeof(n));
_spline1dinterpolant_init(&c, _state, ae_true);
_spline1dinterpolant_init(&s2, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&n, 0, DT_INT, _state, ae_true);
eps = 100*ae_machineepsilon;
/*
* Special test - N=2.
*
* Following properties are tested:
* * monotone spline must be equal to the Hermite spline with
* zero derivative at the ends
* * monotone spline is constant beyond left/right boundaries
*/
ae_vector_set_length(&x, 2, _state);
ae_vector_set_length(&y, 2, _state);
ae_vector_set_length(&d, 2, _state);
x.ptr.p_double[0] = -0.1-ae_randomreal(_state);
y.ptr.p_double[0] = 2*ae_randomreal(_state)-1;
d.ptr.p_double[0] = 0.0;
x.ptr.p_double[1] = 0.1+ae_randomreal(_state);
y.ptr.p_double[1] = y.ptr.p_double[0];
d.ptr.p_double[1] = 0.0;
spline1dbuildmonotone(&x, &y, 2, &c, _state);
spline1dbuildhermite(&x, &y, &d, 2, &s2, _state);
v = 2*ae_randomreal(_state)-1;
if( ae_fp_greater(ae_fabs(spline1dcalc(&c, v, _state)-spline1dcalc(&s2, v, _state), _state),eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
if( ae_fp_neq(spline1dcalc(&c, (double)(-5), _state),y.ptr.p_double[0]) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
if( ae_fp_neq(spline1dcalc(&c, (double)(5), _state),y.ptr.p_double[0]) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
/*
* Special test - N=3, x=[0,1,2], y=[0,1,0].
* Monotone spline must be equal to the Hermite spline with
* zero derivative at all points.
*/
ae_vector_set_length(&x, 3, _state);
ae_vector_set_length(&y, 3, _state);
ae_vector_set_length(&d, 3, _state);
x.ptr.p_double[0] = 0.0;
y.ptr.p_double[0] = 0.0;
d.ptr.p_double[0] = 0.0;
x.ptr.p_double[1] = 1.0;
y.ptr.p_double[1] = 1.0;
d.ptr.p_double[1] = 0.0;
x.ptr.p_double[2] = 2.0;
y.ptr.p_double[2] = 0.0;
d.ptr.p_double[2] = 0.0;
spline1dbuildmonotone(&x, &y, 3, &c, _state);
spline1dbuildhermite(&x, &y, &d, 3, &s2, _state);
for(i=0; i<=10; i++)
{
v = x.ptr.p_double[0]+(double)i/(double)10*(x.ptr.p_double[2]-x.ptr.p_double[0]);
if( ae_fp_greater(ae_fabs(spline1dcalc(&c, v, _state)-spline1dcalc(&s2, v, _state), _state),eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
/*
* Special test - N=5, x=[0,1,2,3,4], y=[0,1,1,2,3].
*
* 1) spline passes through all prescribed points
* 2) spline derivative at all points except x=3 is exactly zero
* 3) spline derivative at x=3 is 1.0 (within machine epsilon)
*/
ae_vector_set_length(&x, 5, _state);
ae_vector_set_length(&y, 5, _state);
x.ptr.p_double[0] = 0.0;
y.ptr.p_double[0] = 0.0;
x.ptr.p_double[1] = 1.0;
y.ptr.p_double[1] = 1.0;
x.ptr.p_double[2] = 2.0;
y.ptr.p_double[2] = 1.0;
x.ptr.p_double[3] = 3.0;
y.ptr.p_double[3] = 2.0;
x.ptr.p_double[4] = 4.0;
y.ptr.p_double[4] = 3.0;
spline1dbuildmonotone(&x, &y, 5, &c, _state);
for(i=0; i<=4; i++)
{
spline1ddiff(&c, x.ptr.p_double[i], &v, &dv, &d2v, _state);
if( ae_fp_greater(ae_fabs(v-y.ptr.p_double[i], _state),eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
if( (ae_fp_eq(x.ptr.p_double[i],3.0)&&ae_fp_greater(ae_fabs(dv-1.0, _state),eps))||(ae_fp_neq(x.ptr.p_double[i],3.0)&&ae_fp_neq(dv,(double)(0))) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
/*
* Special test:
* * N=4
* * three fixed points - (0,0), (1,1), (2,0)
* * one special point (x,y) with x in [0.1,0.9], y in [0.1,0.9]
* * monotonicity of the interpolant at [0,1] is checked with very small step 1/KMax
*/
ae_vector_set_length(&x, 4, _state);
ae_vector_set_length(&y, 4, _state);
x.ptr.p_double[0] = 0.0;
y.ptr.p_double[0] = 0.0;
x.ptr.p_double[2] = 1.0;
y.ptr.p_double[2] = 1.0;
x.ptr.p_double[3] = 2.0;
y.ptr.p_double[3] = 0.0;
for(i=1; i<=9; i++)
{
for(j=1; j<=9; j++)
{
x.ptr.p_double[1] = (double)i/(double)10;
y.ptr.p_double[1] = (double)j/(double)10;
spline1dbuildmonotone(&x, &y, 4, &c, _state);
kmax = 1000;
for(k=0; k<=kmax-1; k++)
{
if( ae_fp_greater(spline1dcalc(&c, (double)k/(double)kmax, _state),spline1dcalc(&c, (double)(k+1)/(double)kmax, _state)) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
/*
* General case
*/
delta = (double)(0);
nseg = 10;
npoints = 15;
passcount = 30;
for(pass=1; pass<=passcount; pass++)
{
tp = ae_randominteger(6, _state)+4;
r = (double)(ae_randominteger(76, _state)+25);
m = ae_randominteger(nseg, _state)+1;
ae_vector_set_length(&n, m, _state);
alln = 0;
for(i=0; i<=m-1; i++)
{
n.ptr.p_int[i] = ae_randominteger(npoints, _state)+2;
alln = alln+n.ptr.p_int[i];
}
ae_vector_set_length(&x, alln, _state);
ae_vector_set_length(&y, alln, _state);
x.ptr.p_double[0] = r*(2*ae_randomreal(_state)-1);
y.ptr.p_double[0] = r*(2*ae_randomreal(_state)-1);
/*
* Builds monotone function
*/
st = 0.1+0.7*ae_randomreal(_state);
shift = 0;
sign0 = ae_pow((double)(-1), (double)(0), _state);
for(i=0; i<=m-1; i++)
{
for(j=1; j<=n.ptr.p_int[i]-1; j++)
{
x.ptr.p_double[shift+j] = x.ptr.p_double[shift+j-1]+st+ae_randomreal(_state);
delta = ae_maxreal(delta, x.ptr.p_double[shift+j]-x.ptr.p_double[shift+j-1], _state);
y.ptr.p_double[shift+j] = y.ptr.p_double[shift+j-1]+sign0*(st+ae_randomreal(_state));
}
shift = shift+n.ptr.p_int[i];
if( i!=m-1 )
{
sign0 = ae_pow((double)(-1), (double)(i+1), _state);
x.ptr.p_double[shift] = x.ptr.p_double[shift-1]+st+ae_randomreal(_state);
y.ptr.p_double[shift] = y.ptr.p_double[shift-1]+sign0*ae_randomreal(_state);
}
}
delta = 3*delta;
spline1dbuildmonotone(&x, &y, alln, &c, _state);
/*
* Check that built function is monotone
*/
shift = 0;
for(i=0; i<=m-1; i++)
{
for(j=1; j<=n.ptr.p_int[i]-1; j++)
{
st = (x.ptr.p_double[shift+j]-x.ptr.p_double[shift+j-1])/tp;
sign0 = y.ptr.p_double[shift+j]-y.ptr.p_double[shift+j-1];
if( ae_fp_neq(sign0,(double)(0)) )
{
sign0 = sign0/ae_fabs(sign0, _state);
}
for(l=0; l<=tp-1; l++)
{
c0 = spline1dcalc(&c, x.ptr.p_double[shift+j-1]+l*st, _state);
c1 = spline1dcalc(&c, x.ptr.p_double[shift+j-1]+(l+1)*st, _state);
sign1 = c1-c0;
if( ae_fp_neq(sign1,(double)(0)) )
{
sign1 = sign1/ae_fabs(sign1, _state);
}
if( ae_fp_less(sign0*sign1,(double)(0)) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
c0 = spline1dcalc(&c, x.ptr.p_double[0]-delta, _state);
c1 = spline1dcalc(&c, x.ptr.p_double[0], _state);
if( ae_fp_greater(ae_fabs(c0-c1, _state),eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
c0 = spline1dcalc(&c, x.ptr.p_double[alln-1], _state);
c1 = spline1dcalc(&c, x.ptr.p_double[alln-1]+delta, _state);
if( ae_fp_greater(ae_fabs(c0-c1, _state),eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
/*
* Builds constant function
*/
y.ptr.p_double[0] = r*(2*ae_randomreal(_state)-1);
for(i=1; i<=alln-1; i++)
{
y.ptr.p_double[i] = y.ptr.p_double[0];
}
spline1dbuildmonotone(&x, &y, alln, &c, _state);
shift = 0;
for(i=0; i<=m-1; i++)
{
for(j=1; j<=n.ptr.p_int[i]-1; j++)
{
st = (x.ptr.p_double[shift+j]-x.ptr.p_double[shift+j-1])/tp;
sign0 = y.ptr.p_double[shift+j]-y.ptr.p_double[shift+j-1];
for(l=0; l<=tp-1; l++)
{
c0 = spline1dcalc(&c, x.ptr.p_double[shift+j-1]+l*st, _state);
c1 = spline1dcalc(&c, x.ptr.p_double[shift+j-1]+(l+1)*st, _state);
sign1 = c1-c0;
if( ae_fp_greater(sign0,eps)||ae_fp_greater(sign1,eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
static void testspline1dunit_testsplinefitting(ae_bool* fiterrors,
ae_state *_state)
{
ae_frame _frame_block;
double threshold;
double nonstrictthreshold;
ae_int_t passcount;
ae_int_t n;
ae_int_t m;
ae_int_t i;
ae_int_t k;
ae_int_t pass;
ae_vector x;
ae_vector y;
ae_vector w;
ae_vector w2;
ae_vector xc;
ae_vector yc;
ae_vector d;
ae_vector dc;
ae_int_t info;
ae_int_t info2;
spline1dinterpolant c;
spline1dinterpolant c2;
spline1dfitreport rep;
spline1dfitreport rep2;
double s;
double v;
double v1;
double v2;
double u;
double u1;
double u2;
double a;
double b;
double refrms;
double refavg;
double refavgrel;
double refmax;
double rho;
hqrndstate rs;
double prevresiduals;
double prevpenalty;
double residuals;
double penalty;
double mxd2;
ae_int_t testtype;
double lipschitzeps;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&w, 0, sizeof(w));
memset(&w2, 0, sizeof(w2));
memset(&xc, 0, sizeof(xc));
memset(&yc, 0, sizeof(yc));
memset(&d, 0, sizeof(d));
memset(&dc, 0, sizeof(dc));
memset(&c, 0, sizeof(c));
memset(&c2, 0, sizeof(c2));
memset(&rep, 0, sizeof(rep));
memset(&rep2, 0, sizeof(rep2));
memset(&rs, 0, sizeof(rs));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&yc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&dc, 0, DT_INT, _state, ae_true);
_spline1dinterpolant_init(&c, _state, ae_true);
_spline1dinterpolant_init(&c2, _state, ae_true);
_spline1dfitreport_init(&rep, _state, ae_true);
_spline1dfitreport_init(&rep2, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Values:
* * pass count
* * threshold - for tests which must be satisfied exactly
* * nonstrictthreshold - for approximate tests
*/
passcount = 20;
threshold = 10000*ae_machineepsilon;
nonstrictthreshold = 1.0E-6;
lipschitzeps = 1.0E-6;
*fiterrors = ae_false;
/*
* check basic properties of penalized splines which are
* preserved independently of Rho parameter.
*/
for(m=4; m<=10; m++)
{
for(k=-5; k<=5; k++)
{
rho = (double)(k);
/*
* when we have two points (even with different weights),
* resulting spline must be equal to the straight line
*/
ae_vector_set_length(&x, 2, _state);
ae_vector_set_length(&y, 2, _state);
ae_vector_set_length(&w, 2, _state);
x.ptr.p_double[0] = -0.5-ae_randomreal(_state);
y.ptr.p_double[0] = 0.5+ae_randomreal(_state);
w.ptr.p_double[0] = 1+ae_randomreal(_state);
x.ptr.p_double[1] = 0.5+ae_randomreal(_state);
y.ptr.p_double[1] = 0.5+ae_randomreal(_state);
w.ptr.p_double[1] = 1+ae_randomreal(_state);
testspline1dunit_unsetspline1d(&c, _state);
testspline1dunit_unsetreport(&rep, _state);
spline1dfit(&x, &y, 2, m, ae_pow(10.0, rho, _state), &c, &rep, _state);
v = 2*ae_randomreal(_state)-1;
v1 = (v-x.ptr.p_double[0])/(x.ptr.p_double[1]-x.ptr.p_double[0])*y.ptr.p_double[1]+(v-x.ptr.p_double[1])/(x.ptr.p_double[0]-x.ptr.p_double[1])*y.ptr.p_double[0];
ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(v1-spline1dcalc(&c, v, _state), _state),threshold), __FILE__, __LINE__, "testspline1dunit.ap:1508");
ae_set_error_flag(fiterrors, ae_fp_greater(rep.rmserror,threshold), __FILE__, __LINE__, "testspline1dunit.ap:1509");
ae_set_error_flag(fiterrors, ae_fp_greater(rep.avgerror,threshold), __FILE__, __LINE__, "testspline1dunit.ap:1510");
ae_set_error_flag(fiterrors, ae_fp_greater(rep.maxerror,threshold), __FILE__, __LINE__, "testspline1dunit.ap:1511");
}
}
/*
* Test spline ability to reproduce target:
* * a penalized spline with M=N and nearly zero Rho must pass
* through all points on equidistant grid
* * a penalized spline with M about 5*N and sufficiently small
* Rho must pass through all points on equidistant grid
* In both cases spline must be C0, C1 and C2 continuous.
*/
for(n=2; n<=20; n++)
{
/*
* Fit
*/
m = n;
rho = (double)(-15);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = (double)i/(double)(n-1);
y.ptr.p_double[i] = ae_randomreal(_state)-0.5;
}
testspline1dunit_unsetspline1d(&c, _state);
testspline1dunit_unsetreport(&rep, _state);
spline1dfit(&x, &y, n, m, ae_pow((double)(10), rho, _state), &c, &rep, _state);
/*
* Test that spline passes through all the points
*/
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(y.ptr.p_double[i]-spline1dcalc(&c, x.ptr.p_double[i], _state), _state),nonstrictthreshold), __FILE__, __LINE__, "testspline1dunit.ap:1544");
}
ae_set_error_flag(fiterrors, ae_fp_greater(rep.rmserror,nonstrictthreshold), __FILE__, __LINE__, "testspline1dunit.ap:1545");
ae_set_error_flag(fiterrors, ae_fp_greater(rep.avgerror,nonstrictthreshold), __FILE__, __LINE__, "testspline1dunit.ap:1546");
ae_set_error_flag(fiterrors, ae_fp_greater(rep.maxerror,nonstrictthreshold), __FILE__, __LINE__, "testspline1dunit.ap:1547");
/*
* Test continuity properties
*/
s = 0.01*((double)1/(double)m);
testspline1dunit_lconst((double)(0), (double)(1), &c, s, &u, &u1, &u2, _state);
testspline1dunit_lconst((double)(0), (double)(1), &c, s/2, &v, &v1, &v2, _state);
ae_set_error_flag(fiterrors, ae_fp_greater(v/(u+lipschitzeps),1.2), __FILE__, __LINE__, "testspline1dunit.ap:1556");
ae_set_error_flag(fiterrors, ae_fp_greater(v1/(u1+lipschitzeps*m),1.2), __FILE__, __LINE__, "testspline1dunit.ap:1557");
ae_set_error_flag(fiterrors, ae_fp_greater(v2/(u2+lipschitzeps*ae_sqr((double)(m), _state)),1.2), __FILE__, __LINE__, "testspline1dunit.ap:1558");
}
for(n=2; n<=20; n++)
{
m = 5*n;
rho = (double)(-10);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
ae_vector_set_length(&w, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = (double)i/(double)(n-1);
y.ptr.p_double[i] = ae_randomreal(_state);
w.ptr.p_double[i] = 0.1+ae_randomreal(_state);
}
testspline1dunit_unsetspline1d(&c, _state);
testspline1dunit_unsetreport(&rep, _state);
spline1dfit(&x, &y, n, m, ae_pow((double)(10), rho, _state), &c, &rep, _state);
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(y.ptr.p_double[i]-spline1dcalc(&c, x.ptr.p_double[i], _state), _state),nonstrictthreshold), __FILE__, __LINE__, "testspline1dunit.ap:1577");
}
ae_set_error_flag(fiterrors, ae_fp_greater(rep.rmserror,nonstrictthreshold), __FILE__, __LINE__, "testspline1dunit.ap:1578");
ae_set_error_flag(fiterrors, ae_fp_greater(rep.avgerror,nonstrictthreshold), __FILE__, __LINE__, "testspline1dunit.ap:1579");
ae_set_error_flag(fiterrors, ae_fp_greater(rep.maxerror,nonstrictthreshold), __FILE__, __LINE__, "testspline1dunit.ap:1580");
/*
* Test continuity properties
*/
s = 0.01*((double)1/(double)m);
testspline1dunit_lconst((double)(0), (double)(1), &c, s, &u, &u1, &u2, _state);
testspline1dunit_lconst((double)(0), (double)(1), &c, s/2, &v, &v1, &v2, _state);
ae_set_error_flag(fiterrors, ae_fp_greater(v/(u+lipschitzeps),1.2), __FILE__, __LINE__, "testspline1dunit.ap:1589");
ae_set_error_flag(fiterrors, ae_fp_greater(v1/(u1+lipschitzeps*m),1.2), __FILE__, __LINE__, "testspline1dunit.ap:1590");
ae_set_error_flag(fiterrors, ae_fp_greater(v2/(u2+lipschitzeps*ae_sqr((double)(m), _state)),1.2), __FILE__, __LINE__, "testspline1dunit.ap:1591");
}
/*
* Test smoothing properties: a sequence of problems with increasing Rho
* results in residuals monotonically increasing and nonlinearity penalty
* monotonically decreasing.
*
* This test is performed twice: first time for M<>N
*/
for(testtype=0; testtype<=1; testtype++)
{
if( testtype==0 )
{
n = 100;
m = 10;
}
else
{
n = 10;
m = 100;
}
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = hqrndnormal(&rs, _state);
y.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
a = x.ptr.p_double[0];
b = x.ptr.p_double[0];
for(i=1; i<=n-1; i++)
{
a = ae_minreal(a, x.ptr.p_double[i], _state);
b = ae_maxreal(b, x.ptr.p_double[i], _state);
}
prevresiduals = (double)(0);
prevpenalty = ae_maxrealnumber;
rho = (double)(-4);
while(ae_fp_less_eq(rho,(double)(4)))
{
/*
* Fit spline
*/
testspline1dunit_unsetspline1d(&c, _state);
testspline1dunit_unsetreport(&rep, _state);
spline1dfit(&x, &y, n, m, ae_pow((double)(10), rho, _state), &c, &rep, _state);
/*
* Test continuity properties
*/
s = 0.01*((b-a)/m);
testspline1dunit_lconst(a, b, &c, s, &u, &u1, &u2, _state);
testspline1dunit_lconst(a, b, &c, s/2, &v, &v1, &v2, _state);
ae_set_error_flag(fiterrors, ae_fp_greater(v/(u+lipschitzeps),1.2), __FILE__, __LINE__, "testspline1dunit.ap:1646");
ae_set_error_flag(fiterrors, ae_fp_greater(v1/(u1+lipschitzeps*m),1.2), __FILE__, __LINE__, "testspline1dunit.ap:1647");
ae_set_error_flag(fiterrors, ae_fp_greater(v2/(u2+lipschitzeps*ae_sqr((double)(m), _state)),1.2), __FILE__, __LINE__, "testspline1dunit.ap:1648");
/*
* Compute residuals and penalty
*/
residuals = (double)(0);
for(i=0; i<=n-1; i++)
{
residuals = residuals+ae_sqr(spline1dcalc(&c, x.ptr.p_double[i], _state)-y.ptr.p_double[i], _state);
}
residuals = residuals/n;
penalty = (double)(0);
mxd2 = (double)(0);
k = 100*m;
for(i=0; i<=k; i++)
{
spline1ddiff(&c, a+(b-a)*i/k, &v, &v1, &v2, _state);
penalty = penalty+ae_sqr(v2, _state);
mxd2 = ae_maxreal(mxd2, ae_fabs(v2, _state), _state);
}
penalty = penalty/(k+1);
/*
* Compare with previous, update previous, update Rho
*
* Write('%.15e %.15e %.15e\n', Residuals, Penalty, MxD2);
*/
ae_set_error_flag(fiterrors, ae_fp_less_eq(residuals,prevresiduals), __FILE__, __LINE__, "testspline1dunit.ap:1674");
ae_set_error_flag(fiterrors, ae_fp_greater_eq(penalty,prevpenalty), __FILE__, __LINE__, "testspline1dunit.ap:1675");
prevresiduals = residuals;
prevpenalty = penalty;
rho = rho+1;
}
ae_set_error_flag(fiterrors, ae_fp_greater_eq(penalty,1.0E-6), __FILE__, __LINE__, "testspline1dunit.ap:1680");
ae_set_error_flag(fiterrors, ae_fp_greater_eq(mxd2,1.0E-3), __FILE__, __LINE__, "testspline1dunit.ap:1681");
}
/*
* Special test which allows to distinguish "true smoothing" from
* basic regularization enforced upon spline coefficients.
*/
n = 4;
m = 100;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
x.ptr.p_double[0] = (double)(-2);
x.ptr.p_double[1] = (double)(-1);
x.ptr.p_double[2] = (double)(1);
x.ptr.p_double[3] = (double)(2);
y.ptr.p_double[0] = (double)(-1);
y.ptr.p_double[1] = (double)(1);
y.ptr.p_double[2] = (double)(1);
y.ptr.p_double[3] = (double)(-1);
rho = (double)(-5);
spline1dfit(&x, &y, n, m, ae_pow((double)(10), rho, _state), &c, &rep, _state);
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(spline1dcalc(&c, x.ptr.p_double[i], _state)-y.ptr.p_double[i], _state),0.0001), __FILE__, __LINE__, "testspline1dunit.ap:1703");
}
ae_set_error_flag(fiterrors, ae_fp_less(spline1dcalc(&c, (double)(0), _state),1.000), __FILE__, __LINE__, "testspline1dunit.ap:1704");
/*
* Check correctness of error reports
*/
for(pass=1; pass<=passcount; pass++)
{
ae_assert(passcount>=2, "PassCount should be 2 or greater!", _state);
/*
* solve simple task (all X[] are the same, Y[] are specially
* calculated to ensure simple form of all types of errors)
* and check correctness of the errors calculated by subroutines
*
* First pass is done with zero Y[], other passes - with random Y[].
* It should test both ability to correctly calculate errors and
* ability to not fail while working with zeros :)
*/
n = 4;
if( pass==1 )
{
v1 = (double)(0);
v2 = (double)(0);
v = (double)(0);
}
else
{
v1 = ae_randomreal(_state);
v2 = ae_randomreal(_state);
v = 1+ae_randomreal(_state);
}
ae_vector_set_length(&x, 4, _state);
ae_vector_set_length(&y, 4, _state);
ae_vector_set_length(&w, 4, _state);
x.ptr.p_double[0] = (double)(0);
y.ptr.p_double[0] = v-v2;
w.ptr.p_double[0] = (double)(1);
x.ptr.p_double[1] = (double)(0);
y.ptr.p_double[1] = v-v1;
w.ptr.p_double[1] = (double)(1);
x.ptr.p_double[2] = (double)(0);
y.ptr.p_double[2] = v+v1;
w.ptr.p_double[2] = (double)(1);
x.ptr.p_double[3] = (double)(0);
y.ptr.p_double[3] = v+v2;
w.ptr.p_double[3] = (double)(1);
refrms = ae_sqrt((ae_sqr(v1, _state)+ae_sqr(v2, _state))/2, _state);
refavg = (ae_fabs(v1, _state)+ae_fabs(v2, _state))/2;
if( pass==1 )
{
refavgrel = (double)(0);
}
else
{
refavgrel = 0.25*(ae_fabs(v2, _state)/ae_fabs(v-v2, _state)+ae_fabs(v1, _state)/ae_fabs(v-v1, _state)+ae_fabs(v1, _state)/ae_fabs(v+v1, _state)+ae_fabs(v2, _state)/ae_fabs(v+v2, _state));
}
refmax = ae_maxreal(v1, v2, _state);
spline1dfit(&x, &y, 4, 4, 0.0, &c, &rep, _state);
s = spline1dcalc(&c, (double)(0), _state);
ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(s-v, _state),threshold), __FILE__, __LINE__, "testspline1dunit.ap:1759");
ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state),threshold), __FILE__, __LINE__, "testspline1dunit.ap:1760");
ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state),threshold), __FILE__, __LINE__, "testspline1dunit.ap:1761");
ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state),threshold), __FILE__, __LINE__, "testspline1dunit.ap:1762");
ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(rep.maxerror-refmax, _state),threshold), __FILE__, __LINE__, "testspline1dunit.ap:1763");
}
ae_frame_leave(_state);
}
static void testparametricunit_testrdp(ae_bool* errorflag,
ae_state *_state);
static void testparametricunit_unsetp2(pspline2interpolant* p,
ae_state *_state);
static void testparametricunit_unsetp3(pspline3interpolant* p,
ae_state *_state);
ae_bool testparametric(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_bool waserrors;
ae_bool p2errors;
ae_bool p3errors;
ae_bool rdperrors;
double nonstrictthreshold;
double threshold;
ae_int_t maxn;
ae_int_t periodicity;
ae_int_t skind;
ae_int_t pkind;
ae_bool periodic;
double a;
double b;
ae_int_t n;
ae_int_t tmpn;
ae_int_t i;
double vx;
double vy;
double vz;
double vx2;
double vy2;
double vz2;
double vdx;
double vdy;
double vdz;
double vdx2;
double vdy2;
double vdz2;
double vd2x;
double vd2y;
double vd2z;
double vd2x2;
double vd2y2;
double vd2z2;
double v0;
double v1;
ae_vector x;
ae_vector y;
ae_vector z;
ae_vector t;
ae_vector t2;
ae_vector t3;
ae_matrix xy;
ae_matrix xyz;
pspline2interpolant p2;
pspline3interpolant p3;
spline1dinterpolant s;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&z, 0, sizeof(z));
memset(&t, 0, sizeof(t));
memset(&t2, 0, sizeof(t2));
memset(&t3, 0, sizeof(t3));
memset(&xy, 0, sizeof(xy));
memset(&xyz, 0, sizeof(xyz));
memset(&p2, 0, sizeof(p2));
memset(&p3, 0, sizeof(p3));
memset(&s, 0, sizeof(s));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&z, 0, DT_REAL, _state, ae_true);
ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
ae_vector_init(&t2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&t3, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xyz, 0, 0, DT_REAL, _state, ae_true);
_pspline2interpolant_init(&p2, _state, ae_true);
_pspline3interpolant_init(&p3, _state, ae_true);
_spline1dinterpolant_init(&s, _state, ae_true);
waserrors = ae_false;
maxn = 10;
threshold = 10000*ae_machineepsilon;
nonstrictthreshold = 0.00001;
p2errors = ae_false;
p3errors = ae_false;
rdperrors = ae_false;
testparametricunit_testrdp(&rdperrors, _state);
/*
* Test basic properties of 2- and 3-dimensional splines:
* * PSpline2ParameterValues() properties
* * values at nodes
* * for periodic splines - periodicity properties
*
* Variables used:
* * N points count
* * SKind spline
* * PKind parameterization
* * Periodicity whether we have periodic spline or not
*/
for(n=2; n<=maxn; n++)
{
for(skind=0; skind<=2; skind++)
{
for(pkind=0; pkind<=2; pkind++)
{
for(periodicity=0; periodicity<=1; periodicity++)
{
periodic = periodicity==1;
/*
* skip unsupported combinations of parameters
*/
if( periodic&&n<3 )
{
continue;
}
if( periodic&&skind==0 )
{
continue;
}
if( n<5&&skind==0 )
{
continue;
}
/*
* init
*/
ae_matrix_set_length(&xy, n, 2, _state);
ae_matrix_set_length(&xyz, n, 3, _state);
taskgenint1dequidist((double)(-1), (double)(1), n, &t2, &x, _state);
ae_v_move(&xy.ptr.pp_double[0][0], xy.stride, &x.ptr.p_double[0], 1, ae_v_len(0,n-1));
ae_v_move(&xyz.ptr.pp_double[0][0], xyz.stride, &x.ptr.p_double[0], 1, ae_v_len(0,n-1));
taskgenint1dequidist((double)(-1), (double)(1), n, &t2, &y, _state);
ae_v_move(&xy.ptr.pp_double[0][1], xy.stride, &y.ptr.p_double[0], 1, ae_v_len(0,n-1));
ae_v_move(&xyz.ptr.pp_double[0][1], xyz.stride, &y.ptr.p_double[0], 1, ae_v_len(0,n-1));
taskgenint1dequidist((double)(-1), (double)(1), n, &t2, &z, _state);
ae_v_move(&xyz.ptr.pp_double[0][2], xyz.stride, &z.ptr.p_double[0], 1, ae_v_len(0,n-1));
testparametricunit_unsetp2(&p2, _state);
testparametricunit_unsetp3(&p3, _state);
if( periodic )
{
pspline2buildperiodic(&xy, n, skind, pkind, &p2, _state);
pspline3buildperiodic(&xyz, n, skind, pkind, &p3, _state);
}
else
{
pspline2build(&xy, n, skind, pkind, &p2, _state);
pspline3build(&xyz, n, skind, pkind, &p3, _state);
}
/*
* PSpline2ParameterValues() properties
*/
pspline2parametervalues(&p2, &tmpn, &t2, _state);
if( tmpn!=n )
{
p2errors = ae_true;
continue;
}
pspline3parametervalues(&p3, &tmpn, &t3, _state);
if( tmpn!=n )
{
p3errors = ae_true;
continue;
}
p2errors = p2errors||ae_fp_neq(t2.ptr.p_double[0],(double)(0));
p3errors = p3errors||ae_fp_neq(t3.ptr.p_double[0],(double)(0));
for(i=1; i<=n-1; i++)
{
p2errors = p2errors||ae_fp_less_eq(t2.ptr.p_double[i],t2.ptr.p_double[i-1]);
p3errors = p3errors||ae_fp_less_eq(t3.ptr.p_double[i],t3.ptr.p_double[i-1]);
}
if( periodic )
{
p2errors = p2errors||ae_fp_greater_eq(t2.ptr.p_double[n-1],(double)(1));
p3errors = p3errors||ae_fp_greater_eq(t3.ptr.p_double[n-1],(double)(1));
}
else
{
p2errors = p2errors||ae_fp_neq(t2.ptr.p_double[n-1],(double)(1));
p3errors = p3errors||ae_fp_neq(t3.ptr.p_double[n-1],(double)(1));
}
/*
* Now we have parameter values stored at T,
* and want to test whether the actully correspond to
* points
*/
for(i=0; i<=n-1; i++)
{
/*
* 2-dimensional test
*/
pspline2calc(&p2, t2.ptr.p_double[i], &vx, &vy, _state);
p2errors = p2errors||ae_fp_greater(ae_fabs(vx-x.ptr.p_double[i], _state),threshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vy-y.ptr.p_double[i], _state),threshold);
/*
* 3-dimensional test
*/
pspline3calc(&p3, t3.ptr.p_double[i], &vx, &vy, &vz, _state);
p3errors = p3errors||ae_fp_greater(ae_fabs(vx-x.ptr.p_double[i], _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vy-y.ptr.p_double[i], _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vz-z.ptr.p_double[i], _state),threshold);
}
/*
* Test periodicity (if needed)
*/
if( periodic )
{
/*
* periodicity at nodes
*/
for(i=0; i<=n-1; i++)
{
/*
* 2-dimensional test
*/
pspline2calc(&p2, t2.ptr.p_double[i]+ae_randominteger(10, _state)-5, &vx, &vy, _state);
p2errors = p2errors||ae_fp_greater(ae_fabs(vx-x.ptr.p_double[i], _state),threshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vy-y.ptr.p_double[i], _state),threshold);
pspline2diff(&p2, t2.ptr.p_double[i]+ae_randominteger(10, _state)-5, &vx, &vdx, &vy, &vdy, _state);
p2errors = p2errors||ae_fp_greater(ae_fabs(vx-x.ptr.p_double[i], _state),threshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vy-y.ptr.p_double[i], _state),threshold);
pspline2diff2(&p2, t2.ptr.p_double[i]+ae_randominteger(10, _state)-5, &vx, &vdx, &vd2x, &vy, &vdy, &vd2y, _state);
p2errors = p2errors||ae_fp_greater(ae_fabs(vx-x.ptr.p_double[i], _state),threshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vy-y.ptr.p_double[i], _state),threshold);
/*
* 3-dimensional test
*/
pspline3calc(&p3, t3.ptr.p_double[i]+ae_randominteger(10, _state)-5, &vx, &vy, &vz, _state);
p3errors = p3errors||ae_fp_greater(ae_fabs(vx-x.ptr.p_double[i], _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vy-y.ptr.p_double[i], _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vz-z.ptr.p_double[i], _state),threshold);
pspline3diff(&p3, t3.ptr.p_double[i]+ae_randominteger(10, _state)-5, &vx, &vdx, &vy, &vdy, &vz, &vdz, _state);
p3errors = p3errors||ae_fp_greater(ae_fabs(vx-x.ptr.p_double[i], _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vy-y.ptr.p_double[i], _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vz-z.ptr.p_double[i], _state),threshold);
pspline3diff2(&p3, t3.ptr.p_double[i]+ae_randominteger(10, _state)-5, &vx, &vdx, &vd2x, &vy, &vdy, &vd2y, &vz, &vdz, &vd2z, _state);
p3errors = p3errors||ae_fp_greater(ae_fabs(vx-x.ptr.p_double[i], _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vy-y.ptr.p_double[i], _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vz-z.ptr.p_double[i], _state),threshold);
}
/*
* periodicity between nodes
*/
v0 = ae_randomreal(_state);
pspline2calc(&p2, v0, &vx, &vy, _state);
pspline2calc(&p2, v0+ae_randominteger(10, _state)-5, &vx2, &vy2, _state);
p2errors = p2errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold);
pspline3calc(&p3, v0, &vx, &vy, &vz, _state);
pspline3calc(&p3, v0+ae_randominteger(10, _state)-5, &vx2, &vy2, &vz2, _state);
p3errors = p3errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vz-vz2, _state),threshold);
/*
* near-boundary test for continuity of function values and derivatives:
* 2-dimensional curve
*/
ae_assert(skind==1||skind==2, "TEST: unexpected spline type!", _state);
v0 = 100*ae_machineepsilon;
v1 = 1-v0;
pspline2calc(&p2, v0, &vx, &vy, _state);
pspline2calc(&p2, v1, &vx2, &vy2, _state);
p2errors = p2errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold);
pspline2diff(&p2, v0, &vx, &vdx, &vy, &vdy, _state);
pspline2diff(&p2, v1, &vx2, &vdx2, &vy2, &vdy2, _state);
p2errors = p2errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vdx-vdx2, _state),nonstrictthreshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vdy-vdy2, _state),nonstrictthreshold);
pspline2diff2(&p2, v0, &vx, &vdx, &vd2x, &vy, &vdy, &vd2y, _state);
pspline2diff2(&p2, v1, &vx2, &vdx2, &vd2x2, &vy2, &vdy2, &vd2y2, _state);
p2errors = p2errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vdx-vdx2, _state),nonstrictthreshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vdy-vdy2, _state),nonstrictthreshold);
if( skind==2 )
{
/*
* second derivative test only for cubic splines
*/
p2errors = p2errors||ae_fp_greater(ae_fabs(vd2x-vd2x2, _state),nonstrictthreshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vd2y-vd2y2, _state),nonstrictthreshold);
}
/*
* near-boundary test for continuity of function values and derivatives:
* 3-dimensional curve
*/
ae_assert(skind==1||skind==2, "TEST: unexpected spline type!", _state);
v0 = 100*ae_machineepsilon;
v1 = 1-v0;
pspline3calc(&p3, v0, &vx, &vy, &vz, _state);
pspline3calc(&p3, v1, &vx2, &vy2, &vz2, _state);
p3errors = p3errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vz-vz2, _state),threshold);
pspline3diff(&p3, v0, &vx, &vdx, &vy, &vdy, &vz, &vdz, _state);
pspline3diff(&p3, v1, &vx2, &vdx2, &vy2, &vdy2, &vz2, &vdz2, _state);
p3errors = p3errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vz-vz2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vdx-vdx2, _state),nonstrictthreshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vdy-vdy2, _state),nonstrictthreshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vdz-vdz2, _state),nonstrictthreshold);
pspline3diff2(&p3, v0, &vx, &vdx, &vd2x, &vy, &vdy, &vd2y, &vz, &vdz, &vd2z, _state);
pspline3diff2(&p3, v1, &vx2, &vdx2, &vd2x2, &vy2, &vdy2, &vd2y2, &vz2, &vdz2, &vd2z2, _state);
p3errors = p3errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vz-vz2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vdx-vdx2, _state),nonstrictthreshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vdy-vdy2, _state),nonstrictthreshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vdz-vdz2, _state),nonstrictthreshold);
if( skind==2 )
{
/*
* second derivative test only for cubic splines
*/
p3errors = p3errors||ae_fp_greater(ae_fabs(vd2x-vd2x2, _state),nonstrictthreshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vd2y-vd2y2, _state),nonstrictthreshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vd2z-vd2z2, _state),nonstrictthreshold);
}
}
}
}
}
}
/*
* Test differentiation, tangents, calculation between nodes.
*
* Because differentiation is done in parameterization/spline/periodicity
* oblivious manner, we don't have to test all possible combinations
* of spline types and parameterizations.
*
* Actually we test special combination with properties which allow us
* to easily solve this problem:
* * 2 (3) variables
* * first variable is sampled from equidistant grid on [0,1]
* * other variables are random
* * uniform parameterization is used
* * periodicity - none
* * spline type - any (we use cubic splines)
* Same problem allows us to test calculation BETWEEN nodes.
*/
for(n=2; n<=maxn; n++)
{
/*
* init
*/
ae_matrix_set_length(&xy, n, 2, _state);
ae_matrix_set_length(&xyz, n, 3, _state);
taskgenint1dequidist((double)(0), (double)(1), n, &t, &x, _state);
ae_v_move(&xy.ptr.pp_double[0][0], xy.stride, &x.ptr.p_double[0], 1, ae_v_len(0,n-1));
ae_v_move(&xyz.ptr.pp_double[0][0], xyz.stride, &x.ptr.p_double[0], 1, ae_v_len(0,n-1));
taskgenint1dequidist((double)(0), (double)(1), n, &t, &y, _state);
ae_v_move(&xy.ptr.pp_double[0][1], xy.stride, &y.ptr.p_double[0], 1, ae_v_len(0,n-1));
ae_v_move(&xyz.ptr.pp_double[0][1], xyz.stride, &y.ptr.p_double[0], 1, ae_v_len(0,n-1));
taskgenint1dequidist((double)(0), (double)(1), n, &t, &z, _state);
ae_v_move(&xyz.ptr.pp_double[0][2], xyz.stride, &z.ptr.p_double[0], 1, ae_v_len(0,n-1));
testparametricunit_unsetp2(&p2, _state);
testparametricunit_unsetp3(&p3, _state);
pspline2build(&xy, n, 2, 0, &p2, _state);
pspline3build(&xyz, n, 2, 0, &p3, _state);
/*
* Test 2D/3D spline:
* * build non-parametric cubic spline from T and X/Y
* * calculate its value and derivatives at V0
* * compare with Spline2Calc/Spline2Diff/Spline2Diff2
* Because of task properties both variants should
* return same answer.
*/
v0 = ae_randomreal(_state);
spline1dbuildcubic(&t, &x, n, 0, 0.0, 0, 0.0, &s, _state);
spline1ddiff(&s, v0, &vx2, &vdx2, &vd2x2, _state);
spline1dbuildcubic(&t, &y, n, 0, 0.0, 0, 0.0, &s, _state);
spline1ddiff(&s, v0, &vy2, &vdy2, &vd2y2, _state);
spline1dbuildcubic(&t, &z, n, 0, 0.0, 0, 0.0, &s, _state);
spline1ddiff(&s, v0, &vz2, &vdz2, &vd2z2, _state);
/*
* 2D test
*/
pspline2calc(&p2, v0, &vx, &vy, _state);
p2errors = p2errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold);
pspline2diff(&p2, v0, &vx, &vdx, &vy, &vdy, _state);
p2errors = p2errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vdx-vdx2, _state),threshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vdy-vdy2, _state),threshold);
pspline2diff2(&p2, v0, &vx, &vdx, &vd2x, &vy, &vdy, &vd2y, _state);
p2errors = p2errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vdx-vdx2, _state),threshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vdy-vdy2, _state),threshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vd2x-vd2x2, _state),threshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vd2y-vd2y2, _state),threshold);
/*
* 3D test
*/
pspline3calc(&p3, v0, &vx, &vy, &vz, _state);
p3errors = p3errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vz-vz2, _state),threshold);
pspline3diff(&p3, v0, &vx, &vdx, &vy, &vdy, &vz, &vdz, _state);
p3errors = p3errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vz-vz2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vdx-vdx2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vdy-vdy2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vdz-vdz2, _state),threshold);
pspline3diff2(&p3, v0, &vx, &vdx, &vd2x, &vy, &vdy, &vd2y, &vz, &vdz, &vd2z, _state);
p3errors = p3errors||ae_fp_greater(ae_fabs(vx-vx2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vy-vy2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vz-vz2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vdx-vdx2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vdy-vdy2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vdz-vdz2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vd2x-vd2x2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vd2y-vd2y2, _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vd2z-vd2z2, _state),threshold);
/*
* Test tangents for 2D/3D
*/
pspline2tangent(&p2, v0, &vx, &vy, _state);
p2errors = p2errors||ae_fp_greater(ae_fabs(vx-vdx2/safepythag2(vdx2, vdy2, _state), _state),threshold);
p2errors = p2errors||ae_fp_greater(ae_fabs(vy-vdy2/safepythag2(vdx2, vdy2, _state), _state),threshold);
pspline3tangent(&p3, v0, &vx, &vy, &vz, _state);
p3errors = p3errors||ae_fp_greater(ae_fabs(vx-vdx2/safepythag3(vdx2, vdy2, vdz2, _state), _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vy-vdy2/safepythag3(vdx2, vdy2, vdz2, _state), _state),threshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(vz-vdz2/safepythag3(vdx2, vdy2, vdz2, _state), _state),threshold);
}
/*
* Arc length test.
*
* Simple problem with easy solution (points on a straight line with
* uniform parameterization).
*/
for(n=2; n<=maxn; n++)
{
ae_matrix_set_length(&xy, n, 2, _state);
ae_matrix_set_length(&xyz, n, 3, _state);
for(i=0; i<=n-1; i++)
{
xy.ptr.pp_double[i][0] = (double)(i);
xy.ptr.pp_double[i][1] = (double)(i);
xyz.ptr.pp_double[i][0] = (double)(i);
xyz.ptr.pp_double[i][1] = (double)(i);
xyz.ptr.pp_double[i][2] = (double)(i);
}
pspline2build(&xy, n, 1, 0, &p2, _state);
pspline3build(&xyz, n, 1, 0, &p3, _state);
a = ae_randomreal(_state);
b = ae_randomreal(_state);
p2errors = p2errors||ae_fp_greater(ae_fabs(pspline2arclength(&p2, a, b, _state)-(b-a)*ae_sqrt((double)(2), _state)*(n-1), _state),nonstrictthreshold);
p3errors = p3errors||ae_fp_greater(ae_fabs(pspline3arclength(&p3, a, b, _state)-(b-a)*ae_sqrt((double)(3), _state)*(n-1), _state),nonstrictthreshold);
}
/*
* report
*/
waserrors = (p2errors||p3errors)||rdperrors;
if( !silent )
{
printf("TESTING PARAMETRIC INTERPOLATION\n");
/*
* Normal tests
*/
printf("2D SPLINES: ");
if( p2errors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("3D SPLINES: ");
if( p3errors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("RDP: ");
if( rdperrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
/*
* end
*/
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function tests 4PL/5PL fitting. On error sets FitErrors flag variable;
on success - flag is not changed.
*************************************************************************/
static void testparametricunit_testrdp(ae_bool* errorflag,
ae_state *_state)
{
ae_frame _frame_block;
hqrndstate rs;
ae_vector x;
ae_vector y;
ae_vector e;
ae_vector x2;
ae_vector y2;
ae_vector x3;
ae_vector y3;
ae_matrix xy;
ae_matrix xy2;
ae_matrix xy3;
ae_vector idx2;
ae_vector idx3;
ae_int_t nsections;
ae_int_t nsections3;
double eps;
double v;
ae_int_t i;
ae_int_t j;
ae_int_t n;
ae_int_t d;
spline1dinterpolant s;
ae_frame_make(_state, &_frame_block);
memset(&rs, 0, sizeof(rs));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&e, 0, sizeof(e));
memset(&x2, 0, sizeof(x2));
memset(&y2, 0, sizeof(y2));
memset(&x3, 0, sizeof(x3));
memset(&y3, 0, sizeof(y3));
memset(&xy, 0, sizeof(xy));
memset(&xy2, 0, sizeof(xy2));
memset(&xy3, 0, sizeof(xy3));
memset(&idx2, 0, sizeof(idx2));
memset(&idx3, 0, sizeof(idx3));
memset(&s, 0, sizeof(s));
_hqrndstate_init(&rs, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&e, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x3, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y3, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy3, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&idx2, 0, DT_INT, _state, ae_true);
ae_vector_init(&idx3, 0, DT_INT, _state, ae_true);
_spline1dinterpolant_init(&s, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Parametric test 1: non-closed curve
*/
ae_matrix_set_length(&xy, 4, 2, _state);
xy.ptr.pp_double[0][0] = (double)(0);
xy.ptr.pp_double[0][1] = (double)(0);
xy.ptr.pp_double[1][0] = (double)(1);
xy.ptr.pp_double[1][1] = (double)(2);
xy.ptr.pp_double[2][0] = (double)(3);
xy.ptr.pp_double[2][1] = (double)(1);
xy.ptr.pp_double[3][0] = (double)(3);
xy.ptr.pp_double[3][1] = (double)(3);
parametricrdpfixed(&xy, 4, 2, 0, ae_sqrt((double)(2), _state)+0.001, &xy2, &idx2, &nsections, _state);
ae_set_error_flag(errorflag, nsections!=1, __FILE__, __LINE__, "testparametricunit.ap:41");
if( nsections==1 )
{
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:44");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:45");
ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:46");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][0],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:47");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][1],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:48");
ae_set_error_flag(errorflag, idx2.ptr.p_int[1]!=3, __FILE__, __LINE__, "testparametricunit.ap:49");
}
parametricrdpfixed(&xy, 4, 2, 0, ae_sqrt((double)(2), _state)-0.001, &xy2, &idx2, &nsections, _state);
ae_set_error_flag(errorflag, nsections!=3, __FILE__, __LINE__, "testparametricunit.ap:52");
if( nsections==3 )
{
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:55");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:56");
ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:57");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][0],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:58");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][1],(double)(2)), __FILE__, __LINE__, "testparametricunit.ap:59");
ae_set_error_flag(errorflag, idx2.ptr.p_int[1]!=1, __FILE__, __LINE__, "testparametricunit.ap:60");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][0],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:61");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][1],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:62");
ae_set_error_flag(errorflag, idx2.ptr.p_int[2]!=2, __FILE__, __LINE__, "testparametricunit.ap:63");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[3][0],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:64");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[3][1],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:65");
ae_set_error_flag(errorflag, idx2.ptr.p_int[3]!=3, __FILE__, __LINE__, "testparametricunit.ap:66");
}
parametricrdpfixed(&xy, 4, 2, 1, 0.0, &xy2, &idx2, &nsections, _state);
ae_set_error_flag(errorflag, nsections!=1, __FILE__, __LINE__, "testparametricunit.ap:69");
if( nsections==1 )
{
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:72");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:73");
ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:74");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][0],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:75");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][1],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:76");
ae_set_error_flag(errorflag, idx2.ptr.p_int[1]!=3, __FILE__, __LINE__, "testparametricunit.ap:77");
}
parametricrdpfixed(&xy, 4, 2, 2, 0.0, &xy2, &idx2, &nsections, _state);
ae_set_error_flag(errorflag, nsections!=2, __FILE__, __LINE__, "testparametricunit.ap:80");
if( nsections==2 )
{
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:83");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:84");
ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:85");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][0],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:86");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][1],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:87");
ae_set_error_flag(errorflag, idx2.ptr.p_int[1]!=2, __FILE__, __LINE__, "testparametricunit.ap:88");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][0],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:89");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][1],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:90");
ae_set_error_flag(errorflag, idx2.ptr.p_int[2]!=3, __FILE__, __LINE__, "testparametricunit.ap:91");
}
parametricrdpfixed(&xy, 4, 2, 3, 0.0, &xy2, &idx2, &nsections, _state);
ae_set_error_flag(errorflag, nsections!=3, __FILE__, __LINE__, "testparametricunit.ap:94");
if( nsections==3 )
{
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:97");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:98");
ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:99");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][0],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:100");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][1],(double)(2)), __FILE__, __LINE__, "testparametricunit.ap:101");
ae_set_error_flag(errorflag, idx2.ptr.p_int[1]!=1, __FILE__, __LINE__, "testparametricunit.ap:102");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][0],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:103");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][1],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:104");
ae_set_error_flag(errorflag, idx2.ptr.p_int[2]!=2, __FILE__, __LINE__, "testparametricunit.ap:105");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[3][0],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:106");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[3][1],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:107");
ae_set_error_flag(errorflag, idx2.ptr.p_int[3]!=3, __FILE__, __LINE__, "testparametricunit.ap:108");
}
parametricrdpfixed(&xy, 4, 2, 4, 0.0, &xy2, &idx2, &nsections, _state);
ae_set_error_flag(errorflag, nsections!=3, __FILE__, __LINE__, "testparametricunit.ap:111");
if( nsections==3 )
{
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:114");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:115");
ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:116");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][0],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:117");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][1],(double)(2)), __FILE__, __LINE__, "testparametricunit.ap:118");
ae_set_error_flag(errorflag, idx2.ptr.p_int[1]!=1, __FILE__, __LINE__, "testparametricunit.ap:119");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][0],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:120");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][1],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:121");
ae_set_error_flag(errorflag, idx2.ptr.p_int[2]!=2, __FILE__, __LINE__, "testparametricunit.ap:122");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[3][0],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:123");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[3][1],(double)(3)), __FILE__, __LINE__, "testparametricunit.ap:124");
ae_set_error_flag(errorflag, idx2.ptr.p_int[3]!=3, __FILE__, __LINE__, "testparametricunit.ap:125");
}
/*
* Parametric test 2: closed curve
*/
ae_matrix_set_length(&xy, 5, 2, _state);
xy.ptr.pp_double[0][0] = (double)(0);
xy.ptr.pp_double[0][1] = (double)(0);
xy.ptr.pp_double[1][0] = (double)(1);
xy.ptr.pp_double[1][1] = (double)(0);
xy.ptr.pp_double[2][0] = (double)(1);
xy.ptr.pp_double[2][1] = (double)(1);
xy.ptr.pp_double[3][0] = (double)(0);
xy.ptr.pp_double[3][1] = (double)(1);
xy.ptr.pp_double[4][0] = (double)(0);
xy.ptr.pp_double[4][1] = (double)(0);
parametricrdpfixed(&xy, 5, 2, 0, ae_sqrt((double)(2), _state)+0.001, &xy2, &idx2, &nsections, _state);
ae_set_error_flag(errorflag, nsections!=1, __FILE__, __LINE__, "testparametricunit.ap:144");
if( nsections==1 )
{
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:147");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:148");
ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:149");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:150");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:151");
ae_set_error_flag(errorflag, idx2.ptr.p_int[1]!=4, __FILE__, __LINE__, "testparametricunit.ap:152");
}
parametricrdpfixed(&xy, 5, 2, 0, ae_sqrt((double)(2), _state)-0.001, &xy2, &idx2, &nsections, _state);
ae_set_error_flag(errorflag, nsections!=2, __FILE__, __LINE__, "testparametricunit.ap:155");
if( nsections==2 )
{
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:158");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:159");
ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:160");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][0],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:161");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][1],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:162");
ae_set_error_flag(errorflag, idx2.ptr.p_int[1]!=2, __FILE__, __LINE__, "testparametricunit.ap:163");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:164");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:165");
ae_set_error_flag(errorflag, idx2.ptr.p_int[2]!=4, __FILE__, __LINE__, "testparametricunit.ap:166");
}
parametricrdpfixed(&xy, 5, 2, 0, ae_sqrt((double)(2), _state)/2+0.001, &xy2, &idx2, &nsections, _state);
ae_set_error_flag(errorflag, nsections!=2, __FILE__, __LINE__, "testparametricunit.ap:169");
if( nsections==2 )
{
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:172");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:173");
ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:174");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][0],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:175");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][1],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:176");
ae_set_error_flag(errorflag, idx2.ptr.p_int[1]!=2, __FILE__, __LINE__, "testparametricunit.ap:177");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:178");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:179");
ae_set_error_flag(errorflag, idx2.ptr.p_int[2]!=4, __FILE__, __LINE__, "testparametricunit.ap:180");
}
parametricrdpfixed(&xy, 5, 2, 0, ae_sqrt((double)(2), _state)/2-0.001, &xy2, &idx2, &nsections, _state);
ae_set_error_flag(errorflag, nsections!=4, __FILE__, __LINE__, "testparametricunit.ap:183");
if( nsections==4 )
{
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:186");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[0][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:187");
ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:188");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][0],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:189");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[1][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:190");
ae_set_error_flag(errorflag, idx2.ptr.p_int[1]!=1, __FILE__, __LINE__, "testparametricunit.ap:191");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][0],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:192");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[2][1],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:193");
ae_set_error_flag(errorflag, idx2.ptr.p_int[2]!=2, __FILE__, __LINE__, "testparametricunit.ap:194");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[3][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:195");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[3][1],(double)(1)), __FILE__, __LINE__, "testparametricunit.ap:196");
ae_set_error_flag(errorflag, idx2.ptr.p_int[3]!=3, __FILE__, __LINE__, "testparametricunit.ap:197");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[4][0],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:198");
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[4][1],(double)(0)), __FILE__, __LINE__, "testparametricunit.ap:199");
ae_set_error_flag(errorflag, idx2.ptr.p_int[4]!=4, __FILE__, __LINE__, "testparametricunit.ap:200");
}
/*
* Parametric, variable precision test (non-fixed), results are compared against fixed-section test
*/
eps = 10.0;
n = 100;
while(ae_fp_greater_eq(eps,0.0001))
{
/*
* Try different dimension counts
*/
for(d=1; d<=5; d++)
{
/*
* Generate dataset
*/
ae_matrix_set_length(&xy, n, d, _state);
for(i=0; i<=n-1; i++)
{
v = ae_pi*i/(n-1);
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][j] = ae_pow(ae_sin(v, _state), (double)(j+1), _state)+0.01*(hqrnduniformr(&rs, _state)-0.5);
}
}
/*
* Perform run of eps-based RDP algorithm
*/
parametricrdpfixed(&xy, n, d, 0, eps, &xy2, &idx2, &nsections, _state);
ae_set_error_flag(errorflag, nsections==0, __FILE__, __LINE__, "testparametricunit.ap:231");
if( nsections==0 )
{
ae_frame_leave(_state);
return;
}
/*
* Check properties
*/
ae_set_error_flag(errorflag, idx2.ptr.p_int[0]!=0, __FILE__, __LINE__, "testparametricunit.ap:238");
for(i=0; i<=nsections-1; i++)
{
ae_set_error_flag(errorflag, idx2.ptr.p_int[i]>=idx2.ptr.p_int[i+1], __FILE__, __LINE__, "testparametricunit.ap:240");
}
ae_set_error_flag(errorflag, idx2.ptr.p_int[nsections]!=n-1, __FILE__, __LINE__, "testparametricunit.ap:241");
for(i=0; i<=nsections; i++)
{
for(j=0; j<=d-1; j++)
{
ae_set_error_flag(errorflag, ae_fp_neq(xy2.ptr.pp_double[i][j],xy.ptr.pp_double[idx2.ptr.p_int[i]][j]), __FILE__, __LINE__, "testparametricunit.ap:244");
}
}
ae_vector_set_length(&x, nsections+1, _state);
ae_vector_set_length(&y, nsections+1, _state);
ae_vector_set_length(&e, n, _state);
for(i=0; i<=n-1; i++)
{
e.ptr.p_double[i] = (double)(0);
}
for(j=0; j<=d-1; j++)
{
for(i=0; i<=nsections; i++)
{
x.ptr.p_double[i] = (double)(idx2.ptr.p_int[i]);
y.ptr.p_double[i] = xy2.ptr.pp_double[i][j];
}
spline1dbuildlinear(&x, &y, nsections+1, &s, _state);
for(i=0; i<=n-1; i++)
{
e.ptr.p_double[i] = e.ptr.p_double[i]+ae_sqr(spline1dcalc(&s, (double)(i), _state)-xy.ptr.pp_double[i][j], _state);
}
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_sqrt(e.ptr.p_double[i], _state),eps), __FILE__, __LINE__, "testparametricunit.ap:262");
}
/*
* compare results with values returned by section-based algorithm
*/
parametricrdpfixed(&xy, n, d, nsections, 0.0, &xy3, &idx3, &nsections3, _state);
ae_set_error_flag(errorflag, nsections3!=nsections, __FILE__, __LINE__, "testparametricunit.ap:268");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=nsections; i++)
{
ae_set_error_flag(errorflag, idx2.ptr.p_int[i]!=idx3.ptr.p_int[i], __FILE__, __LINE__, "testparametricunit.ap:273");
for(j=0; j<=d-1; j++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xy2.ptr.pp_double[i][j]-xy3.ptr.pp_double[i][j], _state),1000*ae_machineepsilon), __FILE__, __LINE__, "testparametricunit.ap:275");
}
}
}
/*
* Next epsilon
*/
eps = eps*0.5;
}
ae_frame_leave(_state);
}
/*************************************************************************
Unset spline, i.e. initialize it with random garbage
*************************************************************************/
static void testparametricunit_unsetp2(pspline2interpolant* p,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix xy;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
_pspline2interpolant_clear(p);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_set_length(&xy, 2, 2, _state);
xy.ptr.pp_double[0][0] = (double)(-1);
xy.ptr.pp_double[0][1] = (double)(-1);
xy.ptr.pp_double[1][0] = (double)(1);
xy.ptr.pp_double[1][1] = (double)(1);
pspline2build(&xy, 2, 1, 0, p, _state);
ae_frame_leave(_state);
}
/*************************************************************************
Unset spline, i.e. initialize it with random garbage
*************************************************************************/
static void testparametricunit_unsetp3(pspline3interpolant* p,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix xy;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
_pspline3interpolant_clear(p);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_set_length(&xy, 2, 3, _state);
xy.ptr.pp_double[0][0] = (double)(-1);
xy.ptr.pp_double[0][1] = (double)(-1);
xy.ptr.pp_double[0][2] = (double)(-1);
xy.ptr.pp_double[1][0] = (double)(1);
xy.ptr.pp_double[1][1] = (double)(1);
xy.ptr.pp_double[1][2] = (double)(1);
pspline3build(&xy, 2, 1, 0, p, _state);
ae_frame_leave(_state);
}
static ae_bool testspline3dunit_basictest(ae_state *_state);
static ae_bool testspline3dunit_testunpack(ae_state *_state);
static ae_bool testspline3dunit_testlintrans(ae_state *_state);
static ae_bool testspline3dunit_testtrilinearresample(ae_state *_state);
static void testspline3dunit_buildrndgrid(ae_bool isvect,
ae_bool reorder,
ae_int_t* n,
ae_int_t* m,
ae_int_t* l,
ae_int_t* d,
/* Real */ ae_vector* x,
/* Real */ ae_vector* y,
/* Real */ ae_vector* z,
/* Real */ ae_vector* f,
ae_state *_state);
ae_bool testspline3d(ae_bool silence, ae_state *_state)
{
ae_bool waserrors;
ae_bool basicerr;
ae_bool unpackerr;
ae_bool lintransferr;
ae_bool trilinreserr;
ae_bool result;
basicerr = testspline3dunit_basictest(_state);
unpackerr = testspline3dunit_testunpack(_state);
lintransferr = testspline3dunit_testlintrans(_state);
trilinreserr = testspline3dunit_testtrilinearresample(_state);
waserrors = ((basicerr||unpackerr)||lintransferr)||trilinreserr;
if( !silence )
{
printf("TESTING 3D SPLINE\n");
printf("BASIC TEST: ");
if( basicerr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("UNPACK TEST: ");
if( unpackerr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("LIN_TRANSF TEST: ");
if( lintransferr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("TRILINEAR RESAMPLING TEST: ");
if( trilinreserr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
/*
* Summary
*/
if( waserrors )
{
printf("TEST FAILED");
}
else
{
printf("TEST PASSED");
}
printf("\n\n");
}
result = !waserrors;
return result;
}
/*************************************************************************
The function does test basic functionality.
*************************************************************************/
static ae_bool testspline3dunit_basictest(ae_state *_state)
{
ae_frame _frame_block;
spline3dinterpolant c;
spline3dinterpolant cc;
ae_vector vvf;
double vsf;
ae_int_t d;
ae_int_t m;
ae_int_t n;
ae_int_t l;
ae_vector x;
ae_vector y;
ae_vector z;
ae_vector sf;
ae_vector vf;
double eps;
ae_int_t pass;
ae_int_t passcount;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t offs;
ae_int_t di;
double ax;
double ay;
double az;
double axy;
double ayz;
double vx;
double vy;
double vz;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&c, 0, sizeof(c));
memset(&cc, 0, sizeof(cc));
memset(&vvf, 0, sizeof(vvf));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&z, 0, sizeof(z));
memset(&sf, 0, sizeof(sf));
memset(&vf, 0, sizeof(vf));
_spline3dinterpolant_init(&c, _state, ae_true);
_spline3dinterpolant_init(&cc, _state, ae_true);
ae_vector_init(&vvf, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&z, 0, DT_REAL, _state, ae_true);
ae_vector_init(&sf, 0, DT_REAL, _state, ae_true);
ae_vector_init(&vf, 0, DT_REAL, _state, ae_true);
eps = 1000*ae_machineepsilon;
/*
* Test spline ability to reproduce D-dimensional vector function
* f[idx](x,y,z) = idx+AX*x + AY*y + AZ*z + AXY*x*y + AYZ*y*z
* with random AX/AY/...
*
* We generate random test function, build spline, then evaluate
* it in the random test point.
*/
for(d=1; d<=3; d++)
{
n = 2+ae_randominteger(4, _state);
m = 2+ae_randominteger(4, _state);
l = 2+ae_randominteger(4, _state);
ae_vector_set_length(&x, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = (double)(i);
}
ae_vector_set_length(&y, m, _state);
for(i=0; i<=m-1; i++)
{
y.ptr.p_double[i] = (double)(i);
}
ae_vector_set_length(&z, l, _state);
for(i=0; i<=l-1; i++)
{
z.ptr.p_double[i] = (double)(i);
}
ae_vector_set_length(&vf, l*m*n*d, _state);
offs = 0;
ax = 2*ae_randomreal(_state)-1;
ay = 2*ae_randomreal(_state)-1;
az = 2*ae_randomreal(_state)-1;
axy = 2*ae_randomreal(_state)-1;
ayz = 2*ae_randomreal(_state)-1;
for(k=0; k<=l-1; k++)
{
for(j=0; j<=m-1; j++)
{
for(i=0; i<=n-1; i++)
{
for(di=0; di<=d-1; di++)
{
vf.ptr.p_double[offs] = di+ax*i+ay*j+az*k+axy*i*j+ayz*j*k;
offs = offs+1;
}
}
}
}
spline3dbuildtrilinearv(&x, n, &y, m, &z, l, &vf, d, &c, _state);
vx = ae_randomreal(_state)*n;
vy = ae_randomreal(_state)*m;
vz = ae_randomreal(_state)*l;
spline3dcalcv(&c, vx, vy, vz, &vf, _state);
for(di=0; di<=d-1; di++)
{
if( ae_fp_greater(ae_fabs(di+ax*vx+ay*vy+az*vz+axy*vx*vy+ayz*vy*vz-vf.ptr.p_double[di], _state),eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
if( d==1 )
{
vsf = spline3dcalc(&c, vx, vy, vz, _state);
if( ae_fp_greater(ae_fabs(ax*vx+ay*vy+az*vz+axy*vx*vy+ayz*vy*vz-vsf, _state),eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
/*
* Generate random grid and test function.
* Test spline ability to reproduce function values at grid nodes.
*/
passcount = 20;
for(pass=1; pass<=passcount; pass++)
{
/*
* Prepare a model and check that functions (Spline3DBuildTrilinear,
* Spline3DCalc,Spline3DCalcV) work correctly and
*/
testspline3dunit_buildrndgrid(ae_true, ae_true, &n, &m, &l, &d, &x, &y, &z, &vf, _state);
rvectorsetlengthatleast(&sf, n*m*l, _state);
/*
* Check that the model's values are equal to the function's values
* in grid points
*/
spline3dbuildtrilinearv(&x, n, &y, m, &z, l, &vf, d, &c, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
for(k=0; k<=l-1; k++)
{
spline3dcalcv(&c, x.ptr.p_double[i], y.ptr.p_double[j], z.ptr.p_double[k], &vvf, _state);
for(di=0; di<=d-1; di++)
{
if( ae_fp_greater(ae_fabs(vf.ptr.p_double[d*(n*(m*k+j)+i)+di]-vvf.ptr.p_double[di], _state),eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Unpack/UnpackV test
*************************************************************************/
static ae_bool testspline3dunit_testunpack(ae_state *_state)
{
ae_frame _frame_block;
spline3dinterpolant c;
ae_matrix tbl0;
ae_matrix tbl1;
ae_int_t n;
ae_int_t m;
ae_int_t l;
ae_int_t d;
ae_int_t sz;
ae_int_t un;
ae_int_t um;
ae_int_t ul;
ae_int_t ud;
ae_int_t ust;
ae_int_t uvn;
ae_int_t uvm;
ae_int_t uvl;
ae_int_t uvd;
ae_int_t uvst;
ae_int_t ci;
ae_int_t cj;
ae_int_t ck;
ae_vector x;
ae_vector y;
ae_vector z;
ae_vector sf;
ae_vector vf;
ae_int_t p0;
ae_int_t p1;
double tx;
double ty;
double tz;
double v1;
double v2;
double err;
ae_int_t pass;
ae_int_t passcount;
ae_bool bperr;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t di;
ae_int_t i0;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&c, 0, sizeof(c));
memset(&tbl0, 0, sizeof(tbl0));
memset(&tbl1, 0, sizeof(tbl1));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&z, 0, sizeof(z));
memset(&sf, 0, sizeof(sf));
memset(&vf, 0, sizeof(vf));
_spline3dinterpolant_init(&c, _state, ae_true);
ae_matrix_init(&tbl0, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&tbl1, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&z, 0, DT_REAL, _state, ae_true);
ae_vector_init(&sf, 0, DT_REAL, _state, ae_true);
ae_vector_init(&vf, 0, DT_REAL, _state, ae_true);
passcount = 20;
err = (double)(0);
for(pass=1; pass<=passcount; pass++)
{
/*
* generate random grid.
* NOTE: for this test we need ordered grid, i.e. grid
* with nodes in ascending order
*/
testspline3dunit_buildrndgrid(ae_true, ae_false, &n, &m, &l, &d, &x, &y, &z, &vf, _state);
sz = n*m*l;
rvectorsetlengthatleast(&sf, sz, _state);
spline3dbuildtrilinearv(&x, n, &y, m, &z, l, &vf, d, &c, _state);
spline3dunpackv(&c, &uvn, &uvm, &uvl, &uvd, &uvst, &tbl0, _state);
for(di=0; di<=d-1; di++)
{
/*
* DI-th component copy of a vector-function to
* a scalar function
*/
for(i=0; i<=sz-1; i++)
{
sf.ptr.p_double[i] = vf.ptr.p_double[d*i+di];
}
spline3dbuildtrilinearv(&x, n, &y, m, &z, l, &sf, 1, &c, _state);
spline3dunpackv(&c, &un, &um, &ul, &ud, &ust, &tbl1, _state);
for(i=0; i<=n-2; i++)
{
for(j=0; j<=m-2; j++)
{
for(k=0; k<=l-2; k++)
{
p1 = (n-1)*((m-1)*k+j)+i;
p0 = d*p1+di;
/*
* Check that all components are correct:
* *first check, that unpacked componets are equal
* to packed components;
*/
bperr = (((((((((((((((((un!=n||um!=m)||ul!=l)||ae_fp_neq(tbl1.ptr.pp_double[p1][0],x.ptr.p_double[i]))||ae_fp_neq(tbl1.ptr.pp_double[p1][1],x.ptr.p_double[i+1]))||ae_fp_neq(tbl1.ptr.pp_double[p1][2],y.ptr.p_double[j]))||ae_fp_neq(tbl1.ptr.pp_double[p1][3],y.ptr.p_double[j+1]))||ae_fp_neq(tbl1.ptr.pp_double[p1][4],z.ptr.p_double[k]))||ae_fp_neq(tbl1.ptr.pp_double[p1][5],z.ptr.p_double[k+1]))||uvn!=n)||uvm!=m)||uvl!=l)||uvd!=d)||ae_fp_neq(tbl0.ptr.pp_double[p0][0],x.ptr.p_double[i]))||ae_fp_neq(tbl0.ptr.pp_double[p0][1],x.ptr.p_double[i+1]))||ae_fp_neq(tbl0.ptr.pp_double[p0][2],y.ptr.p_double[j]))||ae_fp_neq(tbl0.ptr.pp_double[p0][3],y.ptr.p_double[j+1]))||ae_fp_neq(tbl0.ptr.pp_double[p0][4],z.ptr.p_double[k]))||ae_fp_neq(tbl0.ptr.pp_double[p0][5],z.ptr.p_double[k+1]);
/*
* *check, that all components unpacked by Unpack
* function are equal to all components unpacked
* by UnpackV function.
*/
for(i0=0; i0<=13; i0++)
{
bperr = bperr||ae_fp_neq(tbl0.ptr.pp_double[p0][i0],tbl1.ptr.pp_double[p1][i0]);
}
if( bperr )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
tx = (0.001+0.999*ae_randomreal(_state))*(tbl1.ptr.pp_double[p1][1]-tbl1.ptr.pp_double[p1][0]);
ty = (0.001+0.999*ae_randomreal(_state))*(tbl1.ptr.pp_double[p1][3]-tbl1.ptr.pp_double[p1][2]);
tz = (0.001+0.999*ae_randomreal(_state))*(tbl1.ptr.pp_double[p1][5]-tbl1.ptr.pp_double[p1][4]);
/*
* Interpolation properties for:
* *scalar function;
*/
v1 = (double)(0);
for(ci=0; ci<=1; ci++)
{
for(cj=0; cj<=1; cj++)
{
for(ck=0; ck<=1; ck++)
{
v1 = v1+tbl1.ptr.pp_double[p1][6+2*(2*ck+cj)+ci]*ae_pow(tx, (double)(ci), _state)*ae_pow(ty, (double)(cj), _state)*ae_pow(tz, (double)(ck), _state);
}
}
}
v2 = spline3dcalc(&c, tbl1.ptr.pp_double[p1][0]+tx, tbl1.ptr.pp_double[p1][2]+ty, tbl1.ptr.pp_double[p1][4]+tz, _state);
err = ae_maxreal(err, ae_fabs(v1-v2, _state), _state);
/*
* *component of vector function.
*/
v1 = (double)(0);
for(ci=0; ci<=1; ci++)
{
for(cj=0; cj<=1; cj++)
{
for(ck=0; ck<=1; ck++)
{
v1 = v1+tbl0.ptr.pp_double[p0][6+2*(2*ck+cj)+ci]*ae_pow(tx, (double)(ci), _state)*ae_pow(ty, (double)(cj), _state)*ae_pow(tz, (double)(ck), _state);
}
}
}
v2 = spline3dcalc(&c, tbl0.ptr.pp_double[p0][0]+tx, tbl0.ptr.pp_double[p0][2]+ty, tbl0.ptr.pp_double[p0][4]+tz, _state);
err = ae_maxreal(err, ae_fabs(v1-v2, _state), _state);
}
}
}
}
}
result = ae_fp_greater(err,1.0E+5*ae_machineepsilon);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
LinTrans test
*************************************************************************/
static ae_bool testspline3dunit_testlintrans(ae_state *_state)
{
ae_frame _frame_block;
spline3dinterpolant c;
spline3dinterpolant c2;
ae_int_t m;
ae_int_t n;
ae_int_t l;
ae_int_t d;
ae_vector x;
ae_vector y;
ae_vector z;
ae_vector f;
double a1;
double a2;
double a3;
double b1;
double b2;
double b3;
double tx;
double ty;
double tz;
double vx;
double vy;
double vz;
ae_vector v1;
ae_vector v2;
ae_int_t pass;
ae_int_t passcount;
ae_int_t xjob;
ae_int_t yjob;
ae_int_t zjob;
double err;
ae_int_t i;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&c, 0, sizeof(c));
memset(&c2, 0, sizeof(c2));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&z, 0, sizeof(z));
memset(&f, 0, sizeof(f));
memset(&v1, 0, sizeof(v1));
memset(&v2, 0, sizeof(v2));
_spline3dinterpolant_init(&c, _state, ae_true);
_spline3dinterpolant_init(&c2, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&z, 0, DT_REAL, _state, ae_true);
ae_vector_init(&f, 0, DT_REAL, _state, ae_true);
ae_vector_init(&v1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&v2, 0, DT_REAL, _state, ae_true);
err = (double)(0);
passcount = 15;
for(pass=1; pass<=passcount; pass++)
{
testspline3dunit_buildrndgrid(ae_true, ae_false, &n, &m, &l, &d, &x, &y, &z, &f, _state);
spline3dbuildtrilinearv(&x, n, &y, m, &z, l, &f, d, &c, _state);
for(xjob=0; xjob<=1; xjob++)
{
for(yjob=0; yjob<=1; yjob++)
{
for(zjob=0; zjob<=1; zjob++)
{
/*
* Prepare
*/
do
{
a1 = 2.0*ae_randomreal(_state)-1.0;
}
while(ae_fp_eq(a1,(double)(0)));
a1 = a1*xjob;
b1 = x.ptr.p_double[0]+ae_randomreal(_state)*(x.ptr.p_double[n-1]-x.ptr.p_double[0]+2.0)-1.0;
do
{
a2 = 2.0*ae_randomreal(_state)-1.0;
}
while(ae_fp_eq(a2,(double)(0)));
a2 = a2*yjob;
b2 = y.ptr.p_double[0]+ae_randomreal(_state)*(y.ptr.p_double[m-1]-y.ptr.p_double[0]+2.0)-1.0;
do
{
a3 = 2.0*ae_randomreal(_state)-1.0;
}
while(ae_fp_eq(a3,(double)(0)));
a3 = a3*zjob;
b3 = z.ptr.p_double[0]+ae_randomreal(_state)*(z.ptr.p_double[l-1]-z.ptr.p_double[0]+2.0)-1.0;
/*
* Test XYZ
*/
spline3dcopy(&c, &c2, _state);
spline3dlintransxyz(&c2, a1, b1, a2, b2, a3, b3, _state);
tx = x.ptr.p_double[0]+ae_randomreal(_state)*(x.ptr.p_double[n-1]-x.ptr.p_double[0]);
ty = y.ptr.p_double[0]+ae_randomreal(_state)*(y.ptr.p_double[m-1]-y.ptr.p_double[0]);
tz = z.ptr.p_double[0]+ae_randomreal(_state)*(z.ptr.p_double[l-1]-z.ptr.p_double[0]);
if( xjob==0 )
{
tx = b1;
vx = x.ptr.p_double[0]+ae_randomreal(_state)*(x.ptr.p_double[n-1]-x.ptr.p_double[0]);
}
else
{
vx = (tx-b1)/a1;
}
if( yjob==0 )
{
ty = b2;
vy = y.ptr.p_double[0]+ae_randomreal(_state)*(y.ptr.p_double[m-1]-y.ptr.p_double[0]);
}
else
{
vy = (ty-b2)/a2;
}
if( zjob==0 )
{
tz = b3;
vz = z.ptr.p_double[0]+ae_randomreal(_state)*(z.ptr.p_double[l-1]-z.ptr.p_double[0]);
}
else
{
vz = (tz-b3)/a3;
}
spline3dcalcv(&c, tx, ty, tz, &v1, _state);
spline3dcalcv(&c2, vx, vy, vz, &v2, _state);
for(i=0; i<=d-1; i++)
{
err = ae_maxreal(err, ae_fabs(v1.ptr.p_double[i]-v2.ptr.p_double[i], _state), _state);
}
if( ae_fp_greater(err,1.0E+4*ae_machineepsilon) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
/*
* Test F
*/
spline3dcopy(&c, &c2, _state);
spline3dlintransf(&c2, a1, b1, _state);
tx = x.ptr.p_double[0]+ae_randomreal(_state)*(x.ptr.p_double[n-1]-x.ptr.p_double[0]);
ty = y.ptr.p_double[0]+ae_randomreal(_state)*(y.ptr.p_double[m-1]-y.ptr.p_double[0]);
tz = z.ptr.p_double[0]+ae_randomreal(_state)*(z.ptr.p_double[l-1]-z.ptr.p_double[0]);
spline3dcalcv(&c, tx, ty, tz, &v1, _state);
spline3dcalcv(&c2, tx, ty, tz, &v2, _state);
for(i=0; i<=d-1; i++)
{
err = ae_maxreal(err, ae_fabs(a1*v1.ptr.p_double[i]+b1-v2.ptr.p_double[i], _state), _state);
}
}
}
}
}
result = ae_fp_greater(err,1.0E+4*ae_machineepsilon);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Resample test
*************************************************************************/
static ae_bool testspline3dunit_testtrilinearresample(ae_state *_state)
{
ae_frame _frame_block;
spline3dinterpolant c;
ae_int_t n;
ae_int_t m;
ae_int_t l;
ae_int_t n2;
ae_int_t m2;
ae_int_t l2;
ae_vector x;
ae_vector y;
ae_vector z;
ae_vector f;
ae_vector fr;
double v1;
double v2;
double err;
double mf;
ae_int_t pass;
ae_int_t passcount;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&c, 0, sizeof(c));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&z, 0, sizeof(z));
memset(&f, 0, sizeof(f));
memset(&fr, 0, sizeof(fr));
_spline3dinterpolant_init(&c, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&z, 0, DT_REAL, _state, ae_true);
ae_vector_init(&f, 0, DT_REAL, _state, ae_true);
ae_vector_init(&fr, 0, DT_REAL, _state, ae_true);
result = ae_false;
passcount = 20;
for(pass=1; pass<=passcount; pass++)
{
n = ae_randominteger(4, _state)+2;
m = ae_randominteger(4, _state)+2;
l = ae_randominteger(4, _state)+2;
n2 = ae_randominteger(4, _state)+2;
m2 = ae_randominteger(4, _state)+2;
l2 = ae_randominteger(4, _state)+2;
rvectorsetlengthatleast(&x, n, _state);
rvectorsetlengthatleast(&y, m, _state);
rvectorsetlengthatleast(&z, l, _state);
rvectorsetlengthatleast(&f, n*m*l, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = (double)i/(double)(n-1);
}
for(i=0; i<=m-1; i++)
{
y.ptr.p_double[i] = (double)i/(double)(m-1);
}
for(i=0; i<=l-1; i++)
{
z.ptr.p_double[i] = (double)i/(double)(l-1);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
for(k=0; k<=l-1; k++)
{
f.ptr.p_double[n*(m*k+j)+i] = 2*ae_randomreal(_state)-1;
}
}
}
spline3dresampletrilinear(&f, l, m, n, l2, m2, n2, &fr, _state);
spline3dbuildtrilinearv(&x, n, &y, m, &z, l, &f, 1, &c, _state);
err = (double)(0);
mf = (double)(0);
for(i=0; i<=n2-1; i++)
{
for(j=0; j<=m2-1; j++)
{
for(k=0; k<=l2-1; k++)
{
v1 = spline3dcalc(&c, (double)i/(double)(n2-1), (double)j/(double)(m2-1), (double)k/(double)(l2-1), _state);
v2 = fr.ptr.p_double[n2*(m2*k+j)+i];
err = ae_maxreal(err, ae_fabs(v1-v2, _state), _state);
mf = ae_maxreal(mf, ae_fabs(v1, _state), _state);
}
}
}
result = result||ae_fp_greater(err/mf,1.0E+4*ae_machineepsilon);
if( result )
{
ae_frame_leave(_state);
return result;
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
The function does build random function on random grid with random number
of points:
* N, M, K - random from 2 to 5
* D - 1 in case IsVect=False, 1..3 in case IsVect=True
* X, Y, Z - each variable spans from MinV to MaxV, with MinV is random
number from [-1.5,0.5] and MaxV is random number from
[0.5,1.5]. All nodes are well separated. All nodes are
randomly reordered in case Reorder=False. When Reorder=True,
nodes are returned in ascending order.
* F - random values from [-1,+1]
*************************************************************************/
static void testspline3dunit_buildrndgrid(ae_bool isvect,
ae_bool reorder,
ae_int_t* n,
ae_int_t* m,
ae_int_t* l,
ae_int_t* d,
/* Real */ ae_vector* x,
/* Real */ ae_vector* y,
/* Real */ ae_vector* z,
/* Real */ ae_vector* f,
ae_state *_state)
{
double st;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t di;
double v;
double mx;
double maxv;
double minv;
*n = 0;
*m = 0;
*l = 0;
*d = 0;
ae_vector_clear(x);
ae_vector_clear(y);
ae_vector_clear(z);
ae_vector_clear(f);
st = 0.3;
*m = ae_randominteger(4, _state)+2;
*n = ae_randominteger(4, _state)+2;
*l = ae_randominteger(4, _state)+2;
if( isvect )
{
*d = ae_randominteger(3, _state)+1;
}
else
{
*d = 1;
}
rvectorsetlengthatleast(x, *n, _state);
rvectorsetlengthatleast(y, *m, _state);
rvectorsetlengthatleast(z, *l, _state);
rvectorsetlengthatleast(f, *n*(*m)*(*l)*(*d), _state);
/*
* Fill X
*/
x->ptr.p_double[0] = (double)(0);
for(i=1; i<=*n-1; i++)
{
x->ptr.p_double[i] = x->ptr.p_double[i-1]+st+ae_randomreal(_state);
}
minv = -0.5-ae_randomreal(_state);
maxv = 0.5+ae_randomreal(_state);
mx = x->ptr.p_double[*n-1];
for(i=0; i<=*n-1; i++)
{
x->ptr.p_double[i] = x->ptr.p_double[i]/mx*(maxv-minv)+minv;
}
if( reorder )
{
for(i=0; i<=*n-1; i++)
{
k = ae_randominteger(*n, _state);
v = x->ptr.p_double[i];
x->ptr.p_double[i] = x->ptr.p_double[k];
x->ptr.p_double[k] = v;
}
}
/*
* Fill Y
*/
y->ptr.p_double[0] = (double)(0);
for(i=1; i<=*m-1; i++)
{
y->ptr.p_double[i] = y->ptr.p_double[i-1]+st+ae_randomreal(_state);
}
minv = -0.5-ae_randomreal(_state);
maxv = 0.5+ae_randomreal(_state);
mx = y->ptr.p_double[*m-1];
for(i=0; i<=*m-1; i++)
{
y->ptr.p_double[i] = y->ptr.p_double[i]/mx*(maxv-minv)+minv;
}
if( reorder )
{
for(i=0; i<=*m-1; i++)
{
k = ae_randominteger(*m, _state);
v = y->ptr.p_double[i];
y->ptr.p_double[i] = y->ptr.p_double[k];
y->ptr.p_double[k] = v;
}
}
/*
* Fill Z
*/
z->ptr.p_double[0] = (double)(0);
for(i=1; i<=*l-1; i++)
{
z->ptr.p_double[i] = z->ptr.p_double[i-1]+st+ae_randomreal(_state);
}
minv = -0.5-ae_randomreal(_state);
maxv = 0.5+ae_randomreal(_state);
mx = z->ptr.p_double[*l-1];
for(i=0; i<=*l-1; i++)
{
z->ptr.p_double[i] = z->ptr.p_double[i]/mx*(maxv-minv)+minv;
}
if( reorder )
{
for(i=0; i<=*l-1; i++)
{
k = ae_randominteger(*l, _state);
v = z->ptr.p_double[i];
z->ptr.p_double[i] = z->ptr.p_double[k];
z->ptr.p_double[k] = v;
}
}
/*
* Fill F
*/
for(i=0; i<=*n-1; i++)
{
for(j=0; j<=*m-1; j++)
{
for(k=0; k<=*l-1; k++)
{
for(di=0; di<=*d-1; di++)
{
f->ptr.p_double[*d*(*n*(*m*k+j)+i)+di] = 2*ae_randomreal(_state)-1;
}
}
}
}
}
static double testpolintunit_internalpolint(/* Real */ ae_vector* x,
/* Real */ ae_vector* f,
ae_int_t n,
double t,
ae_state *_state);
static void testpolintunit_brcunset(barycentricinterpolant* b,
ae_state *_state);
/*************************************************************************
Unit test
*************************************************************************/
ae_bool testpolint(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_bool waserrors;
ae_bool interrors;
double threshold;
ae_vector x;
ae_vector y;
ae_vector w;
ae_vector c;
ae_vector c0;
ae_vector c1;
ae_vector c2;
ae_vector x2;
ae_vector y2;
ae_vector w2;
ae_vector xfull;
ae_vector yfull;
double a;
double b;
double t;
ae_int_t i;
ae_int_t k;
ae_vector xc;
ae_vector yc;
ae_vector dc;
double v;
double v0;
double v1;
double v2;
double v3;
double v4;
double pscale;
double poffset;
double eps;
barycentricinterpolant p;
barycentricinterpolant p1;
barycentricinterpolant p2;
ae_int_t n;
ae_int_t maxn;
ae_int_t pass;
ae_int_t passcount;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&w, 0, sizeof(w));
memset(&c, 0, sizeof(c));
memset(&c0, 0, sizeof(c0));
memset(&c1, 0, sizeof(c1));
memset(&c2, 0, sizeof(c2));
memset(&x2, 0, sizeof(x2));
memset(&y2, 0, sizeof(y2));
memset(&w2, 0, sizeof(w2));
memset(&xfull, 0, sizeof(xfull));
memset(&yfull, 0, sizeof(yfull));
memset(&xc, 0, sizeof(xc));
memset(&yc, 0, sizeof(yc));
memset(&dc, 0, sizeof(dc));
memset(&p, 0, sizeof(p));
memset(&p1, 0, sizeof(p1));
memset(&p2, 0, sizeof(p2));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
ae_vector_init(&c, 0, DT_REAL, _state, ae_true);
ae_vector_init(&c0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&c1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&c2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xfull, 0, DT_REAL, _state, ae_true);
ae_vector_init(&yfull, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&yc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&dc, 0, DT_INT, _state, ae_true);
_barycentricinterpolant_init(&p, _state, ae_true);
_barycentricinterpolant_init(&p1, _state, ae_true);
_barycentricinterpolant_init(&p2, _state, ae_true);
waserrors = ae_false;
interrors = ae_false;
maxn = 5;
passcount = 20;
threshold = 1.0E8*ae_machineepsilon;
/*
* Test equidistant interpolation
*/
for(pass=1; pass<=passcount; pass++)
{
for(n=1; n<=maxn; n++)
{
/*
* prepare task:
* * equidistant points
* * random Y
* * T in [A,B] or near (within 10% of its width)
*/
do
{
a = 2*ae_randomreal(_state)-1;
b = 2*ae_randomreal(_state)-1;
}
while(ae_fp_less_eq(ae_fabs(a-b, _state),0.2));
t = a+(1.2*ae_randomreal(_state)-0.1)*(b-a);
taskgenint1dequidist(a, b, n, &x, &y, _state);
/*
* test "fast" equidistant interpolation (no barycentric model)
*/
interrors = interrors||ae_fp_greater(ae_fabs(polynomialcalceqdist(a, b, &y, n, t, _state)-testpolintunit_internalpolint(&x, &y, n, t, _state), _state),threshold);
/*
* test "slow" equidistant interpolation (create barycentric model)
*/
testpolintunit_brcunset(&p, _state);
polynomialbuild(&x, &y, n, &p, _state);
interrors = interrors||ae_fp_greater(ae_fabs(barycentriccalc(&p, t, _state)-testpolintunit_internalpolint(&x, &y, n, t, _state), _state),threshold);
/*
* test "fast" interpolation (create "fast" barycentric model)
*/
testpolintunit_brcunset(&p, _state);
polynomialbuildeqdist(a, b, &y, n, &p, _state);
interrors = interrors||ae_fp_greater(ae_fabs(barycentriccalc(&p, t, _state)-testpolintunit_internalpolint(&x, &y, n, t, _state), _state),threshold);
}
}
/*
* Test Chebyshev-1 interpolation
*/
for(pass=1; pass<=passcount; pass++)
{
for(n=1; n<=maxn; n++)
{
/*
* prepare task:
* * equidistant points
* * random Y
* * T in [A,B] or near (within 10% of its width)
*/
do
{
a = 2*ae_randomreal(_state)-1;
b = 2*ae_randomreal(_state)-1;
}
while(ae_fp_less_eq(ae_fabs(a-b, _state),0.2));
t = a+(1.2*ae_randomreal(_state)-0.1)*(b-a);
taskgenint1dcheb1(a, b, n, &x, &y, _state);
/*
* test "fast" interpolation (no barycentric model)
*/
interrors = interrors||ae_fp_greater(ae_fabs(polynomialcalccheb1(a, b, &y, n, t, _state)-testpolintunit_internalpolint(&x, &y, n, t, _state), _state),threshold);
/*
* test "slow" interpolation (create barycentric model)
*/
testpolintunit_brcunset(&p, _state);
polynomialbuild(&x, &y, n, &p, _state);
interrors = interrors||ae_fp_greater(ae_fabs(barycentriccalc(&p, t, _state)-testpolintunit_internalpolint(&x, &y, n, t, _state), _state),threshold);
/*
* test "fast" interpolation (create "fast" barycentric model)
*/
testpolintunit_brcunset(&p, _state);
polynomialbuildcheb1(a, b, &y, n, &p, _state);
interrors = interrors||ae_fp_greater(ae_fabs(barycentriccalc(&p, t, _state)-testpolintunit_internalpolint(&x, &y, n, t, _state), _state),threshold);
}
}
/*
* Test Chebyshev-2 interpolation
*/
for(pass=1; pass<=passcount; pass++)
{
for(n=1; n<=maxn; n++)
{
/*
* prepare task:
* * equidistant points
* * random Y
* * T in [A,B] or near (within 10% of its width)
*/
do
{
a = 2*ae_randomreal(_state)-1;
b = 2*ae_randomreal(_state)-1;
}
while(ae_fp_less_eq(ae_fabs(a-b, _state),0.2));
t = a+(1.2*ae_randomreal(_state)-0.1)*(b-a);
taskgenint1dcheb2(a, b, n, &x, &y, _state);
/*
* test "fast" interpolation (no barycentric model)
*/
interrors = interrors||ae_fp_greater(ae_fabs(polynomialcalccheb2(a, b, &y, n, t, _state)-testpolintunit_internalpolint(&x, &y, n, t, _state), _state),threshold);
/*
* test "slow" interpolation (create barycentric model)
*/
testpolintunit_brcunset(&p, _state);
polynomialbuild(&x, &y, n, &p, _state);
interrors = interrors||ae_fp_greater(ae_fabs(barycentriccalc(&p, t, _state)-testpolintunit_internalpolint(&x, &y, n, t, _state), _state),threshold);
/*
* test "fast" interpolation (create "fast" barycentric model)
*/
testpolintunit_brcunset(&p, _state);
polynomialbuildcheb2(a, b, &y, n, &p, _state);
interrors = interrors||ae_fp_greater(ae_fabs(barycentriccalc(&p, t, _state)-testpolintunit_internalpolint(&x, &y, n, t, _state), _state),threshold);
}
}
/*
* Testing conversion Barycentric<->Chebyshev
*/
for(pass=1; pass<=passcount; pass++)
{
for(k=1; k<=3; k++)
{
/*
* Allocate
*/
ae_vector_set_length(&x, k, _state);
ae_vector_set_length(&y, k, _state);
/*
* Generate problem
*/
a = 2*ae_randomreal(_state)-1;
b = a+(0.1+ae_randomreal(_state))*(2*ae_randominteger(2, _state)-1);
v0 = 2*ae_randomreal(_state)-1;
v1 = 2*ae_randomreal(_state)-1;
v2 = 2*ae_randomreal(_state)-1;
if( k==1 )
{
x.ptr.p_double[0] = 0.5*(a+b);
y.ptr.p_double[0] = v0;
}
if( k==2 )
{
x.ptr.p_double[0] = a;
y.ptr.p_double[0] = v0-v1;
x.ptr.p_double[1] = b;
y.ptr.p_double[1] = v0+v1;
}
if( k==3 )
{
x.ptr.p_double[0] = a;
y.ptr.p_double[0] = v0-v1+v2;
x.ptr.p_double[1] = 0.5*(a+b);
y.ptr.p_double[1] = v0-v2;
x.ptr.p_double[2] = b;
y.ptr.p_double[2] = v0+v1+v2;
}
/*
* Test forward conversion
*/
polynomialbuild(&x, &y, k, &p, _state);
ae_vector_set_length(&c, 1, _state);
polynomialbar2cheb(&p, a, b, &c, _state);
interrors = interrors||c.cnt!=k;
if( k>=1 )
{
interrors = interrors||ae_fp_greater(ae_fabs(c.ptr.p_double[0]-v0, _state),threshold);
}
if( k>=2 )
{
interrors = interrors||ae_fp_greater(ae_fabs(c.ptr.p_double[1]-v1, _state),threshold);
}
if( k>=3 )
{
interrors = interrors||ae_fp_greater(ae_fabs(c.ptr.p_double[2]-v2, _state),threshold);
}
/*
* Test backward conversion
*/
polynomialcheb2bar(&c, k, a, b, &p2, _state);
v = a+ae_randomreal(_state)*(b-a);
interrors = interrors||ae_fp_greater(ae_fabs(barycentriccalc(&p, v, _state)-barycentriccalc(&p2, v, _state), _state),threshold);
}
}
/*
* Testing conversion Barycentric<->Power
*/
for(pass=1; pass<=passcount; pass++)
{
for(k=1; k<=5; k++)
{
/*
* Allocate
*/
ae_vector_set_length(&x, k, _state);
ae_vector_set_length(&y, k, _state);
/*
* Generate problem
*/
poffset = 2*ae_randomreal(_state)-1;
pscale = (0.1+ae_randomreal(_state))*(2*ae_randominteger(2, _state)-1);
v0 = 2*ae_randomreal(_state)-1;
v1 = 2*ae_randomreal(_state)-1;
v2 = 2*ae_randomreal(_state)-1;
v3 = 2*ae_randomreal(_state)-1;
v4 = 2*ae_randomreal(_state)-1;
if( k==1 )
{
x.ptr.p_double[0] = poffset;
y.ptr.p_double[0] = v0;
}
if( k==2 )
{
x.ptr.p_double[0] = poffset-pscale;
y.ptr.p_double[0] = v0-v1;
x.ptr.p_double[1] = poffset+pscale;
y.ptr.p_double[1] = v0+v1;
}
if( k==3 )
{
x.ptr.p_double[0] = poffset-pscale;
y.ptr.p_double[0] = v0-v1+v2;
x.ptr.p_double[1] = poffset;
y.ptr.p_double[1] = v0;
x.ptr.p_double[2] = poffset+pscale;
y.ptr.p_double[2] = v0+v1+v2;
}
if( k==4 )
{
x.ptr.p_double[0] = poffset-pscale;
y.ptr.p_double[0] = v0-v1+v2-v3;
x.ptr.p_double[1] = poffset-0.5*pscale;
y.ptr.p_double[1] = v0-0.5*v1+0.25*v2-0.125*v3;
x.ptr.p_double[2] = poffset+0.5*pscale;
y.ptr.p_double[2] = v0+0.5*v1+0.25*v2+0.125*v3;
x.ptr.p_double[3] = poffset+pscale;
y.ptr.p_double[3] = v0+v1+v2+v3;
}
if( k==5 )
{
x.ptr.p_double[0] = poffset-pscale;
y.ptr.p_double[0] = v0-v1+v2-v3+v4;
x.ptr.p_double[1] = poffset-0.5*pscale;
y.ptr.p_double[1] = v0-0.5*v1+0.25*v2-0.125*v3+0.0625*v4;
x.ptr.p_double[2] = poffset;
y.ptr.p_double[2] = v0;
x.ptr.p_double[3] = poffset+0.5*pscale;
y.ptr.p_double[3] = v0+0.5*v1+0.25*v2+0.125*v3+0.0625*v4;
x.ptr.p_double[4] = poffset+pscale;
y.ptr.p_double[4] = v0+v1+v2+v3+v4;
}
/*
* Test forward conversion
*/
polynomialbuild(&x, &y, k, &p, _state);
ae_vector_set_length(&c, 1, _state);
polynomialbar2pow(&p, poffset, pscale, &c, _state);
interrors = interrors||c.cnt!=k;
if( k>=1 )
{
interrors = interrors||ae_fp_greater(ae_fabs(c.ptr.p_double[0]-v0, _state),threshold);
}
if( k>=2 )
{
interrors = interrors||ae_fp_greater(ae_fabs(c.ptr.p_double[1]-v1, _state),threshold);
}
if( k>=3 )
{
interrors = interrors||ae_fp_greater(ae_fabs(c.ptr.p_double[2]-v2, _state),threshold);
}
if( k>=4 )
{
interrors = interrors||ae_fp_greater(ae_fabs(c.ptr.p_double[3]-v3, _state),threshold);
}
if( k>=5 )
{
interrors = interrors||ae_fp_greater(ae_fabs(c.ptr.p_double[4]-v4, _state),threshold);
}
/*
* Test backward conversion
*/
polynomialpow2bar(&c, k, poffset, pscale, &p2, _state);
v = poffset+(2*ae_randomreal(_state)-1)*pscale;
interrors = interrors||ae_fp_greater(ae_fabs(barycentriccalc(&p, v, _state)-barycentriccalc(&p2, v, _state), _state),threshold);
}
}
/*
* crash-test: ability to solve tasks which will overflow/underflow
* weights with straightforward implementation
*/
for(n=1; n<=20; n++)
{
a = -0.1*ae_maxrealnumber;
b = 0.1*ae_maxrealnumber;
taskgenint1dequidist(a, b, n, &x, &y, _state);
polynomialbuild(&x, &y, n, &p, _state);
for(i=0; i<=n-1; i++)
{
interrors = interrors||ae_fp_eq(p.w.ptr.p_double[i],(double)(0));
}
}
/*
* Test issue #634: instability in PolynomialBar2Pow().
*
* Function returns incorrect coefficients when called with
* approximately-unit scale for data which have significantly
* non-unit scale.
*/
n = 7;
eps = 1.0E-8;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&x2, n, _state);
ae_vector_set_length(&y, n, _state);
x.ptr.p_double[0] = ae_randomreal(_state)-0.5;
y.ptr.p_double[0] = ae_randomreal(_state)-0.5;
for(i=1; i<=n-1; i++)
{
x.ptr.p_double[i] = x.ptr.p_double[i-1]+ae_randomreal(_state)+0.1;
y.ptr.p_double[i] = ae_randomreal(_state)-0.5;
}
polynomialbuild(&x, &y, n, &p, _state);
polynomialbar2pow(&p, 0.0, 1.0, &c0, _state);
pscale = 1.0E-10;
for(i=0; i<=n-1; i++)
{
x2.ptr.p_double[i] = x.ptr.p_double[i]*pscale;
}
polynomialbuild(&x2, &y, n, &p, _state);
polynomialbar2pow(&p, 0.0, 1.0, &c1, _state);
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(&interrors, ae_fp_greater(ae_fabs(c0.ptr.p_double[i]-c1.ptr.p_double[i]*ae_pow(pscale, (double)(i), _state), _state),eps), __FILE__, __LINE__, "testpolintunit.ap:395");
}
pscale = 1.0E10;
for(i=0; i<=n-1; i++)
{
x2.ptr.p_double[i] = x.ptr.p_double[i]*pscale;
}
polynomialbuild(&x2, &y, n, &p, _state);
polynomialbar2pow(&p, 0.0, 1.0, &c2, _state);
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(&interrors, ae_fp_greater(ae_fabs(c0.ptr.p_double[i]-c2.ptr.p_double[i]*ae_pow(pscale, (double)(i), _state), _state),eps), __FILE__, __LINE__, "testpolintunit.ap:402");
}
/*
* report
*/
waserrors = interrors;
if( !silent )
{
printf("TESTING POLYNOMIAL INTERPOLATION\n");
/*
* Normal tests
*/
printf("INTERPOLATION TEST: ");
if( interrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
/*
* end
*/
result = !waserrors;
ae_frame_leave(_state);
return result;
}
static double testpolintunit_internalpolint(/* Real */ ae_vector* x,
/* Real */ ae_vector* f,
ae_int_t n,
double t,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector _f;
ae_int_t i;
ae_int_t j;
double result;
ae_frame_make(_state, &_frame_block);
memset(&_f, 0, sizeof(_f));
ae_vector_init_copy(&_f, f, _state, ae_true);
f = &_f;
n = n-1;
for(j=0; j<=n-1; j++)
{
for(i=j+1; i<=n; i++)
{
f->ptr.p_double[i] = ((t-x->ptr.p_double[j])*f->ptr.p_double[i]-(t-x->ptr.p_double[i])*f->ptr.p_double[j])/(x->ptr.p_double[i]-x->ptr.p_double[j]);
}
}
result = f->ptr.p_double[n];
ae_frame_leave(_state);
return result;
}
static void testpolintunit_brcunset(barycentricinterpolant* b,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector x;
ae_vector y;
ae_vector w;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&w, 0, sizeof(w));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
ae_vector_set_length(&x, 1, _state);
ae_vector_set_length(&y, 1, _state);
ae_vector_set_length(&w, 1, _state);
x.ptr.p_double[0] = (double)(0);
y.ptr.p_double[0] = (double)(0);
w.ptr.p_double[0] = (double)(1);
barycentricbuildxyw(&x, &y, &w, 1, b, _state);
ae_frame_leave(_state);
}
static void testlsfitunit_testpolynomialfitting(ae_bool* fiterrors,
ae_state *_state);
static void testlsfitunit_testrationalfitting(ae_bool* fiterrors,
ae_state *_state);
static void testlsfitunit_testsplinefitting(ae_bool* fiterrors,
ae_state *_state);
static void testlsfitunit_testgeneralfitting(ae_bool* llserrors,
ae_bool* nlserrors,
ae_state *_state);
static void testlsfitunit_testrdp(ae_bool* errorflag, ae_state *_state);
static void testlsfitunit_testlogisticfitting(ae_bool* fiterrors,
ae_state *_state);
static void testlsfitunit_testbcnls(ae_bool* errorflag, ae_state *_state);
static void testlsfitunit_testlcnls(ae_bool* errorflag, ae_state *_state);
static ae_bool testlsfitunit_isglssolution(ae_int_t n,
ae_int_t m,
ae_int_t k,
/* Real */ ae_vector* y,
/* Real */ ae_vector* w,
/* Real */ ae_matrix* fmatrix,
/* Real */ ae_matrix* cmatrix,
/* Real */ ae_vector* c,
ae_state *_state);
static double testlsfitunit_getglserror(ae_int_t n,
ae_int_t m,
/* Real */ ae_vector* y,
/* Real */ ae_vector* w,
/* Real */ ae_matrix* fmatrix,
/* Real */ ae_vector* c,
ae_state *_state);
static void testlsfitunit_fitlinearnonlinear(ae_int_t m,
ae_int_t deravailable,
/* Real */ ae_matrix* xy,
lsfitstate* state,
ae_bool* nlserrors,
ae_state *_state);
static void testlsfitunit_testgradientcheck(ae_bool* testg,
ae_state *_state);
static void testlsfitunit_funcderiv(/* Real */ ae_vector* c,
/* Real */ ae_vector* x,
/* Real */ ae_vector* x0,
ae_int_t k,
ae_int_t m,
ae_int_t functype,
double* f,
/* Real */ ae_vector* g,
ae_state *_state);
static void testlsfitunit_testfunc1(ae_int_t k,
/* Real */ ae_vector* x,
/* Real */ ae_vector* z,
double* f,
ae_bool needf,
/* Real */ ae_vector* g,
ae_bool needg,
ae_state *_state);
static void testlsfitunit_testfunc2(/* Real */ ae_vector* x,
ae_int_t nx,
/* Real */ ae_vector* c,
ae_int_t nc,
double* f,
ae_bool needf,
/* Real */ ae_vector* g,
ae_bool needg,
ae_state *_state);
static void testlsfitunit_testfunc3(/* Real */ ae_vector* x,
ae_int_t nx,
/* Real */ ae_vector* c,
ae_int_t nc,
double* f,
ae_bool needf,
/* Real */ ae_vector* g,
ae_bool needg,
ae_state *_state);
static void testlsfitunit_append10(/* Real */ ae_vector* x,
double v0,
double v1,
double v2,
double v3,
double v4,
double v5,
double v6,
double v7,
double v8,
double v9,
ae_state *_state);
ae_bool testlsfit(ae_bool silent, ae_state *_state)
{
ae_bool waserrors;
ae_bool llserrors;
ae_bool nlserrors;
ae_bool polfiterrors;
ae_bool ratfiterrors;
ae_bool splfiterrors;
ae_bool graderrors;
ae_bool logisticerrors;
ae_bool rdperrors;
ae_bool result;
waserrors = ae_false;
polfiterrors = ae_false;
ratfiterrors = ae_false;
splfiterrors = ae_false;
llserrors = ae_false;
nlserrors = ae_false;
graderrors = ae_false;
logisticerrors = ae_false;
rdperrors = ae_false;
testlsfitunit_testrdp(&rdperrors, _state);
testlsfitunit_testlogisticfitting(&logisticerrors, _state);
testlsfitunit_testpolynomialfitting(&polfiterrors, _state);
testlsfitunit_testrationalfitting(&ratfiterrors, _state);
testlsfitunit_testsplinefitting(&splfiterrors, _state);
testlsfitunit_testgeneralfitting(&llserrors, &nlserrors, _state);
testlsfitunit_testgradientcheck(&graderrors, _state);
/*
* report
*/
waserrors = ((((((llserrors||nlserrors)||polfiterrors)||ratfiterrors)||splfiterrors)||graderrors)||logisticerrors)||rdperrors;
if( !silent )
{
printf("TESTING LEAST SQUARES\n");
printf("POLYNOMIAL LEAST SQUARES: ");
if( polfiterrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("RATIONAL LEAST SQUARES: ");
if( ratfiterrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("SPLINE LEAST SQUARES: ");
if( splfiterrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("LINEAR LEAST SQUARES: ");
if( llserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("NON-LINEAR LEAST SQUARES: ");
if( nlserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("TEST FOR VERIFICATION OF THE GRADIENT: ");
if( graderrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("LOGISTIC FITTING (4PL/5PL): ");
if( logisticerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("RDP ALGORITHM: ");
if( rdperrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
/*
* end
*/
result = !waserrors;
return result;
}
/*************************************************************************
Unit test
*************************************************************************/
static void testlsfitunit_testpolynomialfitting(ae_bool* fiterrors,
ae_state *_state)
{
ae_frame _frame_block;
double threshold;
ae_vector x;
ae_vector y;
ae_vector w;
ae_vector x2;
ae_vector y2;
ae_vector w2;
ae_vector xfull;
ae_vector yfull;
double t;
ae_int_t i;
ae_int_t k;
ae_vector xc;
ae_vector yc;
ae_vector dc;
ae_int_t info;
ae_int_t info2;
double v;
double v0;
double v1;
double v2;
double s;
double xmin;
double xmax;
double refrms;
double refavg;
double refavgrel;
double refmax;
barycentricinterpolant p;
barycentricinterpolant p1;
barycentricinterpolant p2;
polynomialfitreport rep;
polynomialfitreport rep2;
ae_int_t n;
ae_int_t m;
ae_int_t maxn;
ae_int_t pass;
ae_int_t passcount;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&w, 0, sizeof(w));
memset(&x2, 0, sizeof(x2));
memset(&y2, 0, sizeof(y2));
memset(&w2, 0, sizeof(w2));
memset(&xfull, 0, sizeof(xfull));
memset(&yfull, 0, sizeof(yfull));
memset(&xc, 0, sizeof(xc));
memset(&yc, 0, sizeof(yc));
memset(&dc, 0, sizeof(dc));
memset(&p, 0, sizeof(p));
memset(&p1, 0, sizeof(p1));
memset(&p2, 0, sizeof(p2));
memset(&rep, 0, sizeof(rep));
memset(&rep2, 0, sizeof(rep2));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xfull, 0, DT_REAL, _state, ae_true);
ae_vector_init(&yfull, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&yc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&dc, 0, DT_INT, _state, ae_true);
_barycentricinterpolant_init(&p, _state, ae_true);
_barycentricinterpolant_init(&p1, _state, ae_true);
_barycentricinterpolant_init(&p2, _state, ae_true);
_polynomialfitreport_init(&rep, _state, ae_true);
_polynomialfitreport_init(&rep2, _state, ae_true);
*fiterrors = ae_false;
maxn = 5;
passcount = 20;
threshold = 1.0E8*ae_machineepsilon;
/*
* Test polynomial fitting
*/
for(pass=1; pass<=passcount; pass++)
{
for(n=1; n<=maxn; n++)
{
/*
* N=M+K fitting (i.e. interpolation)
*/
for(k=0; k<=n-1; k++)
{
taskgenint1d((double)(-1), (double)(1), n, &xfull, &yfull, _state);
ae_vector_set_length(&x, n-k, _state);
ae_vector_set_length(&y, n-k, _state);
ae_vector_set_length(&w, n-k, _state);
if( k>0 )
{
ae_vector_set_length(&xc, k, _state);
ae_vector_set_length(&yc, k, _state);
ae_vector_set_length(&dc, k, _state);
}
for(i=0; i<=n-k-1; i++)
{
x.ptr.p_double[i] = xfull.ptr.p_double[i];
y.ptr.p_double[i] = yfull.ptr.p_double[i];
w.ptr.p_double[i] = 1+ae_randomreal(_state);
}
for(i=0; i<=k-1; i++)
{
xc.ptr.p_double[i] = xfull.ptr.p_double[n-k+i];
yc.ptr.p_double[i] = yfull.ptr.p_double[n-k+i];
dc.ptr.p_int[i] = 0;
}
polynomialfitwc(&x, &y, &w, n-k, &xc, &yc, &dc, k, n, &info, &p1, &rep, _state);
if( info<=0 )
{
*fiterrors = ae_true;
}
else
{
for(i=0; i<=n-k-1; i++)
{
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(barycentriccalc(&p1, x.ptr.p_double[i], _state)-y.ptr.p_double[i], _state),threshold);
}
for(i=0; i<=k-1; i++)
{
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(barycentriccalc(&p1, xc.ptr.p_double[i], _state)-yc.ptr.p_double[i], _state),threshold);
}
}
}
/*
* Testing constraints on derivatives.
* Special tasks which will always have solution:
* 1. P(0)=YC[0]
* 2. P(0)=YC[0], P'(0)=YC[1]
*/
if( n>1 )
{
for(m=3; m<=5; m++)
{
for(k=1; k<=2; k++)
{
taskgenint1d((double)(-1), (double)(1), n, &x, &y, _state);
ae_vector_set_length(&w, n, _state);
ae_vector_set_length(&xc, 2, _state);
ae_vector_set_length(&yc, 2, _state);
ae_vector_set_length(&dc, 2, _state);
for(i=0; i<=n-1; i++)
{
w.ptr.p_double[i] = 1+ae_randomreal(_state);
}
xc.ptr.p_double[0] = (double)(0);
yc.ptr.p_double[0] = 2*ae_randomreal(_state)-1;
dc.ptr.p_int[0] = 0;
xc.ptr.p_double[1] = (double)(0);
yc.ptr.p_double[1] = 2*ae_randomreal(_state)-1;
dc.ptr.p_int[1] = 1;
polynomialfitwc(&x, &y, &w, n, &xc, &yc, &dc, k, m, &info, &p1, &rep, _state);
if( info<=0 )
{
*fiterrors = ae_true;
}
else
{
barycentricdiff1(&p1, 0.0, &v0, &v1, _state);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(v0-yc.ptr.p_double[0], _state),threshold);
if( k==2 )
{
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(v1-yc.ptr.p_double[1], _state),threshold);
}
}
}
}
}
}
}
for(m=2; m<=8; m++)
{
for(pass=1; pass<=passcount; pass++)
{
/*
* General fitting
*
* interpolating function through M nodes should have
* greater RMS error than fitting it through the same M nodes
*/
n = 100;
ae_vector_set_length(&x2, n, _state);
ae_vector_set_length(&y2, n, _state);
ae_vector_set_length(&w2, n, _state);
xmin = (double)(0);
xmax = 2*ae_pi;
for(i=0; i<=n-1; i++)
{
x2.ptr.p_double[i] = 2*ae_pi*ae_randomreal(_state);
y2.ptr.p_double[i] = ae_sin(x2.ptr.p_double[i], _state);
w2.ptr.p_double[i] = (double)(1);
}
ae_vector_set_length(&x, m, _state);
ae_vector_set_length(&y, m, _state);
for(i=0; i<=m-1; i++)
{
x.ptr.p_double[i] = xmin+(xmax-xmin)*i/(m-1);
y.ptr.p_double[i] = ae_sin(x.ptr.p_double[i], _state);
}
polynomialbuild(&x, &y, m, &p1, _state);
polynomialfitwc(&x2, &y2, &w2, n, &xc, &yc, &dc, 0, m, &info, &p2, &rep, _state);
if( info<=0 )
{
*fiterrors = ae_true;
}
else
{
/*
* calculate P1 (interpolant) RMS error, compare with P2 error
*/
v1 = (double)(0);
v2 = (double)(0);
for(i=0; i<=n-1; i++)
{
v1 = v1+ae_sqr(barycentriccalc(&p1, x2.ptr.p_double[i], _state)-y2.ptr.p_double[i], _state);
v2 = v2+ae_sqr(barycentriccalc(&p2, x2.ptr.p_double[i], _state)-y2.ptr.p_double[i], _state);
}
v1 = ae_sqrt(v1/n, _state);
v2 = ae_sqrt(v2/n, _state);
*fiterrors = *fiterrors||ae_fp_greater(v2,v1);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(v2-rep.rmserror, _state),threshold);
}
/*
* compare weighted and non-weighted
*/
n = 20;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
ae_vector_set_length(&w, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = i+(ae_randomreal(_state)-0.5);
y.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
w.ptr.p_double[i] = (double)(1);
}
polynomialfitwc(&x, &y, &w, n, &xc, &yc, &dc, 0, m, &info, &p1, &rep, _state);
polynomialfit(&x, &y, n, m, &info2, &p2, &rep2, _state);
if( info<=0||info2<=0 )
{
*fiterrors = ae_true;
}
else
{
/*
* calculate P1 (interpolant), compare with P2 error
* compare RMS errors
*/
t = 2*ae_randomreal(_state)-1;
v1 = barycentriccalc(&p1, t, _state);
v2 = barycentriccalc(&p2, t, _state);
*fiterrors = *fiterrors||!approxequal(v2, v1, 1.0E-12, _state);
*fiterrors = *fiterrors||!approxequal(rep.rmserror, rep2.rmserror, 1.0E-12*maxreal3((double)(1), rep.rmserror, rep2.rmserror, _state), _state);
*fiterrors = *fiterrors||!approxequal(rep.avgerror, rep2.avgerror, 1.0E-12*maxreal3((double)(1), rep.avgerror, rep2.avgerror, _state), _state);
*fiterrors = *fiterrors||!approxequal(rep.avgrelerror, rep2.avgrelerror, 1.0E-12*maxreal3((double)(1), rep.avgrelerror, rep2.avgrelerror, _state), _state);
*fiterrors = *fiterrors||!approxequal(rep.maxerror, rep2.maxerror, 1.0E-12*maxreal3((double)(1), rep.maxerror, rep2.maxerror, _state), _state);
}
}
}
for(m=1; m<=maxn; m++)
{
for(pass=1; pass<=passcount; pass++)
{
ae_assert(passcount>=2, "PassCount should be 2 or greater!", _state);
/*
* solve simple task (all X[] are the same, Y[] are specially
* calculated to ensure simple form of all types of errors)
* and check correctness of the errors calculated by subroutines
*
* First pass is done with zero Y[], other passes - with random Y[].
* It should test both ability to correctly calculate errors and
* ability to not fail while working with zeros :)
*/
n = 4*maxn;
if( pass==1 )
{
v1 = (double)(0);
v2 = (double)(0);
v = (double)(0);
}
else
{
v1 = ae_randomreal(_state);
v2 = ae_randomreal(_state);
v = 1+ae_randomreal(_state);
}
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
ae_vector_set_length(&w, n, _state);
for(i=0; i<=maxn-1; i++)
{
x.ptr.p_double[4*i+0] = (double)(i);
y.ptr.p_double[4*i+0] = v-v2;
w.ptr.p_double[4*i+0] = (double)(1);
x.ptr.p_double[4*i+1] = (double)(i);
y.ptr.p_double[4*i+1] = v-v1;
w.ptr.p_double[4*i+1] = (double)(1);
x.ptr.p_double[4*i+2] = (double)(i);
y.ptr.p_double[4*i+2] = v+v1;
w.ptr.p_double[4*i+2] = (double)(1);
x.ptr.p_double[4*i+3] = (double)(i);
y.ptr.p_double[4*i+3] = v+v2;
w.ptr.p_double[4*i+3] = (double)(1);
}
refrms = ae_sqrt((ae_sqr(v1, _state)+ae_sqr(v2, _state))/2, _state);
refavg = (ae_fabs(v1, _state)+ae_fabs(v2, _state))/2;
if( pass==1 )
{
refavgrel = (double)(0);
}
else
{
refavgrel = 0.25*(ae_fabs(v2, _state)/ae_fabs(v-v2, _state)+ae_fabs(v1, _state)/ae_fabs(v-v1, _state)+ae_fabs(v1, _state)/ae_fabs(v+v1, _state)+ae_fabs(v2, _state)/ae_fabs(v+v2, _state));
}
refmax = ae_maxreal(v1, v2, _state);
/*
* Test errors correctness
*/
polynomialfit(&x, &y, n, m, &info, &p, &rep, _state);
if( info<=0 )
{
*fiterrors = ae_true;
}
else
{
s = barycentriccalc(&p, (double)(0), _state);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(s-v, _state),threshold);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state),threshold);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state),threshold);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state),threshold);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.maxerror-refmax, _state),threshold);
}
}
}
ae_frame_leave(_state);
}
static void testlsfitunit_testrationalfitting(ae_bool* fiterrors,
ae_state *_state)
{
ae_frame _frame_block;
double threshold;
ae_int_t maxn;
ae_int_t passcount;
barycentricinterpolant b1;
barycentricinterpolant b2;
ae_vector x;
ae_vector x2;
ae_vector y;
ae_vector y2;
ae_vector w;
ae_vector w2;
ae_vector xc;
ae_vector yc;
ae_vector dc;
ae_int_t n;
ae_int_t m;
ae_int_t i;
ae_int_t k;
ae_int_t pass;
double t;
double s;
double v;
double v0;
double v1;
double v2;
ae_int_t info;
ae_int_t info2;
double xmin;
double xmax;
double refrms;
double refavg;
double refavgrel;
double refmax;
barycentricfitreport rep;
barycentricfitreport rep2;
ae_frame_make(_state, &_frame_block);
memset(&b1, 0, sizeof(b1));
memset(&b2, 0, sizeof(b2));
memset(&x, 0, sizeof(x));
memset(&x2, 0, sizeof(x2));
memset(&y, 0, sizeof(y));
memset(&y2, 0, sizeof(y2));
memset(&w, 0, sizeof(w));
memset(&w2, 0, sizeof(w2));
memset(&xc, 0, sizeof(xc));
memset(&yc, 0, sizeof(yc));
memset(&dc, 0, sizeof(dc));
memset(&rep, 0, sizeof(rep));
memset(&rep2, 0, sizeof(rep2));
_barycentricinterpolant_init(&b1, _state, ae_true);
_barycentricinterpolant_init(&b2, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&yc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&dc, 0, DT_INT, _state, ae_true);
_barycentricfitreport_init(&rep, _state, ae_true);
_barycentricfitreport_init(&rep2, _state, ae_true);
*fiterrors = ae_false;
/*
* PassCount number of repeated passes
* Threshold error tolerance
* LipschitzTol Lipschitz constant increase allowed
* when calculating constant on a twice denser grid
*/
passcount = 5;
maxn = 15;
threshold = 1000000*ae_machineepsilon;
/*
* Test rational fitting:
*/
for(pass=1; pass<=passcount; pass++)
{
for(n=2; n<=maxn; n++)
{
/*
* N=M+K fitting (i.e. interpolation)
*/
for(k=0; k<=n-1; k++)
{
ae_vector_set_length(&x, n-k, _state);
ae_vector_set_length(&y, n-k, _state);
ae_vector_set_length(&w, n-k, _state);
if( k>0 )
{
ae_vector_set_length(&xc, k, _state);
ae_vector_set_length(&yc, k, _state);
ae_vector_set_length(&dc, k, _state);
}
for(i=0; i<=n-k-1; i++)
{
x.ptr.p_double[i] = (double)i/(double)(n-1);
y.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
w.ptr.p_double[i] = 1+ae_randomreal(_state);
}
for(i=0; i<=k-1; i++)
{
xc.ptr.p_double[i] = (double)(n-k+i)/(double)(n-1);
yc.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
dc.ptr.p_int[i] = 0;
}
barycentricfitfloaterhormannwc(&x, &y, &w, n-k, &xc, &yc, &dc, k, n, &info, &b1, &rep, _state);
if( info<=0 )
{
*fiterrors = ae_true;
}
else
{
for(i=0; i<=n-k-1; i++)
{
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(barycentriccalc(&b1, x.ptr.p_double[i], _state)-y.ptr.p_double[i], _state),threshold);
}
for(i=0; i<=k-1; i++)
{
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(barycentriccalc(&b1, xc.ptr.p_double[i], _state)-yc.ptr.p_double[i], _state),threshold);
}
}
}
/*
* Testing constraints on derivatives:
* * several M's are tried
* * several K's are tried - 1, 2.
* * constraints at the ends of the interval
*/
for(m=3; m<=5; m++)
{
for(k=1; k<=2; k++)
{
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
ae_vector_set_length(&w, n, _state);
ae_vector_set_length(&xc, 2, _state);
ae_vector_set_length(&yc, 2, _state);
ae_vector_set_length(&dc, 2, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
y.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
w.ptr.p_double[i] = 1+ae_randomreal(_state);
}
xc.ptr.p_double[0] = (double)(-1);
yc.ptr.p_double[0] = 2*ae_randomreal(_state)-1;
dc.ptr.p_int[0] = 0;
xc.ptr.p_double[1] = (double)(1);
yc.ptr.p_double[1] = 2*ae_randomreal(_state)-1;
dc.ptr.p_int[1] = 0;
barycentricfitfloaterhormannwc(&x, &y, &w, n, &xc, &yc, &dc, k, m, &info, &b1, &rep, _state);
if( info<=0 )
{
*fiterrors = ae_true;
}
else
{
for(i=0; i<=k-1; i++)
{
barycentricdiff1(&b1, xc.ptr.p_double[i], &v0, &v1, _state);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(v0-yc.ptr.p_double[i], _state),threshold);
}
}
}
}
}
}
for(m=2; m<=8; m++)
{
for(pass=1; pass<=passcount; pass++)
{
/*
* General fitting
*
* interpolating function through M nodes should have
* greater RMS error than fitting it through the same M nodes
*/
n = 100;
ae_vector_set_length(&x2, n, _state);
ae_vector_set_length(&y2, n, _state);
ae_vector_set_length(&w2, n, _state);
xmin = ae_maxrealnumber;
xmax = -ae_maxrealnumber;
for(i=0; i<=n-1; i++)
{
x2.ptr.p_double[i] = 2*ae_pi*ae_randomreal(_state);
y2.ptr.p_double[i] = ae_sin(x2.ptr.p_double[i], _state);
w2.ptr.p_double[i] = (double)(1);
xmin = ae_minreal(xmin, x2.ptr.p_double[i], _state);
xmax = ae_maxreal(xmax, x2.ptr.p_double[i], _state);
}
ae_vector_set_length(&x, m, _state);
ae_vector_set_length(&y, m, _state);
for(i=0; i<=m-1; i++)
{
x.ptr.p_double[i] = xmin+(xmax-xmin)*i/(m-1);
y.ptr.p_double[i] = ae_sin(x.ptr.p_double[i], _state);
}
barycentricbuildfloaterhormann(&x, &y, m, 3, &b1, _state);
barycentricfitfloaterhormannwc(&x2, &y2, &w2, n, &xc, &yc, &dc, 0, m, &info, &b2, &rep, _state);
if( info<=0 )
{
*fiterrors = ae_true;
}
else
{
/*
* calculate B1 (interpolant) RMS error, compare with B2 error
*/
v1 = (double)(0);
v2 = (double)(0);
for(i=0; i<=n-1; i++)
{
v1 = v1+ae_sqr(barycentriccalc(&b1, x2.ptr.p_double[i], _state)-y2.ptr.p_double[i], _state);
v2 = v2+ae_sqr(barycentriccalc(&b2, x2.ptr.p_double[i], _state)-y2.ptr.p_double[i], _state);
}
v1 = ae_sqrt(v1/n, _state);
v2 = ae_sqrt(v2/n, _state);
*fiterrors = *fiterrors||ae_fp_greater(v2,v1);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(v2-rep.rmserror, _state),threshold);
}
/*
* compare weighted and non-weighted
*/
n = 20;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
ae_vector_set_length(&w, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = i+(ae_randomreal(_state)-0.5);
y.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
w.ptr.p_double[i] = (double)(1);
}
barycentricfitfloaterhormannwc(&x, &y, &w, n, &xc, &yc, &dc, 0, m, &info, &b1, &rep, _state);
barycentricfitfloaterhormann(&x, &y, n, m, &info2, &b2, &rep2, _state);
if( info<=0||info2<=0 )
{
*fiterrors = ae_true;
}
else
{
/*
* calculate B1 (interpolant), compare with B2
* compare RMS errors
*/
t = 2*ae_randomreal(_state)-1;
v1 = barycentriccalc(&b1, t, _state);
v2 = barycentriccalc(&b2, t, _state);
*fiterrors = *fiterrors||!approxequal(v2, v1, 1.0E-12, _state);
*fiterrors = *fiterrors||!approxequal(rep.rmserror, rep2.rmserror, 1.0E-12*maxreal3((double)(1), rep.rmserror, rep2.rmserror, _state), _state);
*fiterrors = *fiterrors||!approxequal(rep.avgerror, rep2.avgerror, 1.0E-12*maxreal3((double)(1), rep.avgerror, rep2.avgerror, _state), _state);
*fiterrors = *fiterrors||!approxequal(rep.avgrelerror, rep2.avgrelerror, 1.0E-12*maxreal3((double)(1), rep.avgrelerror, rep2.avgrelerror, _state), _state);
*fiterrors = *fiterrors||!approxequal(rep.maxerror, rep2.maxerror, 1.0E-12*maxreal3((double)(1), rep.maxerror, rep2.maxerror, _state), _state);
}
}
}
for(pass=1; pass<=passcount; pass++)
{
ae_assert(passcount>=2, "PassCount should be 2 or greater!", _state);
/*
* solve simple task (all X[] are the same, Y[] are specially
* calculated to ensure simple form of all types of errors)
* and check correctness of the errors calculated by subroutines
*
* First pass is done with zero Y[], other passes - with random Y[].
* It should test both ability to correctly calculate errors and
* ability to not fail while working with zeros :)
*/
n = 4;
if( pass==1 )
{
v1 = (double)(0);
v2 = (double)(0);
v = (double)(0);
}
else
{
v1 = ae_randomreal(_state);
v2 = ae_randomreal(_state);
v = 1+ae_randomreal(_state);
}
ae_vector_set_length(&x, 4, _state);
ae_vector_set_length(&y, 4, _state);
ae_vector_set_length(&w, 4, _state);
x.ptr.p_double[0] = (double)(0);
y.ptr.p_double[0] = v-v2;
w.ptr.p_double[0] = (double)(1);
x.ptr.p_double[1] = (double)(0);
y.ptr.p_double[1] = v-v1;
w.ptr.p_double[1] = (double)(1);
x.ptr.p_double[2] = (double)(0);
y.ptr.p_double[2] = v+v1;
w.ptr.p_double[2] = (double)(1);
x.ptr.p_double[3] = (double)(0);
y.ptr.p_double[3] = v+v2;
w.ptr.p_double[3] = (double)(1);
refrms = ae_sqrt((ae_sqr(v1, _state)+ae_sqr(v2, _state))/2, _state);
refavg = (ae_fabs(v1, _state)+ae_fabs(v2, _state))/2;
if( pass==1 )
{
refavgrel = (double)(0);
}
else
{
refavgrel = 0.25*(ae_fabs(v2, _state)/ae_fabs(v-v2, _state)+ae_fabs(v1, _state)/ae_fabs(v-v1, _state)+ae_fabs(v1, _state)/ae_fabs(v+v1, _state)+ae_fabs(v2, _state)/ae_fabs(v+v2, _state));
}
refmax = ae_maxreal(v1, v2, _state);
/*
* Test errors correctness
*/
barycentricfitfloaterhormann(&x, &y, 4, 2, &info, &b1, &rep, _state);
if( info<=0 )
{
*fiterrors = ae_true;
}
else
{
s = barycentriccalc(&b1, (double)(0), _state);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(s-v, _state),threshold);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state),threshold);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state),threshold);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state),threshold);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.maxerror-refmax, _state),threshold);
}
}
ae_frame_leave(_state);
}
static void testlsfitunit_testsplinefitting(ae_bool* fiterrors,
ae_state *_state)
{
ae_frame _frame_block;
double threshold;
ae_int_t passcount;
ae_int_t n;
ae_int_t m;
ae_int_t i;
ae_int_t k;
ae_int_t pass;
ae_vector x;
ae_vector y;
ae_vector w;
ae_vector w2;
ae_vector xc;
ae_vector yc;
ae_vector d;
ae_vector dc;
double sa;
double sb;
ae_int_t info;
ae_int_t info1;
ae_int_t info2;
spline1dinterpolant c;
spline1dinterpolant c2;
spline1dfitreport rep;
spline1dfitreport rep2;
double s;
double ds;
double d2s;
ae_int_t stype;
double t;
double v;
double v1;
double v2;
double refrms;
double refavg;
double refavgrel;
double refmax;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&w, 0, sizeof(w));
memset(&w2, 0, sizeof(w2));
memset(&xc, 0, sizeof(xc));
memset(&yc, 0, sizeof(yc));
memset(&d, 0, sizeof(d));
memset(&dc, 0, sizeof(dc));
memset(&c, 0, sizeof(c));
memset(&c2, 0, sizeof(c2));
memset(&rep, 0, sizeof(rep));
memset(&rep2, 0, sizeof(rep2));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&yc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&dc, 0, DT_INT, _state, ae_true);
_spline1dinterpolant_init(&c, _state, ae_true);
_spline1dinterpolant_init(&c2, _state, ae_true);
_spline1dfitreport_init(&rep, _state, ae_true);
_spline1dfitreport_init(&rep2, _state, ae_true);
/*
* Valyes:
* * pass count
* * threshold - for tests which must be satisfied exactly
*/
passcount = 20;
threshold = 10000*ae_machineepsilon;
*fiterrors = ae_false;
/*
* Test fitting by Cubic and Hermite splines (obsolete, but still supported)
*/
for(pass=1; pass<=passcount; pass++)
{
/*
* Cubic splines
* Ability to handle boundary constraints (1-4 constraints on F, dF/dx).
*/
for(m=4; m<=8; m++)
{
for(k=1; k<=4; k++)
{
if( k>=m )
{
continue;
}
n = 100;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
ae_vector_set_length(&w, n, _state);
ae_vector_set_length(&xc, 4, _state);
ae_vector_set_length(&yc, 4, _state);
ae_vector_set_length(&dc, 4, _state);
sa = 1+ae_randomreal(_state);
sb = 2*ae_randomreal(_state)-1;
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = sa*ae_randomreal(_state)+sb;
y.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
w.ptr.p_double[i] = 1+ae_randomreal(_state);
}
xc.ptr.p_double[0] = sb;
yc.ptr.p_double[0] = 2*ae_randomreal(_state)-1;
dc.ptr.p_int[0] = 0;
xc.ptr.p_double[1] = sb;
yc.ptr.p_double[1] = 2*ae_randomreal(_state)-1;
dc.ptr.p_int[1] = 1;
xc.ptr.p_double[2] = sa+sb;
yc.ptr.p_double[2] = 2*ae_randomreal(_state)-1;
dc.ptr.p_int[2] = 0;
xc.ptr.p_double[3] = sa+sb;
yc.ptr.p_double[3] = 2*ae_randomreal(_state)-1;
dc.ptr.p_int[3] = 1;
spline1dfitcubicwc(&x, &y, &w, n, &xc, &yc, &dc, k, m, &info, &c, &rep, _state);
if( info<=0 )
{
*fiterrors = ae_true;
}
else
{
/*
* Check that constraints are satisfied
*/
for(i=0; i<=k-1; i++)
{
spline1ddiff(&c, xc.ptr.p_double[i], &s, &ds, &d2s, _state);
if( dc.ptr.p_int[i]==0 )
{
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(s-yc.ptr.p_double[i], _state),threshold);
}
if( dc.ptr.p_int[i]==1 )
{
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(ds-yc.ptr.p_double[i], _state),threshold);
}
if( dc.ptr.p_int[i]==2 )
{
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(d2s-yc.ptr.p_double[i], _state),threshold);
}
}
}
}
}
/*
* Cubic splines
* Ability to handle one internal constraint
*/
for(m=4; m<=8; m++)
{
n = 100;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
ae_vector_set_length(&w, n, _state);
ae_vector_set_length(&xc, 1, _state);
ae_vector_set_length(&yc, 1, _state);
ae_vector_set_length(&dc, 1, _state);
sa = 1+ae_randomreal(_state);
sb = 2*ae_randomreal(_state)-1;
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = sa*ae_randomreal(_state)+sb;
y.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
w.ptr.p_double[i] = 1+ae_randomreal(_state);
}
xc.ptr.p_double[0] = sa*ae_randomreal(_state)+sb;
yc.ptr.p_double[0] = 2*ae_randomreal(_state)-1;
dc.ptr.p_int[0] = ae_randominteger(2, _state);
spline1dfitcubicwc(&x, &y, &w, n, &xc, &yc, &dc, 1, m, &info, &c, &rep, _state);
if( info<=0 )
{
*fiterrors = ae_true;
}
else
{
/*
* Check that constraints are satisfied
*/
spline1ddiff(&c, xc.ptr.p_double[0], &s, &ds, &d2s, _state);
if( dc.ptr.p_int[0]==0 )
{
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(s-yc.ptr.p_double[0], _state),threshold);
}
if( dc.ptr.p_int[0]==1 )
{
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(ds-yc.ptr.p_double[0], _state),threshold);
}
if( dc.ptr.p_int[0]==2 )
{
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(d2s-yc.ptr.p_double[0], _state),threshold);
}
}
}
/*
* Hermite splines
* Ability to handle boundary constraints (1-4 constraints on F, dF/dx).
*/
for(m=4; m<=8; m++)
{
for(k=1; k<=4; k++)
{
if( k>=m )
{
continue;
}
if( m%2!=0 )
{
continue;
}
n = 100;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
ae_vector_set_length(&w, n, _state);
ae_vector_set_length(&xc, 4, _state);
ae_vector_set_length(&yc, 4, _state);
ae_vector_set_length(&dc, 4, _state);
sa = 1+ae_randomreal(_state);
sb = 2*ae_randomreal(_state)-1;
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = sa*ae_randomreal(_state)+sb;
y.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
w.ptr.p_double[i] = 1+ae_randomreal(_state);
}
xc.ptr.p_double[0] = sb;
yc.ptr.p_double[0] = 2*ae_randomreal(_state)-1;
dc.ptr.p_int[0] = 0;
xc.ptr.p_double[1] = sb;
yc.ptr.p_double[1] = 2*ae_randomreal(_state)-1;
dc.ptr.p_int[1] = 1;
xc.ptr.p_double[2] = sa+sb;
yc.ptr.p_double[2] = 2*ae_randomreal(_state)-1;
dc.ptr.p_int[2] = 0;
xc.ptr.p_double[3] = sa+sb;
yc.ptr.p_double[3] = 2*ae_randomreal(_state)-1;
dc.ptr.p_int[3] = 1;
spline1dfithermitewc(&x, &y, &w, n, &xc, &yc, &dc, k, m, &info, &c, &rep, _state);
if( info<=0 )
{
*fiterrors = ae_true;
}
else
{
/*
* Check that constraints are satisfied
*/
for(i=0; i<=k-1; i++)
{
spline1ddiff(&c, xc.ptr.p_double[i], &s, &ds, &d2s, _state);
if( dc.ptr.p_int[i]==0 )
{
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(s-yc.ptr.p_double[i], _state),threshold);
}
if( dc.ptr.p_int[i]==1 )
{
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(ds-yc.ptr.p_double[i], _state),threshold);
}
if( dc.ptr.p_int[i]==2 )
{
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(d2s-yc.ptr.p_double[i], _state),threshold);
}
}
}
}
}
/*
* Hermite splines
* Ability to handle one internal constraint
*/
for(m=4; m<=8; m++)
{
if( m%2!=0 )
{
continue;
}
n = 100;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
ae_vector_set_length(&w, n, _state);
ae_vector_set_length(&xc, 1, _state);
ae_vector_set_length(&yc, 1, _state);
ae_vector_set_length(&dc, 1, _state);
sa = 1+ae_randomreal(_state);
sb = 2*ae_randomreal(_state)-1;
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = sa*ae_randomreal(_state)+sb;
y.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
w.ptr.p_double[i] = 1+ae_randomreal(_state);
}
xc.ptr.p_double[0] = sa*ae_randomreal(_state)+sb;
yc.ptr.p_double[0] = 2*ae_randomreal(_state)-1;
dc.ptr.p_int[0] = ae_randominteger(2, _state);
spline1dfithermitewc(&x, &y, &w, n, &xc, &yc, &dc, 1, m, &info, &c, &rep, _state);
if( info<=0 )
{
*fiterrors = ae_true;
}
else
{
/*
* Check that constraints are satisfied
*/
spline1ddiff(&c, xc.ptr.p_double[0], &s, &ds, &d2s, _state);
if( dc.ptr.p_int[0]==0 )
{
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(s-yc.ptr.p_double[0], _state),threshold);
}
if( dc.ptr.p_int[0]==1 )
{
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(ds-yc.ptr.p_double[0], _state),threshold);
}
if( dc.ptr.p_int[0]==2 )
{
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(d2s-yc.ptr.p_double[0], _state),threshold);
}
}
}
}
for(m=4; m<=8; m++)
{
for(stype=0; stype<=1; stype++)
{
for(pass=1; pass<=passcount; pass++)
{
if( stype==1&&m%2!=0 )
{
continue;
}
/*
* cubic/Hermite spline fitting:
* * generate "template spline" C2
* * generate 2*N points from C2, such that result of
* ideal fit should be equal to C2
* * fit, store in C
* * compare C and C2
*/
sa = 1+ae_randomreal(_state);
sb = 2*ae_randomreal(_state)-1;
if( stype==0 )
{
ae_vector_set_length(&x, m-2, _state);
ae_vector_set_length(&y, m-2, _state);
for(i=0; i<=m-2-1; i++)
{
x.ptr.p_double[i] = sa*i/(m-2-1)+sb;
y.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
spline1dbuildcubic(&x, &y, m-2, 1, 2*ae_randomreal(_state)-1, 1, 2*ae_randomreal(_state)-1, &c2, _state);
}
if( stype==1 )
{
ae_vector_set_length(&x, m/2, _state);
ae_vector_set_length(&y, m/2, _state);
ae_vector_set_length(&d, m/2, _state);
for(i=0; i<=m/2-1; i++)
{
x.ptr.p_double[i] = sa*i/(m/2-1)+sb;
y.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
d.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
spline1dbuildhermite(&x, &y, &d, m/2, &c2, _state);
}
n = 50;
ae_vector_set_length(&x, 2*n, _state);
ae_vector_set_length(&y, 2*n, _state);
ae_vector_set_length(&w, 2*n, _state);
for(i=0; i<=n-1; i++)
{
/*
* "if i=0" and "if i=1" are needed to
* synchronize interval size for C2 and
* spline being fitted (i.e. C).
*/
t = ae_randomreal(_state);
x.ptr.p_double[i] = sa*ae_randomreal(_state)+sb;
if( i==0 )
{
x.ptr.p_double[i] = sb;
}
if( i==1 )
{
x.ptr.p_double[i] = sa+sb;
}
v = spline1dcalc(&c2, x.ptr.p_double[i], _state);
y.ptr.p_double[i] = v+t;
w.ptr.p_double[i] = 1+ae_randomreal(_state);
x.ptr.p_double[n+i] = x.ptr.p_double[i];
y.ptr.p_double[n+i] = v-t;
w.ptr.p_double[n+i] = w.ptr.p_double[i];
}
info = -1;
if( stype==0 )
{
spline1dfitcubicwc(&x, &y, &w, 2*n, &xc, &yc, &dc, 0, m, &info, &c, &rep, _state);
}
if( stype==1 )
{
spline1dfithermitewc(&x, &y, &w, 2*n, &xc, &yc, &dc, 0, m, &info, &c, &rep, _state);
}
if( info<=0 )
{
*fiterrors = ae_true;
}
else
{
for(i=0; i<=n-1; i++)
{
v = sa*ae_randomreal(_state)+sb;
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(spline1dcalc(&c, v, _state)-spline1dcalc(&c2, v, _state), _state),threshold);
}
}
}
}
}
for(m=4; m<=8; m++)
{
for(pass=1; pass<=passcount; pass++)
{
/*
* prepare points/weights
*/
n = 10+ae_randominteger(10, _state);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
ae_vector_set_length(&w, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = i+(ae_randomreal(_state)-0.5);
y.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
w.ptr.p_double[i] = (double)(1);
}
/*
* Fit cubic with unity weights, without weights, then compare
*/
if( m>=4 )
{
spline1dfitcubicwc(&x, &y, &w, n, &xc, &yc, &dc, 0, m, &info1, &c, &rep, _state);
spline1dfitcubic(&x, &y, n, m, &info2, &c2, &rep2, _state);
if( info1<=0||info2<=0 )
{
*fiterrors = ae_true;
}
else
{
for(i=0; i<=n-1; i++)
{
v = ae_randomreal(_state)*(n-1);
*fiterrors = *fiterrors||!approxequal(spline1dcalc(&c, v, _state), spline1dcalc(&c2, v, _state), 1.0E-12, _state);
*fiterrors = *fiterrors||!approxequal(rep.taskrcond, rep2.taskrcond, 1.0E-12*maxreal3((double)(1), rep.taskrcond, rep2.taskrcond, _state), _state);
*fiterrors = *fiterrors||!approxequal(rep.rmserror, rep2.rmserror, 1.0E-12*maxreal3((double)(1), rep.rmserror, rep2.rmserror, _state), _state);
*fiterrors = *fiterrors||!approxequal(rep.avgerror, rep2.avgerror, 1.0E-12*maxreal3((double)(1), rep.avgerror, rep2.avgerror, _state), _state);
*fiterrors = *fiterrors||!approxequal(rep.avgrelerror, rep2.avgrelerror, 1.0E-12*maxreal3((double)(1), rep.avgrelerror, rep2.avgrelerror, _state), _state);
*fiterrors = *fiterrors||!approxequal(rep.maxerror, rep2.maxerror, 1.0E-12*maxreal3((double)(1), rep.maxerror, rep2.maxerror, _state), _state);
}
}
}
/*
* Fit Hermite with unity weights, without weights, then compare
*/
if( m>=4&&m%2==0 )
{
spline1dfithermitewc(&x, &y, &w, n, &xc, &yc, &dc, 0, m, &info1, &c, &rep, _state);
spline1dfithermite(&x, &y, n, m, &info2, &c2, &rep2, _state);
if( info1<=0||info2<=0 )
{
*fiterrors = ae_true;
}
else
{
for(i=0; i<=n-1; i++)
{
v = ae_randomreal(_state)*(n-1);
*fiterrors = *fiterrors||!approxequal(spline1dcalc(&c, v, _state), spline1dcalc(&c2, v, _state), 1.0E-12, _state);
*fiterrors = *fiterrors||!approxequal(rep.taskrcond, rep2.taskrcond, 1.0E-12*maxreal3((double)(1), rep.taskrcond, rep2.taskrcond, _state), _state);
*fiterrors = *fiterrors||!approxequal(rep.rmserror, rep2.rmserror, 1.0E-12*maxreal3((double)(1), rep.rmserror, rep2.rmserror, _state), _state);
*fiterrors = *fiterrors||!approxequal(rep.avgerror, rep2.avgerror, 1.0E-12*maxreal3((double)(1), rep.avgerror, rep2.avgerror, _state), _state);
*fiterrors = *fiterrors||!approxequal(rep.avgrelerror, rep2.avgrelerror, 1.0E-12*maxreal3((double)(1), rep.avgrelerror, rep2.avgrelerror, _state), _state);
*fiterrors = *fiterrors||!approxequal(rep.maxerror, rep2.maxerror, 1.0E-12*maxreal3((double)(1), rep.maxerror, rep2.maxerror, _state), _state);
}
}
}
}
}
/*
* Check correctness of error reports
*/
for(pass=1; pass<=passcount; pass++)
{
ae_assert(passcount>=2, "PassCount should be 2 or greater!", _state);
/*
* solve simple task (all X[] are the same, Y[] are specially
* calculated to ensure simple form of all types of errors)
* and check correctness of the errors calculated by subroutines
*
* First pass is done with zero Y[], other passes - with random Y[].
* It should test both ability to correctly calculate errors and
* ability to not fail while working with zeros :)
*/
n = 4;
if( pass==1 )
{
v1 = (double)(0);
v2 = (double)(0);
v = (double)(0);
}
else
{
v1 = ae_randomreal(_state);
v2 = ae_randomreal(_state);
v = 1+ae_randomreal(_state);
}
ae_vector_set_length(&x, 4, _state);
ae_vector_set_length(&y, 4, _state);
ae_vector_set_length(&w, 4, _state);
x.ptr.p_double[0] = (double)(0);
y.ptr.p_double[0] = v-v2;
w.ptr.p_double[0] = (double)(1);
x.ptr.p_double[1] = (double)(0);
y.ptr.p_double[1] = v-v1;
w.ptr.p_double[1] = (double)(1);
x.ptr.p_double[2] = (double)(0);
y.ptr.p_double[2] = v+v1;
w.ptr.p_double[2] = (double)(1);
x.ptr.p_double[3] = (double)(0);
y.ptr.p_double[3] = v+v2;
w.ptr.p_double[3] = (double)(1);
refrms = ae_sqrt((ae_sqr(v1, _state)+ae_sqr(v2, _state))/2, _state);
refavg = (ae_fabs(v1, _state)+ae_fabs(v2, _state))/2;
if( pass==1 )
{
refavgrel = (double)(0);
}
else
{
refavgrel = 0.25*(ae_fabs(v2, _state)/ae_fabs(v-v2, _state)+ae_fabs(v1, _state)/ae_fabs(v-v1, _state)+ae_fabs(v1, _state)/ae_fabs(v+v1, _state)+ae_fabs(v2, _state)/ae_fabs(v+v2, _state));
}
refmax = ae_maxreal(v1, v2, _state);
/*
* Test cubic fitting
*/
spline1dfitcubic(&x, &y, 4, 4, &info, &c, &rep, _state);
if( info<=0 )
{
*fiterrors = ae_true;
}
else
{
s = spline1dcalc(&c, (double)(0), _state);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(s-v, _state),threshold);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state),threshold);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state),threshold);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state),threshold);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.maxerror-refmax, _state),threshold);
}
/*
* Test Hermite fitting
*/
spline1dfithermite(&x, &y, 4, 4, &info, &c, &rep, _state);
if( info<=0 )
{
*fiterrors = ae_true;
}
else
{
s = spline1dcalc(&c, (double)(0), _state);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(s-v, _state),threshold);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state),threshold);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state),threshold);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state),threshold);
*fiterrors = *fiterrors||ae_fp_greater(ae_fabs(rep.maxerror-refmax, _state),threshold);
}
}
ae_frame_leave(_state);
}
static void testlsfitunit_testgeneralfitting(ae_bool* llserrors,
ae_bool* nlserrors,
ae_state *_state)
{
ae_frame _frame_block;
double threshold;
double nlthreshold;
ae_int_t maxn;
ae_int_t maxm;
ae_int_t skind;
ae_int_t pkind;
ae_int_t passcount;
ae_int_t n;
ae_int_t m;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t pass;
double xscale;
double cscale;
double wscale;
double noiselevel;
double tol;
double diffstep;
ae_vector x;
ae_vector y;
ae_vector y2;
ae_vector w;
ae_vector w2;
ae_vector s;
ae_vector c;
ae_vector cstart;
ae_vector cend;
ae_vector c2;
ae_matrix a;
ae_matrix a2;
ae_matrix cm;
double v;
double v1;
double v2;
lsfitreport rep;
lsfitreport rep2;
ae_int_t info;
ae_int_t info2;
double refrms;
double refavg;
double refavgrel;
double refmax;
double avgdeviationpar;
double avgdeviationcurve;
double avgdeviationnoise;
double adccnt;
double adpcnt;
double adncnt;
lsfitstate state;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&y2, 0, sizeof(y2));
memset(&w, 0, sizeof(w));
memset(&w2, 0, sizeof(w2));
memset(&s, 0, sizeof(s));
memset(&c, 0, sizeof(c));
memset(&cstart, 0, sizeof(cstart));
memset(&cend, 0, sizeof(cend));
memset(&c2, 0, sizeof(c2));
memset(&a, 0, sizeof(a));
memset(&a2, 0, sizeof(a2));
memset(&cm, 0, sizeof(cm));
memset(&rep, 0, sizeof(rep));
memset(&rep2, 0, sizeof(rep2));
memset(&state, 0, sizeof(state));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
ae_vector_init(&w2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&s, 0, DT_REAL, _state, ae_true);
ae_vector_init(&c, 0, DT_REAL, _state, ae_true);
ae_vector_init(&cstart, 0, DT_REAL, _state, ae_true);
ae_vector_init(&cend, 0, DT_REAL, _state, ae_true);
ae_vector_init(&c2, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&cm, 0, 0, DT_REAL, _state, ae_true);
_lsfitreport_init(&rep, _state, ae_true);
_lsfitreport_init(&rep2, _state, ae_true);
_lsfitstate_init(&state, _state, ae_true);
*llserrors = ae_false;
*nlserrors = ae_false;
threshold = 10000*ae_machineepsilon;
nlthreshold = 0.00001;
diffstep = 0.0001;
maxn = 6;
maxm = 6;
passcount = 4;
/*
* Test constrained NLS problems
*/
testlsfitunit_testbcnls(nlserrors, _state);
testlsfitunit_testlcnls(nlserrors, _state);
/*
* Testing unconstrained least squares (linear/nonlinear)
*/
for(n=1; n<=maxn; n++)
{
for(m=1; m<=maxm; m++)
{
for(pass=1; pass<=passcount; pass++)
{
/*
* Solve non-degenerate linear least squares task
* Use Chebyshev basis. Its condition number is very good.
*/
ae_matrix_set_length(&a, n, m, _state);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
ae_vector_set_length(&w, n, _state);
xscale = 0.9+0.1*ae_randomreal(_state);
for(i=0; i<=n-1; i++)
{
if( n==1 )
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
else
{
x.ptr.p_double[i] = xscale*((double)(2*i)/(double)(n-1)-1);
}
y.ptr.p_double[i] = 3*x.ptr.p_double[i]+ae_exp(x.ptr.p_double[i], _state);
w.ptr.p_double[i] = 1+ae_randomreal(_state);
a.ptr.pp_double[i][0] = (double)(1);
if( m>1 )
{
a.ptr.pp_double[i][1] = x.ptr.p_double[i];
}
for(j=2; j<=m-1; j++)
{
a.ptr.pp_double[i][j] = 2*x.ptr.p_double[i]*a.ptr.pp_double[i][j-1]-a.ptr.pp_double[i][j-2];
}
}
/*
* 1. test weighted fitting (optimality)
* 2. Solve degenerate least squares task built on the basis
* of previous task
*/
lsfitlinearw(&y, &w, &a, n, m, &info, &c, &rep, _state);
if( info<=0 )
{
*llserrors = ae_true;
}
else
{
*llserrors = *llserrors||!testlsfitunit_isglssolution(n, m, 0, &y, &w, &a, &cm, &c, _state);
}
ae_matrix_set_length(&a2, n, 2*m, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
a2.ptr.pp_double[i][2*j+0] = a.ptr.pp_double[i][j];
a2.ptr.pp_double[i][2*j+1] = a.ptr.pp_double[i][j];
}
}
lsfitlinearw(&y, &w, &a2, n, 2*m, &info, &c2, &rep, _state);
if( info<=0 )
{
*llserrors = ae_true;
}
else
{
/*
* test answer correctness using design matrix properties
* and previous task solution
*/
for(j=0; j<=m-1; j++)
{
*llserrors = *llserrors||ae_fp_greater(ae_fabs(c2.ptr.p_double[2*j+0]+c2.ptr.p_double[2*j+1]-c.ptr.p_double[j], _state),threshold);
}
}
/*
* test non-weighted fitting
*/
ae_vector_set_length(&w2, n, _state);
for(i=0; i<=n-1; i++)
{
w2.ptr.p_double[i] = (double)(1);
}
lsfitlinearw(&y, &w2, &a, n, m, &info, &c, &rep, _state);
lsfitlinear(&y, &a, n, m, &info2, &c2, &rep2, _state);
if( info<=0||info2<=0 )
{
*llserrors = ae_true;
}
else
{
/*
* test answer correctness
*/
for(j=0; j<=m-1; j++)
{
*llserrors = *llserrors||ae_fp_greater(ae_fabs(c.ptr.p_double[j]-c2.ptr.p_double[j], _state),threshold);
}
*llserrors = *llserrors||ae_fp_greater(ae_fabs(rep.taskrcond-rep2.taskrcond, _state),threshold);
}
/*
* test nonlinear fitting on the linear task
* (only non-degenerate tasks are tested)
* and compare with answer from linear fitting subroutine
*/
if( n>=m )
{
ae_vector_set_length(&c2, m, _state);
/*
* test function/gradient/Hessian-based weighted fitting
*/
lsfitlinearw(&y, &w, &a, n, m, &info, &c, &rep, _state);
for(i=0; i<=m-1; i++)
{
c2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
lsfitcreatewf(&a, &y, &w, &c2, n, m, m, diffstep, &state, _state);
lsfitsetcond(&state, nlthreshold, 0, _state);
testlsfitunit_fitlinearnonlinear(m, 0, &a, &state, nlserrors, _state);
lsfitresults(&state, &info, &c2, &rep2, _state);
if( info<=0 )
{
*nlserrors = ae_true;
}
else
{
for(i=0; i<=m-1; i++)
{
*nlserrors = *nlserrors||ae_fp_greater(ae_fabs(c.ptr.p_double[i]-c2.ptr.p_double[i], _state),100*nlthreshold);
}
}
for(i=0; i<=m-1; i++)
{
c2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
lsfitcreatewfg(&a, &y, &w, &c2, n, m, m, ae_fp_greater(ae_randomreal(_state),0.5), &state, _state);
lsfitsetcond(&state, nlthreshold, 0, _state);
testlsfitunit_fitlinearnonlinear(m, 1, &a, &state, nlserrors, _state);
lsfitresults(&state, &info, &c2, &rep2, _state);
if( info<=0 )
{
*nlserrors = ae_true;
}
else
{
for(i=0; i<=m-1; i++)
{
*nlserrors = *nlserrors||ae_fp_greater(ae_fabs(c.ptr.p_double[i]-c2.ptr.p_double[i], _state),100*nlthreshold);
}
}
for(i=0; i<=m-1; i++)
{
c2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
lsfitcreatewfgh(&a, &y, &w, &c2, n, m, m, &state, _state);
lsfitsetcond(&state, nlthreshold, 0, _state);
testlsfitunit_fitlinearnonlinear(m, 2, &a, &state, nlserrors, _state);
lsfitresults(&state, &info, &c2, &rep2, _state);
if( info<=0 )
{
*nlserrors = ae_true;
}
else
{
for(i=0; i<=m-1; i++)
{
*nlserrors = *nlserrors||ae_fp_greater(ae_fabs(c.ptr.p_double[i]-c2.ptr.p_double[i], _state),100*nlthreshold);
}
}
/*
* test gradient-only or Hessian-based fitting without weights
*/
lsfitlinear(&y, &a, n, m, &info, &c, &rep, _state);
for(i=0; i<=m-1; i++)
{
c2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
lsfitcreatef(&a, &y, &c2, n, m, m, diffstep, &state, _state);
lsfitsetcond(&state, nlthreshold, 0, _state);
testlsfitunit_fitlinearnonlinear(m, 0, &a, &state, nlserrors, _state);
lsfitresults(&state, &info, &c2, &rep2, _state);
if( info<=0 )
{
*nlserrors = ae_true;
}
else
{
for(i=0; i<=m-1; i++)
{
*nlserrors = *nlserrors||ae_fp_greater(ae_fabs(c.ptr.p_double[i]-c2.ptr.p_double[i], _state),100*nlthreshold);
}
}
for(i=0; i<=m-1; i++)
{
c2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
lsfitcreatefg(&a, &y, &c2, n, m, m, ae_fp_greater(ae_randomreal(_state),0.5), &state, _state);
lsfitsetcond(&state, nlthreshold, 0, _state);
testlsfitunit_fitlinearnonlinear(m, 1, &a, &state, nlserrors, _state);
lsfitresults(&state, &info, &c2, &rep2, _state);
if( info<=0 )
{
*nlserrors = ae_true;
}
else
{
for(i=0; i<=m-1; i++)
{
*nlserrors = *nlserrors||ae_fp_greater(ae_fabs(c.ptr.p_double[i]-c2.ptr.p_double[i], _state),100*nlthreshold);
}
}
for(i=0; i<=m-1; i++)
{
c2.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
lsfitcreatefgh(&a, &y, &c2, n, m, m, &state, _state);
lsfitsetcond(&state, nlthreshold, 0, _state);
testlsfitunit_fitlinearnonlinear(m, 2, &a, &state, nlserrors, _state);
lsfitresults(&state, &info, &c2, &rep2, _state);
if( info<=0 )
{
*nlserrors = ae_true;
}
else
{
for(i=0; i<=m-1; i++)
{
*nlserrors = *nlserrors||ae_fp_greater(ae_fabs(c.ptr.p_double[i]-c2.ptr.p_double[i], _state),100*nlthreshold);
}
}
}
}
}
/*
* test correctness of the RCond field
*/
ae_matrix_set_length(&a, n-1+1, n-1+1, _state);
ae_vector_set_length(&x, n-1+1, _state);
ae_vector_set_length(&y, n-1+1, _state);
ae_vector_set_length(&w, n-1+1, _state);
v1 = ae_maxrealnumber;
v2 = ae_minrealnumber;
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = 0.1+0.9*ae_randomreal(_state);
y.ptr.p_double[i] = 0.1+0.9*ae_randomreal(_state);
w.ptr.p_double[i] = (double)(1);
for(j=0; j<=n-1; j++)
{
if( i==j )
{
a.ptr.pp_double[i][i] = 0.1+0.9*ae_randomreal(_state);
v1 = ae_minreal(v1, a.ptr.pp_double[i][i], _state);
v2 = ae_maxreal(v2, a.ptr.pp_double[i][i], _state);
}
else
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
}
lsfitlinearw(&y, &w, &a, n, n, &info, &c, &rep, _state);
if( info<=0 )
{
*llserrors = ae_true;
}
else
{
*llserrors = *llserrors||ae_fp_greater(ae_fabs(rep.taskrcond-v1/v2, _state),threshold);
}
}
/*
* Test constrained least squares
*/
for(pass=1; pass<=passcount; pass++)
{
for(n=1; n<=maxn; n++)
{
for(m=1; m<=maxm; m++)
{
/*
* test for K<>0
*/
for(k=1; k<=m-1; k++)
{
/*
* Prepare Chebyshev basis. Its condition number is very good.
* Prepare constraints (random numbers)
*/
ae_matrix_set_length(&a, n, m, _state);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
ae_vector_set_length(&w, n, _state);
xscale = 0.9+0.1*ae_randomreal(_state);
for(i=0; i<=n-1; i++)
{
if( n==1 )
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
else
{
x.ptr.p_double[i] = xscale*((double)(2*i)/(double)(n-1)-1);
}
y.ptr.p_double[i] = 3*x.ptr.p_double[i]+ae_exp(x.ptr.p_double[i], _state);
w.ptr.p_double[i] = 1+ae_randomreal(_state);
a.ptr.pp_double[i][0] = (double)(1);
if( m>1 )
{
a.ptr.pp_double[i][1] = x.ptr.p_double[i];
}
for(j=2; j<=m-1; j++)
{
a.ptr.pp_double[i][j] = 2*x.ptr.p_double[i]*a.ptr.pp_double[i][j-1]-a.ptr.pp_double[i][j-2];
}
}
ae_matrix_set_length(&cm, k, m+1, _state);
for(i=0; i<=k-1; i++)
{
for(j=0; j<=m; j++)
{
cm.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
/*
* Solve constrained task
*/
lsfitlinearwc(&y, &w, &a, &cm, n, m, k, &info, &c, &rep, _state);
if( info<=0 )
{
*llserrors = ae_true;
}
else
{
*llserrors = *llserrors||!testlsfitunit_isglssolution(n, m, k, &y, &w, &a, &cm, &c, _state);
}
/*
* test non-weighted fitting
*/
ae_vector_set_length(&w2, n, _state);
for(i=0; i<=n-1; i++)
{
w2.ptr.p_double[i] = (double)(1);
}
lsfitlinearwc(&y, &w2, &a, &cm, n, m, k, &info, &c, &rep, _state);
lsfitlinearc(&y, &a, &cm, n, m, k, &info2, &c2, &rep2, _state);
if( info<=0||info2<=0 )
{
*llserrors = ae_true;
}
else
{
/*
* test answer correctness
*/
for(j=0; j<=m-1; j++)
{
*llserrors = *llserrors||ae_fp_greater(ae_fabs(c.ptr.p_double[j]-c2.ptr.p_double[j], _state),threshold);
}
*llserrors = *llserrors||ae_fp_greater(ae_fabs(rep.taskrcond-rep2.taskrcond, _state),threshold);
}
}
}
}
}
/*
* nonlinear task for nonlinear fitting:
*
* f(X,C) = 1/(1+C*X^2),
* C(true) = 2.
*/
n = 100;
ae_vector_set_length(&c, 1, _state);
c.ptr.p_double[0] = 1+2*ae_randomreal(_state);
ae_matrix_set_length(&a, n, 1, _state);
ae_vector_set_length(&y, n, _state);
for(i=0; i<=n-1; i++)
{
a.ptr.pp_double[i][0] = 4*ae_randomreal(_state)-2;
y.ptr.p_double[i] = 1/(1+2*ae_sqr(a.ptr.pp_double[i][0], _state));
}
lsfitcreatefg(&a, &y, &c, n, 1, 1, ae_true, &state, _state);
lsfitsetcond(&state, nlthreshold, 0, _state);
while(lsfititeration(&state, _state))
{
if( state.needf )
{
state.f = 1/(1+state.c.ptr.p_double[0]*ae_sqr(state.x.ptr.p_double[0], _state));
}
if( state.needfg )
{
state.f = 1/(1+state.c.ptr.p_double[0]*ae_sqr(state.x.ptr.p_double[0], _state));
state.g.ptr.p_double[0] = -ae_sqr(state.x.ptr.p_double[0], _state)/ae_sqr(1+state.c.ptr.p_double[0]*ae_sqr(state.x.ptr.p_double[0], _state), _state);
}
}
lsfitresults(&state, &info, &c, &rep, _state);
if( info<=0 )
{
ae_set_error_flag(nlserrors, ae_true, __FILE__, __LINE__, "testlsfitunit.ap:1389");
}
else
{
ae_set_error_flag(nlserrors, ae_fp_greater(ae_fabs(c.ptr.p_double[0]-2, _state),100*nlthreshold), __FILE__, __LINE__, "testlsfitunit.ap:1391");
}
/*
* solve simple task (fitting by constant function) and check
* correctness of the errors calculated by subroutines
*/
for(pass=1; pass<=passcount; pass++)
{
/*
* test on task with non-zero Yi
*/
n = 4;
v1 = ae_randomreal(_state);
v2 = ae_randomreal(_state);
v = 1+ae_randomreal(_state);
ae_vector_set_length(&c, 1, _state);
c.ptr.p_double[0] = 1+2*ae_randomreal(_state);
ae_matrix_set_length(&a, 4, 1, _state);
ae_vector_set_length(&y, 4, _state);
a.ptr.pp_double[0][0] = (double)(1);
y.ptr.p_double[0] = v-v2;
a.ptr.pp_double[1][0] = (double)(1);
y.ptr.p_double[1] = v-v1;
a.ptr.pp_double[2][0] = (double)(1);
y.ptr.p_double[2] = v+v1;
a.ptr.pp_double[3][0] = (double)(1);
y.ptr.p_double[3] = v+v2;
refrms = ae_sqrt((ae_sqr(v1, _state)+ae_sqr(v2, _state))/2, _state);
refavg = (ae_fabs(v1, _state)+ae_fabs(v2, _state))/2;
refavgrel = 0.25*(ae_fabs(v2, _state)/ae_fabs(v-v2, _state)+ae_fabs(v1, _state)/ae_fabs(v-v1, _state)+ae_fabs(v1, _state)/ae_fabs(v+v1, _state)+ae_fabs(v2, _state)/ae_fabs(v+v2, _state));
refmax = ae_maxreal(v1, v2, _state);
/*
* Test LLS
*/
lsfitlinear(&y, &a, 4, 1, &info, &c, &rep, _state);
if( info<=0 )
{
*llserrors = ae_true;
}
else
{
*llserrors = *llserrors||ae_fp_greater(ae_fabs(c.ptr.p_double[0]-v, _state),threshold);
*llserrors = *llserrors||ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state),threshold);
*llserrors = *llserrors||ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state),threshold);
*llserrors = *llserrors||ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state),threshold);
*llserrors = *llserrors||ae_fp_greater(ae_fabs(rep.maxerror-refmax, _state),threshold);
}
/*
* Test NLS
*/
lsfitcreatefg(&a, &y, &c, 4, 1, 1, ae_true, &state, _state);
lsfitsetcond(&state, nlthreshold, 0, _state);
while(lsfititeration(&state, _state))
{
if( state.needf )
{
state.f = state.c.ptr.p_double[0];
}
if( state.needfg )
{
state.f = state.c.ptr.p_double[0];
state.g.ptr.p_double[0] = (double)(1);
}
}
lsfitresults(&state, &info, &c, &rep, _state);
if( info<=0 )
{
ae_set_error_flag(nlserrors, ae_true, __FILE__, __LINE__, "testlsfitunit.ap:1456");
}
else
{
ae_set_error_flag(nlserrors, ae_fp_greater(ae_fabs(c.ptr.p_double[0]-v, _state),threshold), __FILE__, __LINE__, "testlsfitunit.ap:1459");
ae_set_error_flag(nlserrors, ae_fp_greater(ae_fabs(rep.rmserror-refrms, _state),threshold), __FILE__, __LINE__, "testlsfitunit.ap:1460");
ae_set_error_flag(nlserrors, ae_fp_greater(ae_fabs(rep.avgerror-refavg, _state),threshold), __FILE__, __LINE__, "testlsfitunit.ap:1461");
ae_set_error_flag(nlserrors, ae_fp_greater(ae_fabs(rep.avgrelerror-refavgrel, _state),threshold), __FILE__, __LINE__, "testlsfitunit.ap:1462");
ae_set_error_flag(nlserrors, ae_fp_greater(ae_fabs(rep.maxerror-refmax, _state),threshold), __FILE__, __LINE__, "testlsfitunit.ap:1463");
}
}
/*
* Check covariance matrix, errors-in-parameters.
*
* We test three different solvers:
* * nonlinear solver
* * unconstrained linear solver
* * constrained linear solver with empty set of constrains
* on two random problems:
* * problem with known prior, noise, unit weights
* * problem with known prior, noise, non-unit weights
*
* We test that:
* * rep.ErrPar=sqrt(diag(Rep.CovPar))
* * Rep.ErrPar is not too optimistic - average value of ratio
* between |c_fit-c_prior| and ErrPar[] is less than TOL
* * Rep.ErrPar is not too pessimistic - average value of ratio
* is larger than 1/TOL
* * similarly, Rep.ErrCurve gives good estimate of |A*c_fit - A*c_prior|
* - not optimistic, not pessimistic.
* * similarly, per-point noise estimates are good enough (we use
* slightly different tolerances, though)
* In order to have these estimates we perform many different tests
* and calculate average deviation divided by ErrPar/ErrCurve. Then
* we perform test.
*
* Due to stochastic nature of the test it is not good idea to
* consider each case individually - it is better to average over
* many runs.
*
*/
tol = 10.0;
for(n=1; n<=10; n++)
{
for(skind=0; skind<=2; skind++)
{
for(pkind=0; pkind<=1; pkind++)
{
/*
* Generate problem:
* * PKind=0 - unit weights
* * PKind=1 - non-unit weights, exact estimate of noise at I-th point
*
* We generate:
* * C - prior values of parameters
* * CStart - random initial point
* * A - function matrix
* * Y - noisy version of A*C
* * W - weights vector
* * S - vector of per-point estimates of noise
*/
cscale = ae_pow(10.0, 2*randomnormal(_state), _state);
xscale = ae_pow(10.0, 2*randomnormal(_state), _state);
noiselevel = 0.01*cscale*xscale;
ae_vector_set_length(&c, n, _state);
ae_vector_set_length(&cstart, n, _state);
for(i=0; i<=n-1; i++)
{
c.ptr.p_double[i] = cscale*randomnormal(_state);
cstart.ptr.p_double[i] = cscale*randomnormal(_state);
}
ae_matrix_set_length(&a, 1000, n, _state);
ae_vector_set_length(&y, a.rows, _state);
ae_vector_set_length(&w, a.rows, _state);
ae_vector_set_length(&s, a.rows, _state);
for(i=0; i<=a.rows-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = xscale*randomnormal(_state);
}
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &c.ptr.p_double[0], 1, ae_v_len(0,n-1));
if( pkind==0 )
{
w.ptr.p_double[i] = (double)(1);
s.ptr.p_double[i] = noiselevel;
y.ptr.p_double[i] = v+s.ptr.p_double[i]*randomnormal(_state);
}
if( pkind==1 )
{
w.ptr.p_double[i] = 1/noiselevel;
s.ptr.p_double[i] = noiselevel;
y.ptr.p_double[i] = v+s.ptr.p_double[i]*randomnormal(_state);
}
}
/*
* Test different solvers:
* * SKind=0 - nonlinear solver
* * SKind=1 - linear unconstrained
* * SKind=2 - linear constrained with empty set of constraints
*/
info = -1;
if( skind==0 )
{
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
lsfitcreatefg(&a, &y, &cstart, a.rows, n, n, ae_true, &state, _state);
}
else
{
lsfitcreatef(&a, &y, &cstart, a.rows, n, n, 0.001*cscale, &state, _state);
}
lsfitsetcond(&state, 0.0, 10, _state);
while(lsfititeration(&state, _state))
{
if( state.needf )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+state.c.ptr.p_double[i]*state.x.ptr.p_double[i];
}
}
if( state.needfg )
{
state.f = (double)(0);
for(i=0; i<=n-1; i++)
{
state.f = state.f+state.c.ptr.p_double[i]*state.x.ptr.p_double[i];
state.g.ptr.p_double[i] = state.x.ptr.p_double[i];
}
}
}
lsfitresults(&state, &info, &cend, &rep, _state);
}
if( skind==1 )
{
if( pkind==0 )
{
lsfitlinear(&y, &a, a.rows, n, &info, &cend, &rep, _state);
}
else
{
lsfitlinearw(&y, &w, &a, a.rows, n, &info, &cend, &rep, _state);
}
}
if( skind==2 )
{
if( pkind==0 )
{
lsfitlinearc(&y, &a, &a2, a.rows, n, 0, &info, &cend, &rep, _state);
}
else
{
lsfitlinearwc(&y, &w, &a, &a2, a.rows, n, 0, &info, &cend, &rep, _state);
}
}
/*
* Tests:
* * check relation between CovPar and ErrPar
* * accumulate average deviation in parameters
* * accumulate average deviation in curve fit
* * accumulate average deviation in noise estimate
*/
avgdeviationpar = (double)(0);
adpcnt = (double)(0);
avgdeviationcurve = (double)(0);
adccnt = (double)(0);
avgdeviationnoise = (double)(0);
adncnt = (double)(0);
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(llserrors, ae_fp_greater(ae_fabs(rep.covpar.ptr.pp_double[i][i]-ae_sqr(rep.errpar.ptr.p_double[i], _state), _state),100*ae_machineepsilon*ae_maxreal(ae_sqr(rep.errpar.ptr.p_double[i], _state), rep.covpar.ptr.pp_double[i][i], _state)), __FILE__, __LINE__, "testlsfitunit.ap:1612");
}
for(i=0; i<=n-1; i++)
{
avgdeviationpar = (avgdeviationpar*adpcnt+ae_fabs(c.ptr.p_double[i]-cend.ptr.p_double[i], _state)/rep.errpar.ptr.p_double[i])/(adpcnt+1);
adpcnt = adpcnt+1;
}
for(i=0; i<=a.rows-1; i++)
{
v1 = ae_v_dotproduct(&c.ptr.p_double[0], 1, &a.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
v2 = ae_v_dotproduct(&cend.ptr.p_double[0], 1, &a.ptr.pp_double[i][0], 1, ae_v_len(0,n-1));
avgdeviationcurve = (avgdeviationcurve*adccnt+ae_fabs(v1-v2, _state)/rep.errcurve.ptr.p_double[i])/(adccnt+1);
adccnt = adccnt+1;
avgdeviationnoise = (avgdeviationnoise*adncnt+rep.noise.ptr.p_double[i]/s.ptr.p_double[i])/(adncnt+1);
adncnt = adncnt+1;
}
/*
* Check that estimates are not too optimistic.
* This test is performed always.
*/
ae_set_error_flag(llserrors, ae_fp_greater(avgdeviationpar,tol), __FILE__, __LINE__, "testlsfitunit.ap:1632");
ae_set_error_flag(llserrors, ae_fp_greater(avgdeviationcurve,tol), __FILE__, __LINE__, "testlsfitunit.ap:1633");
ae_set_error_flag(llserrors, ae_fp_greater(avgdeviationnoise,1.50), __FILE__, __LINE__, "testlsfitunit.ap:1634");
ae_set_error_flag(llserrors, ae_fp_less(avgdeviationnoise,0.66), __FILE__, __LINE__, "testlsfitunit.ap:1635");
/*
* Test for estimates being too pessimistic is performed only
* when we have more than 4 parameters.
*/
ae_set_error_flag(llserrors, n>=5&&ae_fp_less(avgdeviationcurve,0.01), __FILE__, __LINE__, "testlsfitunit.ap:1641");
ae_set_error_flag(llserrors, n>=5&&ae_fp_less(avgdeviationpar,0.01), __FILE__, __LINE__, "testlsfitunit.ap:1642");
}
}
}
/*
* Check special property of the LSFit solver: it does not include points with
* zero weight in the estimate of the noise level. Such property seems to be
* quite natural, but in fact it requires some additional code in order to
* ignore such points.
*
* In order to test it we solve two problems: one 300xN, with 150 non-zero
* weights and 150 zero weights - and another one with only 150 points with
* non-zero weights. Both problems should give us same covariance matrix.
*/
tol = (double)(10);
for(n=1; n<=10; n++)
{
/*
* Generate N-dimensional linear problem with 300 points:
* * y = c'*x + noise
* * prior values of coefficients C has scale CScale
* * coordinates X has scale XScale
* * noise in I-th point has magnitude 0.1*CScale*XScale*WScale/W[i]
*/
cscale = ae_pow(10.0, 2*randomnormal(_state), _state);
xscale = ae_pow(10.0, 2*randomnormal(_state), _state);
wscale = ae_pow(10.0, 2*randomnormal(_state), _state);
noiselevel = 0.1*cscale*xscale;
ae_vector_set_length(&c, n, _state);
ae_vector_set_length(&cstart, n, _state);
for(i=0; i<=n-1; i++)
{
c.ptr.p_double[i] = cscale*randomnormal(_state);
cstart.ptr.p_double[i] = cscale*randomnormal(_state);
}
ae_matrix_set_length(&a, 300, n, _state);
ae_vector_set_length(&y, a.rows, _state);
ae_vector_set_length(&w, a.rows, _state);
for(i=0; i<=a.rows-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = xscale*randomnormal(_state);
}
v = ae_v_dotproduct(&a.ptr.pp_double[i][0], 1, &c.ptr.p_double[0], 1, ae_v_len(0,n-1));
if( i0 and NZ<>0, but in
* some cases either N or NZ (but not both) is zero.
*
* X-values have scale equal to ScaleX
*/
scalex = ae_pow((double)(10), 30*hqrnduniformr(&rs, _state)-15, _state);
n = 40+hqrnduniformi(&rs, 40, _state);
nz = 4+hqrnduniformi(&rs, 4, _state);
if( ae_fp_less(hqrnduniformr(&rs, _state),0.1) )
{
if( ae_fp_less(hqrnduniformr(&rs, _state),0.5) )
{
n = 0;
}
else
{
nz = 0;
}
}
ntotal = 2*(n+nz);
ae_vector_set_length(&x, ntotal, _state);
for(i=0; i<=n-1; i++)
{
v = scalex*ae_exp(ae_log((double)(5), _state)*(2*hqrnduniformr(&rs, _state)-1), _state);
x.ptr.p_double[2*i+0] = v;
x.ptr.p_double[2*i+1] = v;
}
for(i=0; i<=nz-1; i++)
{
x.ptr.p_double[2*n+2*i+0] = (double)(0);
x.ptr.p_double[2*n+2*i+1] = (double)(0);
}
/*
* Fenerate A/B/C/D:
* * A/D are random with scale equal to ScaleY
* * B is in +-[0.25,4.0]
* * for C we choose one of X[], if N>0;
* if N=0, we set C=1.
*/
scaley = ae_pow((double)(10), 30*hqrnduniformr(&rs, _state)-15, _state);
ae = scaley*(hqrnduniformr(&rs, _state)-0.5);
be = (2*hqrnduniformi(&rs, 2, _state)-1)*ae_exp(ae_log((double)(4), _state)*(2*hqrnduniformr(&rs, _state)-1), _state);
ce = scalex*ae_exp(ae_log((double)(2), _state)*(2*hqrnduniformr(&rs, _state)-1), _state);
de = ae+scaley*(2*hqrnduniformi(&rs, 2, _state)-1)*(hqrnduniformr(&rs, _state)+0.5);
/*
* Choose noise level and generate Y[].
*/
noise = 0.05*scaley;
ae_vector_set_length(&y, ntotal, _state);
for(i=0; i<=ntotal/2-1; i++)
{
if( ae_fp_neq(x.ptr.p_double[2*i+0],(double)(0)) )
{
v = de+(ae-de)/(1.0+ae_pow(x.ptr.p_double[2*i+0]/ce, be, _state));
}
else
{
if( ae_fp_greater_eq(be,(double)(0)) )
{
v = ae;
}
else
{
v = de;
}
}
y.ptr.p_double[2*i+0] = v+noise;
y.ptr.p_double[2*i+1] = v-noise;
}
/*
* Unconstrained fit and test
*
* NOTE: we test that B>=0 is returned. If BE<0, we use
* symmetry property of 4PL model.
*/
logisticfit4(&x, &y, ntotal, &a, &b, &c, &d, &rep, _state);
ae_set_error_flag(fiterrors, !ae_isfinite(a, _state), __FILE__, __LINE__, "testlsfitunit.ap:2162");
ae_set_error_flag(fiterrors, !ae_isfinite(b, _state), __FILE__, __LINE__, "testlsfitunit.ap:2163");
ae_set_error_flag(fiterrors, !ae_isfinite(c, _state), __FILE__, __LINE__, "testlsfitunit.ap:2164");
ae_set_error_flag(fiterrors, !ae_isfinite(d, _state), __FILE__, __LINE__, "testlsfitunit.ap:2165");
ae_set_error_flag(fiterrors, ae_fp_less(b,(double)(0)), __FILE__, __LINE__, "testlsfitunit.ap:2166");
v = 0.0;
for(i=0; i<=ntotal-1; i++)
{
if( ae_fp_neq(x.ptr.p_double[i],(double)(0)) )
{
vv = d+(a-d)/(1.0+ae_pow(x.ptr.p_double[i]/c, b, _state));
}
else
{
vv = a;
}
v = v+ae_sqr(y.ptr.p_double[i]-vv, _state);
}
v = ae_sqrt(v/ntotal, _state);
ae_set_error_flag(fiterrors, ae_fp_greater(v,(1+tol)*noise), __FILE__, __LINE__, "testlsfitunit.ap:2177");
/*
* Constrained fit and test
*
* NOTE: we test that B>=0 is returned. If BE<0, we use
* symmetry property of 4PL model.
*/
for(k0=0; k0<=1; k0++)
{
for(k1=0; k1<=1; k1++)
{
/*
* Choose constraints.
*/
if( k0==0 )
{
v0 = _state->v_nan;
}
else
{
if( ae_fp_greater_eq(be,(double)(0)) )
{
v0 = ae;
}
else
{
v0 = de;
}
}
if( k1==0 )
{
v1 = _state->v_nan;
}
else
{
if( ae_fp_greater_eq(be,(double)(0)) )
{
v1 = de;
}
else
{
v1 = ae;
}
}
/*
* Fit
*/
logisticfit4ec(&x, &y, ntotal, v0, v1, &a, &b, &c, &d, &rep, _state);
/*
* Check
*/
ae_set_error_flag(fiterrors, !ae_isfinite(a, _state), __FILE__, __LINE__, "testlsfitunit.ap:2218");
ae_set_error_flag(fiterrors, !ae_isfinite(b, _state), __FILE__, __LINE__, "testlsfitunit.ap:2219");
ae_set_error_flag(fiterrors, !ae_isfinite(c, _state), __FILE__, __LINE__, "testlsfitunit.ap:2220");
ae_set_error_flag(fiterrors, !ae_isfinite(d, _state), __FILE__, __LINE__, "testlsfitunit.ap:2221");
ae_set_error_flag(fiterrors, ae_fp_less(b,(double)(0)), __FILE__, __LINE__, "testlsfitunit.ap:2222");
ae_set_error_flag(fiterrors, k0!=0&&ae_fp_neq(a,v0), __FILE__, __LINE__, "testlsfitunit.ap:2223");
ae_set_error_flag(fiterrors, k1!=0&&ae_fp_neq(d,v1), __FILE__, __LINE__, "testlsfitunit.ap:2224");
v = 0.0;
for(i=0; i<=ntotal-1; i++)
{
if( ae_fp_neq(x.ptr.p_double[i],(double)(0)) )
{
vv = d+(a-d)/(1.0+ae_pow(x.ptr.p_double[i]/c, b, _state));
}
else
{
if( ae_fp_greater_eq(b,(double)(0)) )
{
vv = a;
}
else
{
vv = d;
}
}
v = v+ae_sqr(y.ptr.p_double[i]-vv, _state);
}
v = ae_sqrt(v/ntotal, _state);
ae_set_error_flag(fiterrors, ae_fp_greater(v,(1+tol)*noise), __FILE__, __LINE__, "testlsfitunit.ap:2240");
}
}
}
/*
* 5PL fitting
*
* Generate random AE/BE/CE/DE/GE, generate random set of points and for
* each point generate two function values: F(x)+eps and F(x)-eps.
* Such problem has solution which is exactly AE/BE/CE/DE which were
* used to generate points.
*
* NOTE: because problem has higher condition number, we use lower
* tolerance for power parameters B and G.
*
* This test checks both unconstrained and constrained fitting.
*/
tol = 1.0E-6;
for(pass=1; pass<=10; pass++)
{
/*
* Generate N points, N-1 of them with non-zero X and
* last one with zero X.
* X-values have scale equal to ScaleX
*/
scalex = ae_pow((double)(10), 30*hqrnduniformr(&rs, _state)-15, _state);
k = 50;
n = 2*k+1;
ae_vector_set_length(&x, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = scalex*ae_pow((double)(2), (double)(2*(i-k))/(double)k, _state);
}
x.ptr.p_double[n-1] = (double)(0);
/*
* Generate A/B/C/D/G:
* * A/D are random with scale equal to ScaleY
* * B is in +-[0.25,4.0]
* * G is in [0.25,4.0]
* * C is in [0.25,4.0]*ScaleX
* if N=0, we set C=1.
* Generate Y[].
*/
scaley = ae_pow((double)(10), 30*hqrnduniformr(&rs, _state)-15, _state);
ae = scaley*(hqrnduniformr(&rs, _state)-0.5);
be = (2*hqrnduniformi(&rs, 2, _state)-1)*ae_exp(ae_log((double)(2), _state)*(2*hqrnduniformr(&rs, _state)-1), _state);
ce = scalex*ae_exp(ae_log((double)(2), _state)*(2*hqrnduniformr(&rs, _state)-1), _state);
de = ae+scaley*(2*hqrnduniformi(&rs, 2, _state)-1)*(hqrnduniformr(&rs, _state)+0.5);
ge = ae_exp(ae_log((double)(2), _state)*(2*hqrnduniformr(&rs, _state)-1), _state);
ae_vector_set_length(&y, n, _state);
for(i=0; i<=n-1; i++)
{
if( ae_fp_neq(x.ptr.p_double[i],(double)(0)) )
{
v = de+(ae-de)/ae_pow(1.0+ae_pow(x.ptr.p_double[i]/ce, be, _state), ge, _state);
}
else
{
if( ae_fp_greater_eq(be,(double)(0)) )
{
v = ae;
}
else
{
v = de;
}
}
y.ptr.p_double[i] = v;
}
/*
* Unconstrained fit and test
*
* NOTE: we test that B>=0 is returned. If BE<0, we use
* symmetry property of 4PL model.
*/
logisticfit5(&x, &y, n, &a, &b, &c, &d, &g, &rep, _state);
v = 0.0;
for(i=0; i<=n-1; i++)
{
if( ae_fp_neq(x.ptr.p_double[i],(double)(0)) )
{
vv = d+(a-d)/ae_pow(1.0+ae_pow(x.ptr.p_double[i]/c, b, _state), g, _state);
}
else
{
if( ae_fp_greater_eq(b,(double)(0)) )
{
vv = a;
}
else
{
vv = d;
}
}
v = v+ae_sqr(y.ptr.p_double[i]-vv, _state);
}
v = ae_sqrt(v/n, _state);
ae_set_error_flag(fiterrors, ae_fp_greater(v,scaley*tol), __FILE__, __LINE__, "testlsfitunit.ap:2325");
/*
* Constrained fit and test
*/
for(k0=0; k0<=1; k0++)
{
for(k1=0; k1<=1; k1++)
{
/*
* Choose constraints.
*/
if( k0==0 )
{
v0 = _state->v_nan;
}
else
{
if( ae_fp_greater_eq(be,(double)(0)) )
{
v0 = ae;
}
else
{
v0 = de;
}
}
if( k1==0 )
{
v1 = _state->v_nan;
}
else
{
if( ae_fp_greater_eq(be,(double)(0)) )
{
v1 = de;
}
else
{
v1 = ae;
}
}
/*
* Fit
*/
logisticfit5ec(&x, &y, n, v0, v1, &a, &b, &c, &d, &g, &rep, _state);
ae_set_error_flag(fiterrors, !ae_isfinite(a, _state), __FILE__, __LINE__, "testlsfitunit.ap:2359");
ae_set_error_flag(fiterrors, !ae_isfinite(b, _state), __FILE__, __LINE__, "testlsfitunit.ap:2360");
ae_set_error_flag(fiterrors, !ae_isfinite(c, _state), __FILE__, __LINE__, "testlsfitunit.ap:2361");
ae_set_error_flag(fiterrors, !ae_isfinite(d, _state), __FILE__, __LINE__, "testlsfitunit.ap:2362");
if( ae_fp_greater(b,(double)(0)) )
{
ae_set_error_flag(fiterrors, k0!=0&&ae_fp_neq(a,v0), __FILE__, __LINE__, "testlsfitunit.ap:2365");
ae_set_error_flag(fiterrors, k1!=0&&ae_fp_neq(d,v1), __FILE__, __LINE__, "testlsfitunit.ap:2366");
}
else
{
ae_set_error_flag(fiterrors, k0!=0&&ae_fp_neq(d,v0), __FILE__, __LINE__, "testlsfitunit.ap:2370");
ae_set_error_flag(fiterrors, k1!=0&&ae_fp_neq(a,v1), __FILE__, __LINE__, "testlsfitunit.ap:2371");
}
v = 0.0;
for(i=0; i<=n-1; i++)
{
if( ae_fp_neq(x.ptr.p_double[i],(double)(0)) )
{
vv = d+(a-d)/ae_pow(1.0+ae_pow(x.ptr.p_double[i]/c, b, _state), g, _state);
}
else
{
if( ae_fp_greater_eq(b,(double)(0)) )
{
vv = a;
}
else
{
vv = d;
}
}
v = v+ae_sqr(y.ptr.p_double[i]-vv, _state);
}
v = ae_sqrt(v/n, _state);
ae_set_error_flag(fiterrors, ae_fp_greater(v,scaley*tol), __FILE__, __LINE__, "testlsfitunit.ap:2388");
}
}
}
/*
* Test correctness of errors
*/
tol = 1.0E-6;
for(pass=1; pass<=20; pass++)
{
n = 10;
meany = 0.0;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = (double)(i);
y.ptr.p_double[i] = hqrnduniformr(&rs, _state)-0.5;
meany = meany+y.ptr.p_double[i];
}
meany = meany/n;
x.ptr.p_double[1] = (double)(0);
/*
* Choose model fitting function to test
*/
k = hqrnduniformi(&rs, 4, _state);
a = (double)(0);
d = (double)(0);
c = (double)(1);
b = (double)(1);
g = (double)(1);
if( k==0 )
{
logisticfit4(&x, &y, n, &a, &b, &c, &d, &rep, _state);
g = 1.0;
}
if( k==1 )
{
logisticfit4ec(&x, &y, n, hqrnduniformr(&rs, _state)-0.5, hqrnduniformr(&rs, _state)-0.5, &a, &b, &c, &d, &rep, _state);
g = 1.0;
}
if( k==2 )
{
logisticfit5(&x, &y, n, &a, &b, &c, &d, &g, &rep, _state);
}
if( k==3 )
{
logisticfit5ec(&x, &y, n, hqrnduniformr(&rs, _state)-0.5, hqrnduniformr(&rs, _state)-0.5, &a, &b, &c, &d, &g, &rep, _state);
}
k = 0;
erms = (double)(0);
eavg = (double)(0);
eavgrel = (double)(0);
emax = (double)(0);
rss = 0.0;
tss = 0.0;
for(i=0; i<=n-1; i++)
{
if( ae_fp_neq(x.ptr.p_double[i],(double)(0)) )
{
v = d+(a-d)/ae_pow(1.0+ae_pow(x.ptr.p_double[i]/c, b, _state), g, _state);
}
else
{
if( ae_fp_greater_eq(b,(double)(0)) )
{
v = a;
}
else
{
v = d;
}
}
v = v-y.ptr.p_double[i];
rss = rss+v*v;
tss = tss+ae_sqr(y.ptr.p_double[i]-meany, _state);
erms = erms+ae_sqr(v, _state);
eavg = eavg+ae_fabs(v, _state);
if( ae_fp_neq(y.ptr.p_double[i],(double)(0)) )
{
eavgrel = eavgrel+ae_fabs(v/y.ptr.p_double[i], _state);
k = k+1;
}
emax = ae_maxreal(emax, ae_fabs(v, _state), _state);
}
er2 = 1.0-rss/tss;
erms = ae_sqrt(erms/n, _state);
eavg = eavg/n;
if( k>0 )
{
eavgrel = eavgrel/k;
}
ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(erms-rep.rmserror, _state),tol), __FILE__, __LINE__, "testlsfitunit.ap:2477");
ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(eavg-rep.avgerror, _state),tol), __FILE__, __LINE__, "testlsfitunit.ap:2478");
ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(emax-rep.maxerror, _state),tol), __FILE__, __LINE__, "testlsfitunit.ap:2479");
ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(eavgrel-rep.avgrelerror, _state),tol), __FILE__, __LINE__, "testlsfitunit.ap:2480");
ae_set_error_flag(fiterrors, ae_fp_greater(ae_fabs(er2-rep.r2, _state),tol), __FILE__, __LINE__, "testlsfitunit.ap:2481");
}
/*
* Test previously fixed bug #834
*/
ae_vector_set_length(&x, 0, _state);
testlsfitunit_append10(&x, 0.019556, 0.093533, 0.13780, 0.25210, 0.46373, 0.23997, 0.52861, 0.50526, 0.43401, 0.82270, _state);
testlsfitunit_append10(&x, 0.65746, 0.76479, 0.81512, 0.89031, 1.1959, 1.2032, 1.0671, 1.2350, 1.2954, 1.5422, _state);
testlsfitunit_append10(&x, 1.4306, 1.5628, 1.6774, 1.8053, 1.9866, 2.1446, 2.1740, 2.2574, 2.2662, 2.4035, _state);
testlsfitunit_append10(&x, 2.7225, 2.6500, 2.7752, 2.9126, 2.8962, 3.0439, 3.1260, 3.2458, 3.3613, 3.3728, _state);
testlsfitunit_append10(&x, 3.5641, 3.5168, 3.6975, 3.7848, 3.8421, 3.9058, 4.0292, 4.1111, 4.0835, 4.3436, _state);
testlsfitunit_append10(&x, 4.3982, 4.6098, 4.3606, 4.5595, 4.7099, 4.8806, 4.9779, 4.9909, 5.0121, 5.2571, _state);
testlsfitunit_append10(&x, 5.3663, 5.4739, 5.5818, 5.5224, 5.7895, 5.9141, 6.0897, 6.1476, 6.2491, 6.3541, _state);
testlsfitunit_append10(&x, 6.4007, 6.5969, 6.6530, 6.7837, 6.8692, 6.9383, 7.0344, 7.1702, 7.3118, 7.3728, _state);
testlsfitunit_append10(&x, 7.4589, 7.6068, 7.6290, 7.8139, 7.9891, 8.0425, 8.1817, 8.3442, 8.3772, 8.4691, _state);
testlsfitunit_append10(&x, 8.5864, 8.7201, 8.9721, 8.9208, 9.0603, 9.1961, 9.3344, 9.3738, 9.4808, 9.6527, _state);
testlsfitunit_append10(&x, 9.7197, 9.8180, 10.034, 10.155, 10.205, 10.323, 10.421, 10.571, 10.723, 10.795, _state);
testlsfitunit_append10(&x, 11.000, 10.977, 11.145, 11.249, 11.425, 11.495, 11.598, 11.723, 11.787, 12.001, _state);
testlsfitunit_append10(&x, 12.005, 12.136, 12.312, 12.381, 12.417, 12.645, 12.766, 12.864, 12.889, 13.017, _state);
testlsfitunit_append10(&x, 13.171, 13.323, 13.406, 13.451, 13.551, 13.732, 13.735, 13.909, 14.075, 14.150, _state);
testlsfitunit_append10(&x, 14.265, 14.365, 14.524, 14.541, 14.679, 14.836, 14.998, 15.071, 15.170, 15.238, _state);
testlsfitunit_append10(&x, 15.327, 15.388, 15.614, 15.729, 15.671, 15.858, 15.984, 16.008, 16.219, 16.231, _state);
testlsfitunit_append10(&x, 16.424, 16.642, 16.784, 16.837, 16.959, 17.000, 17.088, 17.162, 17.210, 17.460, _state);
testlsfitunit_append10(&x, 17.597, 17.698, 17.679, 17.962, 17.974, 17.966, 18.240, 18.240, 18.521, 18.645, _state);
testlsfitunit_append10(&x, 18.739, 18.830, 18.749, 19.062, 19.062, 19.160, 19.224, 19.334, 19.395, 19.567, _state);
ae_vector_set_length(&y, 0, _state);
testlsfitunit_append10(&y, 0.096932, 0.099305, 0.098981, 0.098981, 0.099898, 0.096879, 0.098334, 0.097525, 0.097418, 0.098065, _state);
testlsfitunit_append10(&y, 0.098334, 0.096016, 0.098172, 0.096339, 0.098550, 0.098927, 0.099898, 0.098927, 0.097472, 0.097418, _state);
testlsfitunit_append10(&y, 0.098604, 0.097849, 0.096932, 0.098765, 0.097957, 0.099143, 0.097795, 0.098819, 0.098550, 0.098658, _state);
testlsfitunit_append10(&y, 0.099143, 0.096609, 0.099358, 0.099358, 0.100110, 0.098819, 0.097148, 0.098604, 0.095692, 0.097849, _state);
testlsfitunit_append10(&y, 0.098172, 0.097957, 0.099898, 0.097687, 0.097364, 0.098226, 0.098280, 0.099844, 0.099143, 0.098765, _state);
testlsfitunit_append10(&y, 0.099412, 0.098442, 0.100110, 0.098172, 0.098334, 0.096932, 0.097687, 0.098981, 0.098873, 0.096501, _state);
testlsfitunit_append10(&y, 0.098550, 0.099682, 0.100170, 0.098927, 0.099628, 0.099628, 0.099197, 0.099089, 0.098550, 0.098819, _state);
testlsfitunit_append10(&y, 0.099035, 0.097202, 0.099736, 0.099628, 0.099035, 0.099035, 0.099305, 0.097795, 0.099143, 0.100060, _state);
testlsfitunit_append10(&y, 0.098442, 0.099951, 0.098065, 0.099628, 0.098388, 0.099898, 0.098873, 0.099520, 0.097795, 0.097687, _state);
testlsfitunit_append10(&y, 0.098658, 0.098765, 0.099628, 0.099736, 0.098388, 0.099628, 0.099251, 0.098334, 0.097903, 0.099682, _state);
testlsfitunit_append10(&y, 0.097094, 0.098765, 0.098765, 0.098981, 0.099574, 0.099736, 0.098280, 0.099520, 0.099466, 0.099790, _state);
testlsfitunit_append10(&y, 0.099358, 0.098873, 0.097579, 0.099143, 0.099951, 0.099035, 0.097256, 0.098765, 0.099520, 0.099790, _state);
testlsfitunit_append10(&y, 0.097094, 0.099520, 0.099305, 0.098765, 0.098604, 0.099790, 0.098226, 0.099251, 0.098819, 0.099574, _state);
testlsfitunit_append10(&y, 0.099682, 0.099951, 0.098119, 0.100220, 0.099197, 0.098334, 0.099035, 0.098927, 0.099628, 0.10076, _state);
testlsfitunit_append10(&y, 0.10081, 0.10351, 0.10367, 0.10405, 0.10502, 0.10815, 0.11208, 0.11451, 0.11467, 0.11639, _state);
testlsfitunit_append10(&y, 0.11839, 0.12195, 0.12378, 0.12577, 0.12755, 0.12842, 0.13262, 0.13747, 0.14486, 0.15483, _state);
testlsfitunit_append10(&y, 0.17554, 0.20422, 0.23796, 0.27581, 0.31495, 0.35576, 0.39857, 0.44374, 0.48946, 0.53475, _state);
testlsfitunit_append10(&y, 0.57766, 0.61960, 0.65400, 0.68936, 0.72268, 0.75573, 0.78446, 0.81169, 0.83185, 0.86247, _state);
testlsfitunit_append10(&y, 0.88797, 0.91083, 0.93142, 0.94916, 0.96463, 0.97881, 0.98809, 0.99774, 0.99844, 1.00000, _state);
logisticfit4(&x, &y, 190, &a, &b, &c, &d, &rep, _state);
ae_set_error_flag(fiterrors, ae_fp_less(b,31.90)||ae_fp_greater(b,32.00), __FILE__, __LINE__, "testlsfitunit.ap:2528");
ae_set_error_flag(fiterrors, ae_fp_greater(rep.rmserror,0.02), __FILE__, __LINE__, "testlsfitunit.ap:2529");
logisticfit5(&x, &y, 190, &a, &b, &c, &d, &g, &rep2, _state);
ae_set_error_flag(fiterrors, ae_fp_greater(rep2.rmserror,0.95*rep.rmserror), __FILE__, __LINE__, "testlsfitunit.ap:2531");
ae_frame_leave(_state);
}
/*************************************************************************
Test for box constrained problemsNLS.
On failure sets error flag, leaves it unchanged on success.
*************************************************************************/
static void testlsfitunit_testbcnls(ae_bool* errorflag, ae_state *_state)
{
ae_frame _frame_block;
lsfitstate state;
lsfitreport rep;
ae_vector bl;
ae_vector bu;
ae_int_t nx;
ae_int_t nc;
ae_int_t m;
ae_vector x;
ae_vector c0;
ae_vector c1;
ae_vector c2;
ae_matrix xx;
ae_vector y;
ae_int_t i;
ae_int_t j;
ae_int_t ii;
double v;
double h;
hqrndstate rs;
double epsx;
double f0;
double f1;
ae_int_t tmpkind;
ae_int_t terminationtype;
ae_frame_make(_state, &_frame_block);
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&bl, 0, sizeof(bl));
memset(&bu, 0, sizeof(bu));
memset(&x, 0, sizeof(x));
memset(&c0, 0, sizeof(c0));
memset(&c1, 0, sizeof(c1));
memset(&c2, 0, sizeof(c2));
memset(&xx, 0, sizeof(xx));
memset(&y, 0, sizeof(y));
memset(&rs, 0, sizeof(rs));
_lsfitstate_init(&state, _state, ae_true);
_lsfitreport_init(&rep, _state, ae_true);
ae_vector_init(&bl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&c0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&c1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&c2, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xx, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Fit
*
* [ ]
* f(X|C)= SUM_j[ (alpha*c_j+power(c_j,3))*x_j ]
* [ ]
*
* subject to non-negativity constraints on c_j
*/
epsx = 1.0E-9;
for(tmpkind=0; tmpkind<=1; tmpkind++)
{
for(nc=1; nc<=20; nc++)
{
nx = nc;
m = nc+hqrnduniformi(&rs, nc, _state);
ae_vector_set_length(&bl, nc, _state);
ae_vector_set_length(&bu, nc, _state);
ae_vector_set_length(&c0, nc, _state);
ae_vector_set_length(&x, nx, _state);
for(i=0; i<=nc-1; i++)
{
bl.ptr.p_double[i] = (double)(0);
bu.ptr.p_double[i] = _state->v_posinf;
c0.ptr.p_double[i] = 1+hqrnduniformr(&rs, _state);
}
ae_matrix_set_length(&xx, m, nx, _state);
ae_vector_set_length(&y, m, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=nx-1; j++)
{
xx.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
y.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
if( tmpkind==0 )
{
lsfitcreatef(&xx, &y, &c0, m, nx, nc, 10*epsx, &state, _state);
}
if( tmpkind==1 )
{
lsfitcreatefg(&xx, &y, &c0, m, nx, nc, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &state, _state);
}
lsfitsetcond(&state, epsx, 0, _state);
lsfitsetbc(&state, &bl, &bu, _state);
while(lsfititeration(&state, _state))
{
for(i=0; i<=nc-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_less(state.c.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2603");
ae_set_error_flag(errorflag, ae_fp_greater(state.c.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2604");
}
if( state.needf )
{
testlsfitunit_testfunc1(nx, &state.x, &state.c, &state.f, ae_true, &state.g, ae_false, _state);
continue;
}
if( state.needfg )
{
testlsfitunit_testfunc1(nx, &state.x, &state.c, &state.f, ae_true, &state.g, ae_true, _state);
continue;
}
ae_assert(ae_false, "minlm test: integrity check failed", _state);
}
lsfitresults(&state, &terminationtype, &c1, &rep, _state);
ae_set_error_flag(errorflag, terminationtype<=0, __FILE__, __LINE__, "testlsfitunit.ap:2619");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
f0 = (double)(0);
for(ii=0; ii<=m-1; ii++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1));
testlsfitunit_testfunc1(nx, &x, &c1, &v, ae_true, &state.g, ae_false, _state);
f0 = f0+ae_sqr(v-y.ptr.p_double[ii], _state);
}
h = 0.001;
ae_vector_set_length(&c2, nc, _state);
for(i=0; i<=nc-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_less(c1.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2636");
ae_set_error_flag(errorflag, ae_fp_greater(c1.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2637");
if( ae_fp_greater_eq(c1.ptr.p_double[i]+h,bl.ptr.p_double[i]) )
{
for(j=0; j<=nc-1; j++)
{
c2.ptr.p_double[j] = c1.ptr.p_double[j];
}
c2.ptr.p_double[i] = c2.ptr.p_double[i]+h;
f1 = (double)(0);
for(ii=0; ii<=m-1; ii++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1));
testlsfitunit_testfunc1(nx, &x, &c2, &v, ae_true, &state.g, ae_false, _state);
f1 = f1+ae_sqr(v-y.ptr.p_double[ii], _state);
}
ae_set_error_flag(errorflag, ae_fp_less(f1,f0), __FILE__, __LINE__, "testlsfitunit.ap:2652");
}
if( ae_fp_greater_eq(c1.ptr.p_double[i]-h,bl.ptr.p_double[i]) )
{
for(j=0; j<=nc-1; j++)
{
c2.ptr.p_double[j] = c1.ptr.p_double[j];
}
c2.ptr.p_double[i] = c2.ptr.p_double[i]-h;
f1 = (double)(0);
for(ii=0; ii<=m-1; ii++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1));
testlsfitunit_testfunc1(nx, &x, &c2, &v, ae_true, &state.g, ae_false, _state);
f1 = f1+ae_sqr(v-y.ptr.p_double[ii], _state);
}
ae_set_error_flag(errorflag, ae_fp_less(f1,f0), __FILE__, __LINE__, "testlsfitunit.ap:2668");
}
}
}
}
/*
* Fit
*
* [ ]
* f(X|C)= SUM_j[ (alpha*c_j+power(c_j,3))*x_j ]
* [ ]
*
* subject to random box constraints on c_j
*/
epsx = 1.0E-9;
for(tmpkind=0; tmpkind<=1; tmpkind++)
{
for(nc=1; nc<=20; nc++)
{
nx = nc;
m = nc+hqrnduniformi(&rs, nc, _state);
ae_vector_set_length(&bl, nc, _state);
ae_vector_set_length(&bu, nc, _state);
ae_vector_set_length(&c0, nc, _state);
ae_vector_set_length(&x, nx, _state);
for(i=0; i<=nc-1; i++)
{
bl.ptr.p_double[i] = hqrndnormal(&rs, _state);
bu.ptr.p_double[i] = bl.ptr.p_double[i]+hqrnduniformr(&rs, _state);
c0.ptr.p_double[i] = 1+hqrnduniformr(&rs, _state);
}
ae_matrix_set_length(&xx, m, nx, _state);
ae_vector_set_length(&y, m, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=nx-1; j++)
{
xx.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
y.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
if( tmpkind==0 )
{
lsfitcreatef(&xx, &y, &c0, m, nx, nc, 10*epsx, &state, _state);
}
if( tmpkind==1 )
{
lsfitcreatefg(&xx, &y, &c0, m, nx, nc, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &state, _state);
}
lsfitsetcond(&state, epsx, 0, _state);
lsfitsetbc(&state, &bl, &bu, _state);
while(lsfititeration(&state, _state))
{
for(i=0; i<=nc-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_less(state.c.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2717");
ae_set_error_flag(errorflag, ae_fp_greater(state.c.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2718");
}
if( state.needf )
{
testlsfitunit_testfunc1(nx, &state.x, &state.c, &state.f, ae_true, &state.g, ae_false, _state);
continue;
}
if( state.needfg )
{
testlsfitunit_testfunc1(nx, &state.x, &state.c, &state.f, ae_true, &state.g, ae_true, _state);
continue;
}
ae_assert(ae_false, "minlm test: integrity check failed", _state);
}
lsfitresults(&state, &terminationtype, &c1, &rep, _state);
ae_set_error_flag(errorflag, terminationtype<=0, __FILE__, __LINE__, "testlsfitunit.ap:2733");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
f0 = (double)(0);
for(ii=0; ii<=m-1; ii++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1));
testlsfitunit_testfunc1(nx, &x, &c1, &v, ae_true, &state.g, ae_false, _state);
f0 = f0+ae_sqr(v-y.ptr.p_double[ii], _state);
}
h = 0.001;
ae_vector_set_length(&c2, nc, _state);
for(i=0; i<=nc-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_less(c1.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2750");
ae_set_error_flag(errorflag, ae_fp_greater(c1.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2751");
if( ae_fp_greater_eq(c1.ptr.p_double[i]+h,bl.ptr.p_double[i])&&ae_fp_less_eq(c1.ptr.p_double[i]+h,bu.ptr.p_double[i]) )
{
for(j=0; j<=nc-1; j++)
{
c2.ptr.p_double[j] = c1.ptr.p_double[j];
}
c2.ptr.p_double[i] = c2.ptr.p_double[i]+h;
f1 = (double)(0);
for(ii=0; ii<=m-1; ii++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1));
testlsfitunit_testfunc1(nx, &x, &c2, &v, ae_true, &state.g, ae_false, _state);
f1 = f1+ae_sqr(v-y.ptr.p_double[ii], _state);
}
ae_set_error_flag(errorflag, ae_fp_less(f1,f0), __FILE__, __LINE__, "testlsfitunit.ap:2766");
}
if( ae_fp_greater_eq(c1.ptr.p_double[i]-h,bl.ptr.p_double[i])&&ae_fp_less_eq(c1.ptr.p_double[i]-h,bu.ptr.p_double[i]) )
{
for(j=0; j<=nc-1; j++)
{
c2.ptr.p_double[j] = c1.ptr.p_double[j];
}
c2.ptr.p_double[i] = c2.ptr.p_double[i]-h;
f1 = (double)(0);
for(ii=0; ii<=m-1; ii++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1));
testlsfitunit_testfunc1(nx, &x, &c2, &v, ae_true, &state.g, ae_false, _state);
f1 = f1+ae_sqr(v-y.ptr.p_double[ii], _state);
}
ae_set_error_flag(errorflag, ae_fp_less(f1,f0), __FILE__, __LINE__, "testlsfitunit.ap:2782");
}
}
}
}
/*
* Fit
*
*
* f(X|C)= c_0
*
*
* subject to random box constraints on c_0, where X is N-dimensional vector
* (f does not depend on X, and it is not an error! we just test that sizes
* of X and C are correctly handled).
*/
epsx = 1.0E-9;
for(tmpkind=0; tmpkind<=1; tmpkind++)
{
for(nx=1; nx<=20; nx++)
{
nc = 1;
m = nx+hqrnduniformi(&rs, nx, _state);
ae_vector_set_length(&bl, nc, _state);
ae_vector_set_length(&bu, nc, _state);
ae_vector_set_length(&c0, nc, _state);
ae_vector_set_length(&x, nx, _state);
for(i=0; i<=nc-1; i++)
{
bl.ptr.p_double[i] = hqrndnormal(&rs, _state);
bu.ptr.p_double[i] = bl.ptr.p_double[i]+hqrnduniformr(&rs, _state);
c0.ptr.p_double[i] = 1+hqrnduniformr(&rs, _state);
}
ae_matrix_set_length(&xx, m, nx, _state);
ae_vector_set_length(&y, m, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=nx-1; j++)
{
xx.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
y.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
if( tmpkind==0 )
{
lsfitcreatef(&xx, &y, &c0, m, nx, nc, 10*epsx, &state, _state);
}
if( tmpkind==1 )
{
lsfitcreatefg(&xx, &y, &c0, m, nx, nc, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &state, _state);
}
lsfitsetcond(&state, epsx, 0, _state);
lsfitsetbc(&state, &bl, &bu, _state);
while(lsfititeration(&state, _state))
{
for(i=0; i<=nc-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_less(state.c.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2833");
ae_set_error_flag(errorflag, ae_fp_greater(state.c.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2834");
}
if( state.needf )
{
testlsfitunit_testfunc2(&state.x, nx, &state.c, nc, &state.f, ae_true, &state.g, ae_false, _state);
continue;
}
if( state.needfg )
{
testlsfitunit_testfunc2(&state.x, nx, &state.c, nc, &state.f, ae_true, &state.g, ae_true, _state);
continue;
}
ae_assert(ae_false, "minlm test: integrity check failed", _state);
}
lsfitresults(&state, &terminationtype, &c1, &rep, _state);
ae_set_error_flag(errorflag, terminationtype<=0, __FILE__, __LINE__, "testlsfitunit.ap:2849");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
f0 = (double)(0);
for(ii=0; ii<=m-1; ii++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1));
testlsfitunit_testfunc2(&x, nx, &c1, nc, &v, ae_true, &state.g, ae_false, _state);
f0 = f0+ae_sqr(v-y.ptr.p_double[ii], _state);
}
h = 0.001;
ae_vector_set_length(&c2, nc, _state);
for(i=0; i<=nc-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_less(c1.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2866");
ae_set_error_flag(errorflag, ae_fp_greater(c1.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2867");
if( ae_fp_greater_eq(c1.ptr.p_double[i]+h,bl.ptr.p_double[i])&&ae_fp_less_eq(c1.ptr.p_double[i]+h,bu.ptr.p_double[i]) )
{
for(j=0; j<=nc-1; j++)
{
c2.ptr.p_double[j] = c1.ptr.p_double[j];
}
c2.ptr.p_double[i] = c2.ptr.p_double[i]+h;
f1 = (double)(0);
for(ii=0; ii<=m-1; ii++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1));
testlsfitunit_testfunc2(&x, nx, &c2, nc, &v, ae_true, &state.g, ae_false, _state);
f1 = f1+ae_sqr(v-y.ptr.p_double[ii], _state);
}
ae_set_error_flag(errorflag, ae_fp_less(f1,f0), __FILE__, __LINE__, "testlsfitunit.ap:2882");
}
if( ae_fp_greater_eq(c1.ptr.p_double[i]-h,bl.ptr.p_double[i])&&ae_fp_less_eq(c1.ptr.p_double[i]-h,bu.ptr.p_double[i]) )
{
for(j=0; j<=nc-1; j++)
{
c2.ptr.p_double[j] = c1.ptr.p_double[j];
}
c2.ptr.p_double[i] = c2.ptr.p_double[i]-h;
f1 = (double)(0);
for(ii=0; ii<=m-1; ii++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1));
testlsfitunit_testfunc2(&x, nx, &c2, nc, &v, ae_true, &state.g, ae_false, _state);
f1 = f1+ae_sqr(v-y.ptr.p_double[ii], _state);
}
ae_set_error_flag(errorflag, ae_fp_less(f1,f0), __FILE__, __LINE__, "testlsfitunit.ap:2898");
}
}
}
}
/*
* Fit
*
*
* f(X|C)= c_0 + c_1*x0 + c_2*x0^2 + ...
*
*
* subject to random box constraints on c.
*/
epsx = 1.0E-9;
for(tmpkind=0; tmpkind<=1; tmpkind++)
{
for(nc=1; nc<=5; nc++)
{
nx = 1;
m = 10+nc+hqrnduniformi(&rs, nc, _state);
ae_vector_set_length(&bl, nc, _state);
ae_vector_set_length(&bu, nc, _state);
ae_vector_set_length(&c0, nc, _state);
ae_vector_set_length(&x, nx, _state);
for(i=0; i<=nc-1; i++)
{
bl.ptr.p_double[i] = hqrndnormal(&rs, _state);
bu.ptr.p_double[i] = bl.ptr.p_double[i]+hqrnduniformr(&rs, _state);
c0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_matrix_set_length(&xx, m, nx, _state);
ae_vector_set_length(&y, m, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=nx-1; j++)
{
xx.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
y.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
if( tmpkind==0 )
{
lsfitcreatef(&xx, &y, &c0, m, nx, nc, 10*epsx, &state, _state);
}
if( tmpkind==1 )
{
lsfitcreatefg(&xx, &y, &c0, m, nx, nc, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &state, _state);
}
lsfitsetcond(&state, epsx, 0, _state);
lsfitsetbc(&state, &bl, &bu, _state);
while(lsfititeration(&state, _state))
{
for(i=0; i<=nc-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_less(state.c.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2947");
ae_set_error_flag(errorflag, ae_fp_greater(state.c.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2948");
}
if( state.needf )
{
testlsfitunit_testfunc3(&state.x, nx, &state.c, nc, &state.f, ae_true, &state.g, ae_false, _state);
continue;
}
if( state.needfg )
{
testlsfitunit_testfunc3(&state.x, nx, &state.c, nc, &state.f, ae_true, &state.g, ae_true, _state);
continue;
}
ae_assert(ae_false, "minlm test: integrity check failed", _state);
}
lsfitresults(&state, &terminationtype, &c1, &rep, _state);
ae_set_error_flag(errorflag, terminationtype<=0, __FILE__, __LINE__, "testlsfitunit.ap:2963");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
f0 = (double)(0);
for(ii=0; ii<=m-1; ii++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1));
testlsfitunit_testfunc3(&x, nx, &c1, nc, &v, ae_true, &state.g, ae_false, _state);
f0 = f0+ae_sqr(v-y.ptr.p_double[ii], _state);
}
h = 0.001;
ae_vector_set_length(&c2, nc, _state);
for(i=0; i<=nc-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_less(c1.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2980");
ae_set_error_flag(errorflag, ae_fp_greater(c1.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:2981");
if( ae_fp_greater_eq(c1.ptr.p_double[i]+h,bl.ptr.p_double[i])&&ae_fp_less_eq(c1.ptr.p_double[i]+h,bu.ptr.p_double[i]) )
{
for(j=0; j<=nc-1; j++)
{
c2.ptr.p_double[j] = c1.ptr.p_double[j];
}
c2.ptr.p_double[i] = c2.ptr.p_double[i]+h;
f1 = (double)(0);
for(ii=0; ii<=m-1; ii++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1));
testlsfitunit_testfunc3(&x, nx, &c2, nc, &v, ae_true, &state.g, ae_false, _state);
f1 = f1+ae_sqr(v-y.ptr.p_double[ii], _state);
}
ae_set_error_flag(errorflag, ae_fp_less(f1,f0), __FILE__, __LINE__, "testlsfitunit.ap:2996");
}
if( ae_fp_greater_eq(c1.ptr.p_double[i]-h,bl.ptr.p_double[i])&&ae_fp_less_eq(c1.ptr.p_double[i]-h,bu.ptr.p_double[i]) )
{
for(j=0; j<=nc-1; j++)
{
c2.ptr.p_double[j] = c1.ptr.p_double[j];
}
c2.ptr.p_double[i] = c2.ptr.p_double[i]-h;
f1 = (double)(0);
for(ii=0; ii<=m-1; ii++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1));
testlsfitunit_testfunc3(&x, nx, &c2, nc, &v, ae_true, &state.g, ae_false, _state);
f1 = f1+ae_sqr(v-y.ptr.p_double[ii], _state);
}
ae_set_error_flag(errorflag, ae_fp_less(f1,f0), __FILE__, __LINE__, "testlsfitunit.ap:3012");
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Test for linearly constrained NLS problems.
On failure sets error flag, leaves it unchanged on success.
*************************************************************************/
static void testlsfitunit_testlcnls(ae_bool* errorflag, ae_state *_state)
{
ae_frame _frame_block;
lsfitstate state;
lsfitreport rep;
ae_vector bl;
ae_vector bu;
ae_int_t nx;
ae_int_t nc;
ae_int_t m;
ae_vector x;
ae_vector y;
ae_vector c0;
ae_vector c1;
ae_vector c2;
ae_matrix rawc;
ae_vector rawct;
ae_int_t rawccnt;
ae_matrix xx;
ae_matrix xx12;
ae_matrix z;
ae_int_t trialidx;
ae_int_t i;
ae_int_t j;
ae_int_t ii;
double v;
double h;
ae_int_t optkind;
hqrndstate rs;
double epsx;
double xtol;
double f0;
double f1;
ae_bool bflag;
ae_int_t terminationtype;
ae_frame_make(_state, &_frame_block);
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&bl, 0, sizeof(bl));
memset(&bu, 0, sizeof(bu));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&c0, 0, sizeof(c0));
memset(&c1, 0, sizeof(c1));
memset(&c2, 0, sizeof(c2));
memset(&rawc, 0, sizeof(rawc));
memset(&rawct, 0, sizeof(rawct));
memset(&xx, 0, sizeof(xx));
memset(&xx12, 0, sizeof(xx12));
memset(&z, 0, sizeof(z));
memset(&rs, 0, sizeof(rs));
_lsfitstate_init(&state, _state, ae_true);
_lsfitreport_init(&rep, _state, ae_true);
ae_vector_init(&bl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bu, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&c0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&c1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&c2, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&rawc, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rawct, 0, DT_INT, _state, ae_true);
ae_matrix_init(&xx, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xx12, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Minimize
*
* [ [ ]2 ]
* SUM_i[ SUM_j[ (0.1*x_j+power(x_j,3))*c_ij ] ]
* [ [ ] ]
*
* subject to mix of box and linear inequality constraints on x_j
*
* We check correctness of solution by sampling a few random points
* around one returned by optimizer, and comparing function value
* with target. Sampling is performed with respect to inequality
* constraints.
*/
epsx = 1.0E-12;
xtol = 1.0E-8;
optkind = 1;
for(nc=5; nc<=20; nc++)
{
/*
* Generate problem
*/
nx = nc;
m = nc+hqrnduniformi(&rs, nc, _state);
ae_vector_set_length(&bl, nc, _state);
ae_vector_set_length(&bu, nc, _state);
ae_vector_set_length(&c0, nc, _state);
ae_vector_set_length(&x, nx, _state);
for(i=0; i<=nc-1; i++)
{
bl.ptr.p_double[i] = hqrndnormal(&rs, _state);
bu.ptr.p_double[i] = bl.ptr.p_double[i]+0.01+hqrnduniformr(&rs, _state);
c0.ptr.p_double[i] = bl.ptr.p_double[i]+(bu.ptr.p_double[i]-bl.ptr.p_double[i])*hqrnduniformr(&rs, _state);
}
ae_matrix_set_length(&xx, m, nx, _state);
ae_vector_set_length(&y, m, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=nx-1; j++)
{
xx.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
y.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_assert(nc>=5, "Assertion failed", _state);
rawccnt = 3;
ae_matrix_set_length(&rawc, rawccnt, nc+1, _state);
ae_vector_set_length(&rawct, rawccnt, _state);
for(i=0; i<=rawccnt-1; i++)
{
v = (double)(0);
for(j=0; j<=nc-1; j++)
{
rawc.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
v = v+c0.ptr.p_double[j]*rawc.ptr.pp_double[i][j];
}
rawc.ptr.pp_double[i][nc] = v;
rawct.ptr.p_int[i] = 2*hqrnduniformi(&rs, 2, _state)-1;
}
/*
* Solve
*/
if( optkind==0 )
{
lsfitcreatef(&xx, &y, &c0, m, nx, nc, 1.0E-6, &state, _state);
}
if( optkind==1 )
{
lsfitcreatefg(&xx, &y, &c0, m, nx, nc, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &state, _state);
}
lsfitsetcond(&state, epsx, 0, _state);
lsfitsetbc(&state, &bl, &bu, _state);
lsfitsetlc(&state, &rawc, &rawct, rawccnt, _state);
while(lsfititeration(&state, _state))
{
for(i=0; i<=nc-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_less(state.c.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:3121");
ae_set_error_flag(errorflag, ae_fp_greater(state.c.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:3122");
}
if( state.needf )
{
testlsfitunit_testfunc1(nx, &state.x, &state.c, &state.f, ae_true, &state.g, ae_false, _state);
continue;
}
if( state.needfg )
{
testlsfitunit_testfunc1(nx, &state.x, &state.c, &state.f, ae_true, &state.g, ae_true, _state);
continue;
}
ae_assert(ae_false, "lsfit test: integrity check failed", _state);
}
lsfitresults(&state, &terminationtype, &c1, &rep, _state);
ae_set_error_flag(errorflag, terminationtype<=0, __FILE__, __LINE__, "testlsfitunit.ap:3137");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
/*
* Test feasibility w.r.t. box and linear inequality constraints
*/
for(i=0; i<=nc-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_less(c1.ptr.p_double[i],bl.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:3146");
ae_set_error_flag(errorflag, ae_fp_greater(c1.ptr.p_double[i],bu.ptr.p_double[i]), __FILE__, __LINE__, "testlsfitunit.ap:3147");
}
for(i=0; i<=rawccnt-1; i++)
{
v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &c1.ptr.p_double[0], 1, ae_v_len(0,nc-1));
v = v-rawc.ptr.pp_double[i][nc];
if( rawct.ptr.p_int[i]>0 )
{
ae_set_error_flag(errorflag, ae_fp_less(v,-xtol), __FILE__, __LINE__, "testlsfitunit.ap:3154");
}
if( rawct.ptr.p_int[i]<0 )
{
ae_set_error_flag(errorflag, ae_fp_greater(v,xtol), __FILE__, __LINE__, "testlsfitunit.ap:3156");
}
}
/*
* Make several random trial steps and:
* 0) generate small random trial step
* 1) if step is infeasible, skip to next trial
* 2) compare function value in the trial point against one in other points
*/
f0 = (double)(0);
for(ii=0; ii<=m-1; ii++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1));
testlsfitunit_testfunc1(nx, &x, &c1, &v, ae_true, &state.g, ae_false, _state);
f0 = f0+ae_sqr(v-y.ptr.p_double[ii], _state);
}
ae_vector_set_length(&c2, nc, _state);
for(trialidx=0; trialidx<=10*nc; trialidx++)
{
h = 0.001;
for(i=0; i<=nc-1; i++)
{
do
{
c2.ptr.p_double[i] = c1.ptr.p_double[i]+(hqrnduniformr(&rs, _state)*2-1)*h;
}
while(!(ae_fp_greater_eq(c2.ptr.p_double[i],bl.ptr.p_double[i])&&ae_fp_less_eq(c2.ptr.p_double[i],bu.ptr.p_double[i])));
}
bflag = ae_false;
for(i=0; i<=rawccnt-1; i++)
{
ae_assert(rawct.ptr.p_int[i]!=0, "Assertion failed", _state);
v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &c2.ptr.p_double[0], 1, ae_v_len(0,nc-1));
v = v-rawc.ptr.pp_double[i][nc];
bflag = bflag||(rawct.ptr.p_int[i]>0&&ae_fp_less(v,(double)(0)));
bflag = bflag||(rawct.ptr.p_int[i]<0&&ae_fp_greater(v,(double)(0)));
}
if( bflag )
{
continue;
}
f1 = (double)(0);
for(ii=0; ii<=m-1; ii++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1));
testlsfitunit_testfunc1(nx, &x, &c2, &v, ae_true, &state.g, ae_false, _state);
f1 = f1+ae_sqr(v-y.ptr.p_double[ii], _state);
}
ae_set_error_flag(errorflag, ae_fp_less(f1,f0), __FILE__, __LINE__, "testlsfitunit.ap:3205");
}
}
/*
* Minimize
*
* [ [ ]2 ]
* SUM_i[ SUM_j[ (0.1*x_j+power(x_j,3))*c_ij ] ]
* [ [ ] ]
*
* subject to linear EQUALITY constraints on x_j.
*
* We check correctness of solution by sampling a few random points
* around one returned by optimizer, and comparing function value
* with target. Sampling is performed with respect to equality
* constraints. In order to simplify algorithm we use orthogonal
* equality constraints.
*
* NOTE: we solve problem using VJ mode (analytic Jacobian) because
* roundoff errors from numerical differentiation sometimes
* prevent us from converging with good precision.
*/
epsx = 1.0E-12;
xtol = 1.0E-8;
optkind = 1;
for(nc=10; nc<=20; nc++)
{
/*
* Generate problem
*/
nx = nc;
m = nc+hqrnduniformi(&rs, nc, _state);
ae_vector_set_length(&c0, nc, _state);
for(i=0; i<=nc-1; i++)
{
c0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_matrix_set_length(&xx, m, nx, _state);
ae_vector_set_length(&y, m, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=nx-1; j++)
{
xx.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
y.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_assert(nc>=10, "Assertion failed", _state);
rawccnt = 1+hqrnduniformi(&rs, 5, _state);
rmatrixrndorthogonal(nc, &z, _state);
ae_matrix_set_length(&rawc, rawccnt, nc+1, _state);
ae_vector_set_length(&rawct, rawccnt, _state);
for(i=0; i<=rawccnt-1; i++)
{
v = (double)(0);
for(j=0; j<=nc-1; j++)
{
rawc.ptr.pp_double[i][j] = z.ptr.pp_double[i][j];
v = v+c0.ptr.p_double[j]*rawc.ptr.pp_double[i][j];
}
rawc.ptr.pp_double[i][nc] = v;
rawct.ptr.p_int[i] = 0;
}
/*
* Solve
*/
if( optkind==0 )
{
lsfitcreatef(&xx, &y, &c0, m, nx, nc, 1.0E-6, &state, _state);
}
if( optkind==1 )
{
lsfitcreatefg(&xx, &y, &c0, m, nx, nc, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &state, _state);
}
lsfitsetcond(&state, epsx, 0, _state);
lsfitsetlc(&state, &rawc, &rawct, rawccnt, _state);
while(lsfititeration(&state, _state))
{
if( state.needf )
{
testlsfitunit_testfunc1(nx, &state.x, &state.c, &state.f, ae_true, &state.g, ae_false, _state);
continue;
}
if( state.needfg )
{
testlsfitunit_testfunc1(nx, &state.x, &state.c, &state.f, ae_true, &state.g, ae_true, _state);
continue;
}
ae_assert(ae_false, "lsfit test: integrity check failed", _state);
}
lsfitresults(&state, &terminationtype, &c1, &rep, _state);
ae_set_error_flag(errorflag, terminationtype<=0, __FILE__, __LINE__, "testlsfitunit.ap:3291");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
/*
* Test feasibility w.r.t. linear equality constraints
*/
for(i=0; i<=rawccnt-1; i++)
{
v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &c1.ptr.p_double[0], 1, ae_v_len(0,nc-1));
v = v-rawc.ptr.pp_double[i][nc];
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v, _state),xtol), __FILE__, __LINE__, "testlsfitunit.ap:3302");
}
/*
* Make several random trial steps and:
* 0) generate small random trial step
* 1) project it onto equality constrained subspace
* 2) compare function value in the trial point against one in other points
*/
f0 = (double)(0);
for(ii=0; ii<=m-1; ii++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1));
testlsfitunit_testfunc1(nx, &x, &c1, &v, ae_true, &state.g, ae_false, _state);
f0 = f0+ae_sqr(v-y.ptr.p_double[ii], _state);
}
ae_vector_set_length(&c2, nc, _state);
for(trialidx=0; trialidx<=nc; trialidx++)
{
h = 0.001;
for(i=0; i<=nc-1; i++)
{
c2.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
for(i=0; i<=rawccnt-1; i++)
{
v = ae_v_dotproduct(&rawc.ptr.pp_double[i][0], 1, &c2.ptr.p_double[0], 1, ae_v_len(0,nc-1));
ae_v_subd(&c2.ptr.p_double[0], 1, &rawc.ptr.pp_double[i][0], 1, ae_v_len(0,nc-1), v);
}
v = ae_v_dotproduct(&c2.ptr.p_double[0], 1, &c2.ptr.p_double[0], 1, ae_v_len(0,nc-1));
ae_assert(ae_fp_greater(v,(double)(0)), "Assertion failed", _state);
v = h/ae_sqrt(v, _state);
ae_v_muld(&c2.ptr.p_double[0], 1, ae_v_len(0,nc-1), v);
ae_v_add(&c2.ptr.p_double[0], 1, &c1.ptr.p_double[0], 1, ae_v_len(0,nc-1));
f1 = (double)(0);
for(ii=0; ii<=m-1; ii++)
{
ae_v_move(&x.ptr.p_double[0], 1, &xx.ptr.pp_double[ii][0], 1, ae_v_len(0,nx-1));
testlsfitunit_testfunc1(nx, &x, &c2, &v, ae_true, &state.g, ae_false, _state);
f1 = f1+ae_sqr(v-y.ptr.p_double[ii], _state);
}
ae_set_error_flag(errorflag, ae_fp_less(f1,f0), __FILE__, __LINE__, "testlsfitunit.ap:3344");
}
}
/*
* Fit
*
*
* f(X|C)= c_0
*
*
* subject to single general linear equality constraint on c_0.
*
* Here X has dimensionality NX, and C has dimensionality 1.
*
* We do not test convergence to solution, only feasibility of constraint.
* The aim of this test is to assert that optimizer correctly handles
* situations when dimensions of X and C differ.
*/
epsx = 1.0E-9;
for(optkind=0; optkind<=1; optkind++)
{
for(nx=1; nx<=20; nx++)
{
nc = 1;
m = nx+hqrnduniformi(&rs, nx, _state);
ae_vector_set_length(&c0, nc, _state);
for(i=0; i<=nc-1; i++)
{
c0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_matrix_set_length(&xx, m, nx, _state);
ae_vector_set_length(&y, m, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=nx-1; j++)
{
xx.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
y.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_assert(nc==1, "Assertion failed", _state);
rawccnt = 1;
ae_matrix_set_length(&rawc, 1, 2, _state);
ae_vector_set_length(&rawct, 1, _state);
rawc.ptr.pp_double[0][0] = (double)(1);
rawc.ptr.pp_double[0][1] = hqrndnormal(&rs, _state);
rawct.ptr.p_int[0] = 0;
if( optkind==0 )
{
lsfitcreatef(&xx, &y, &c0, m, nx, nc, 10*epsx, &state, _state);
}
if( optkind==1 )
{
lsfitcreatefg(&xx, &y, &c0, m, nx, nc, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &state, _state);
}
lsfitsetcond(&state, epsx, 0, _state);
lsfitsetlc(&state, &rawc, &rawct, rawccnt, _state);
while(lsfititeration(&state, _state))
{
if( state.needf )
{
testlsfitunit_testfunc2(&state.x, nx, &state.c, nc, &state.f, ae_true, &state.g, ae_false, _state);
continue;
}
if( state.needfg )
{
testlsfitunit_testfunc2(&state.x, nx, &state.c, nc, &state.f, ae_true, &state.g, ae_true, _state);
continue;
}
ae_assert(ae_false, "minlm test: integrity check failed", _state);
}
lsfitresults(&state, &terminationtype, &c1, &rep, _state);
ae_set_error_flag(errorflag, terminationtype<=0, __FILE__, __LINE__, "testlsfitunit.ap:3409");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(c1.ptr.p_double[0]-rawc.ptr.pp_double[0][1], _state),1.0E-6), __FILE__, __LINE__, "testlsfitunit.ap:3414");
}
}
/*
* Fit
*
*
* f(X|C)= c_0 + c_1*x0 + c_2*x0^2 + ...
*
*
* subject to single general linear equality constraint on c.
*
* Here X has dimensionality 1, and C has dimensionality NC.
*
* We do not test convergence to solution, only feasibility of constraint.
* The aim of this test is to assert that optimizer correctly handles
* situations when dimensions of X and C differ.
*/
epsx = 1.0E-9;
for(optkind=0; optkind<=1; optkind++)
{
for(nc=1; nc<=5; nc++)
{
nx = 1;
m = 10+nc+hqrnduniformi(&rs, nc, _state);
ae_vector_set_length(&c0, nc, _state);
for(i=0; i<=nc-1; i++)
{
c0.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_matrix_set_length(&xx, m, nx, _state);
ae_vector_set_length(&y, m, _state);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=nx-1; j++)
{
xx.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
y.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
rawccnt = 1;
ae_matrix_set_length(&rawc, 1, nc+1, _state);
ae_vector_set_length(&rawct, 1, _state);
for(j=0; j<=nc; j++)
{
rawc.ptr.pp_double[0][j] = (2*hqrnduniformi(&rs, 2, _state)-1)*(0.1+hqrnduniformr(&rs, _state));
}
rawct.ptr.p_int[0] = 0;
if( optkind==0 )
{
lsfitcreatef(&xx, &y, &c0, m, nx, nc, 10*epsx, &state, _state);
}
if( optkind==1 )
{
lsfitcreatefg(&xx, &y, &c0, m, nx, nc, ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)), &state, _state);
}
lsfitsetcond(&state, epsx, 0, _state);
lsfitsetlc(&state, &rawc, &rawct, rawccnt, _state);
while(lsfititeration(&state, _state))
{
if( state.needf )
{
testlsfitunit_testfunc3(&state.x, nx, &state.c, nc, &state.f, ae_true, &state.g, ae_false, _state);
continue;
}
if( state.needfg )
{
testlsfitunit_testfunc3(&state.x, nx, &state.c, nc, &state.f, ae_true, &state.g, ae_true, _state);
continue;
}
ae_assert(ae_false, "minlm test: integrity check failed", _state);
}
lsfitresults(&state, &terminationtype, &c1, &rep, _state);
ae_set_error_flag(errorflag, terminationtype<=0, __FILE__, __LINE__, "testlsfitunit.ap:3477");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
v = -rawc.ptr.pp_double[0][nc];
for(j=0; j<=nc-1; j++)
{
v = v+rawc.ptr.pp_double[0][j]*c1.ptr.p_double[j];
}
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(v, _state),1.0E-6), __FILE__, __LINE__, "testlsfitunit.ap:3485");
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Tests whether C is solution of (possibly) constrained LLS problem
*************************************************************************/
static ae_bool testlsfitunit_isglssolution(ae_int_t n,
ae_int_t m,
ae_int_t k,
/* Real */ ae_vector* y,
/* Real */ ae_vector* w,
/* Real */ ae_matrix* fmatrix,
/* Real */ ae_matrix* cmatrix,
/* Real */ ae_vector* c,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector _c;
ae_int_t i;
ae_int_t j;
ae_vector c2;
ae_vector sv;
ae_vector deltac;
ae_vector deltaproj;
ae_matrix u;
ae_matrix vt;
double v;
double s1;
double s2;
double s3;
double delta;
double threshold;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&_c, 0, sizeof(_c));
memset(&c2, 0, sizeof(c2));
memset(&sv, 0, sizeof(sv));
memset(&deltac, 0, sizeof(deltac));
memset(&deltaproj, 0, sizeof(deltaproj));
memset(&u, 0, sizeof(u));
memset(&vt, 0, sizeof(vt));
ae_vector_init_copy(&_c, c, _state, ae_true);
c = &_c;
ae_vector_init(&c2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&sv, 0, DT_REAL, _state, ae_true);
ae_vector_init(&deltac, 0, DT_REAL, _state, ae_true);
ae_vector_init(&deltaproj, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&u, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&vt, 0, 0, DT_REAL, _state, ae_true);
/*
* Setup.
* Threshold is small because CMatrix may be ill-conditioned
*/
delta = 0.001;
threshold = ae_sqrt(ae_machineepsilon, _state);
ae_vector_set_length(&c2, m, _state);
ae_vector_set_length(&deltac, m, _state);
ae_vector_set_length(&deltaproj, m, _state);
/*
* test whether C is feasible point or not (projC must be close to C)
*/
for(i=0; i<=k-1; i++)
{
v = ae_v_dotproduct(&cmatrix->ptr.pp_double[i][0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,m-1));
if( ae_fp_greater(ae_fabs(v-cmatrix->ptr.pp_double[i][m], _state),threshold) )
{
result = ae_false;
ae_frame_leave(_state);
return result;
}
}
/*
* find orthogonal basis of Null(CMatrix) (stored in rows from K to M-1)
*/
if( k>0 )
{
rmatrixsvd(cmatrix, k, m, 0, 2, 2, &sv, &u, &vt, _state);
}
/*
* Test result
*/
result = ae_true;
s1 = testlsfitunit_getglserror(n, m, y, w, fmatrix, c, _state);
for(j=0; j<=m-1; j++)
{
/*
* prepare modification of C which leave us in the feasible set.
*
* let deltaC be increment on Jth coordinate, then project
* deltaC in the Null(CMatrix) and store result in DeltaProj
*/
ae_v_move(&c2.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,m-1));
for(i=0; i<=m-1; i++)
{
if( i==j )
{
deltac.ptr.p_double[i] = delta;
}
else
{
deltac.ptr.p_double[i] = (double)(0);
}
}
if( k==0 )
{
ae_v_move(&deltaproj.ptr.p_double[0], 1, &deltac.ptr.p_double[0], 1, ae_v_len(0,m-1));
}
else
{
for(i=0; i<=m-1; i++)
{
deltaproj.ptr.p_double[i] = (double)(0);
}
for(i=k; i<=m-1; i++)
{
v = ae_v_dotproduct(&vt.ptr.pp_double[i][0], 1, &deltac.ptr.p_double[0], 1, ae_v_len(0,m-1));
ae_v_addd(&deltaproj.ptr.p_double[0], 1, &vt.ptr.pp_double[i][0], 1, ae_v_len(0,m-1), v);
}
}
/*
* now we have DeltaProj such that if C is feasible,
* then C+DeltaProj is feasible too
*/
ae_v_move(&c2.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,m-1));
ae_v_add(&c2.ptr.p_double[0], 1, &deltaproj.ptr.p_double[0], 1, ae_v_len(0,m-1));
s2 = testlsfitunit_getglserror(n, m, y, w, fmatrix, &c2, _state);
ae_v_move(&c2.ptr.p_double[0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,m-1));
ae_v_sub(&c2.ptr.p_double[0], 1, &deltaproj.ptr.p_double[0], 1, ae_v_len(0,m-1));
s3 = testlsfitunit_getglserror(n, m, y, w, fmatrix, &c2, _state);
result = (result&&ae_fp_greater_eq(s2,s1/(1+threshold)))&&ae_fp_greater_eq(s3,s1/(1+threshold));
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Tests whether C is solution of LLS problem
*************************************************************************/
static double testlsfitunit_getglserror(ae_int_t n,
ae_int_t m,
/* Real */ ae_vector* y,
/* Real */ ae_vector* w,
/* Real */ ae_matrix* fmatrix,
/* Real */ ae_vector* c,
ae_state *_state)
{
ae_int_t i;
double v;
double result;
result = (double)(0);
for(i=0; i<=n-1; i++)
{
v = ae_v_dotproduct(&fmatrix->ptr.pp_double[i][0], 1, &c->ptr.p_double[0], 1, ae_v_len(0,m-1));
result = result+ae_sqr(w->ptr.p_double[i]*(v-y->ptr.p_double[i]), _state);
}
return result;
}
/*************************************************************************
Subroutine for nonlinear fitting of linear problem
DerAvailable:
* 0 when only function value should be used
* 1 when we can provide gradient/function
* 2 when we can provide Hessian/gradient/function
When something which is not permitted by DerAvailable is requested,
this function sets NLSErrors to True.
*************************************************************************/
static void testlsfitunit_fitlinearnonlinear(ae_int_t m,
ae_int_t deravailable,
/* Real */ ae_matrix* xy,
lsfitstate* state,
ae_bool* nlserrors,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
double v;
while(lsfititeration(state, _state))
{
/*
* assume that one and only one of flags is set
* test that we didn't request hessian in hessian-free setting
*/
if( deravailable<1&&state->needfg )
{
*nlserrors = ae_true;
}
if( deravailable<2&&state->needfgh )
{
*nlserrors = ae_true;
}
i = 0;
if( state->needf )
{
i = i+1;
}
if( state->needfg )
{
i = i+1;
}
if( state->needfgh )
{
i = i+1;
}
if( i!=1 )
{
*nlserrors = ae_true;
}
/*
* test that PointIndex is consistent with actual point passed
*/
for(i=0; i<=m-1; i++)
{
*nlserrors = *nlserrors||ae_fp_neq(xy->ptr.pp_double[state->pointindex][i],state->x.ptr.p_double[i]);
}
/*
* calculate
*/
if( state->needf )
{
v = ae_v_dotproduct(&state->x.ptr.p_double[0], 1, &state->c.ptr.p_double[0], 1, ae_v_len(0,m-1));
state->f = v;
continue;
}
if( state->needfg )
{
v = ae_v_dotproduct(&state->x.ptr.p_double[0], 1, &state->c.ptr.p_double[0], 1, ae_v_len(0,m-1));
state->f = v;
ae_v_move(&state->g.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,m-1));
continue;
}
if( state->needfgh )
{
v = ae_v_dotproduct(&state->x.ptr.p_double[0], 1, &state->c.ptr.p_double[0], 1, ae_v_len(0,m-1));
state->f = v;
ae_v_move(&state->g.ptr.p_double[0], 1, &state->x.ptr.p_double[0], 1, ae_v_len(0,m-1));
for(i=0; i<=m-1; i++)
{
for(j=0; j<=m-1; j++)
{
state->h.ptr.pp_double[i][j] = (double)(0);
}
}
continue;
}
}
}
/*************************************************************************
This function tests, that gradient verified correctly.
On failure sets error flag, on success does not modify it.
*************************************************************************/
static void testlsfitunit_testgradientcheck(ae_bool* testg,
ae_state *_state)
{
ae_frame _frame_block;
lsfitstate state;
lsfitreport rep;
ae_int_t n;
ae_int_t m;
ae_int_t k;
ae_vector c;
ae_vector cres;
ae_matrix x;
ae_vector y;
ae_vector x0;
ae_int_t info;
ae_vector bl;
ae_vector bu;
ae_int_t infcomp;
double teststep;
double noise;
ae_int_t nbrcomp;
double spp;
ae_int_t func;
ae_int_t pass;
ae_int_t passcount;
ae_int_t i;
ae_int_t j;
ae_frame_make(_state, &_frame_block);
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&c, 0, sizeof(c));
memset(&cres, 0, sizeof(cres));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&x0, 0, sizeof(x0));
memset(&bl, 0, sizeof(bl));
memset(&bu, 0, sizeof(bu));
_lsfitstate_init(&state, _state, ae_true);
_lsfitreport_init(&rep, _state, ae_true);
ae_vector_init(&c, 0, DT_REAL, _state, ae_true);
ae_vector_init(&cres, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&x, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bl, 0, DT_REAL, _state, ae_true);
ae_vector_init(&bu, 0, DT_REAL, _state, ae_true);
passcount = 35;
spp = 1.0;
teststep = 0.001;
for(pass=1; pass<=passcount; pass++)
{
m = ae_randominteger(5, _state)+1;
ae_vector_set_length(&x0, m, _state);
k = ae_randominteger(5, _state)+1;
ae_vector_set_length(&c, k, _state);
ae_vector_set_length(&bl, k, _state);
ae_vector_set_length(&bu, k, _state);
/*
* Prepare test's parameters
*/
func = ae_randominteger(3, _state)+1;
n = ae_randominteger(8, _state)+3;
ae_matrix_set_length(&x, n, m, _state);
ae_vector_set_length(&y, n, _state);
nbrcomp = ae_randominteger(k, _state);
noise = (double)(2*ae_randominteger(2, _state)-1);
/*
* Prepare function's parameters
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
x.ptr.pp_double[i][j] = spp*(2*ae_randomreal(_state)-1);
}
y.ptr.p_double[i] = spp*(2*ae_randomreal(_state)-1);
}
for(i=0; i<=k-1; i++)
{
c.ptr.p_double[i] = spp*(2*ae_randomreal(_state)-1);
}
for(i=0; i<=m-1; i++)
{
x0.ptr.p_double[i] = 10*(2*ae_randomreal(_state)-1);
}
/*
* Prepare boundary parameters
*/
for(i=0; i<=k-1; i++)
{
bl.ptr.p_double[i] = -ae_randomreal(_state)-spp;
bu.ptr.p_double[i] = ae_randomreal(_state)+spp;
}
infcomp = ae_randominteger(k+1, _state);
if( infcompv_neginf;
}
infcomp = ae_randominteger(k+1, _state);
if( infcompv_posinf;
}
lsfitcreatefg(&x, &y, &c, n, m, k, ae_true, &state, _state);
lsfitsetgradientcheck(&state, teststep, _state);
lsfitsetcond(&state, 0.0, 100, _state);
lsfitsetbc(&state, &bl, &bu, _state);
/*
* Check that the criterion passes a derivative if it is correct
*/
while(lsfititeration(&state, _state))
{
if( state.needfg )
{
testlsfitunit_funcderiv(&state.c, &state.x, &x0, k, m, func, &state.f, &state.g, _state);
}
}
lsfitresults(&state, &info, &cres, &rep, _state);
/*
* Check that error code does not equal to -7 and parameter .VarIdx
* equal to -1.
*/
if( info==-7||rep.varidx!=-1 )
{
ae_set_error_flag(testg, ae_true, __FILE__, __LINE__, "testlsfitunit.ap:3917");
ae_frame_leave(_state);
return;
}
/*
* Create again and...
*/
lsfitcreatefg(&x, &y, &c, n, m, k, ae_true, &state, _state);
lsfitsetgradientcheck(&state, teststep, _state);
lsfitsetcond(&state, 0.0, 100, _state);
lsfitsetbc(&state, &bl, &bu, _state);
/*
* Check that the criterion does not miss a derivative if
* it is incorrect
*/
while(lsfititeration(&state, _state))
{
if( state.needfg )
{
testlsfitunit_funcderiv(&state.c, &state.x, &x0, k, m, func, &state.f, &state.g, _state);
state.g.ptr.p_double[nbrcomp] = state.g.ptr.p_double[nbrcomp]+noise;
}
}
lsfitresults(&state, &info, &cres, &rep, _state);
/*
* Check that error code equal to -7 and parameter .VarIdx
* equal to number of incorrect component.
*/
if( info!=-7||rep.varidx!=nbrcomp )
{
ae_set_error_flag(testg, ae_true, __FILE__, __LINE__, "testlsfitunit.ap:3949");
ae_frame_leave(_state);
return;
}
}
ae_frame_leave(_state);
}
/*************************************************************************
This function return function's value(F=F(X,C)) and it derivatives(DF=dF/dC).
Function dimension is M. Length(C) is K.
Function's list:
* funcType=1:
K>M:
F(X)=C0^2*(X0-CX0)^2+C1^2*(X1-CX1)^2+...+CM^2*(XM-CXM)^2
+C(M+1)^2+...+CK^2;
KM:
F(X)=C0*sin(X0-CX0)^2+C1*sin(X1-CX1)^2+...+CM*sin(XM-CXM)^2
+C(M+1)^3+...+CK^3;
K=1&&functype<=3, "FuncDeriv: incorrect funcType(funcType<1 or funcType>3).", _state);
ae_assert(k>0, "FuncDeriv: K<=0", _state);
ae_assert(m>0, "FuncDeriv: M<=0", _state);
ae_assert(x->cnt>=m, "FuncDeriv: Length(X)cnt>=m, "FuncDeriv: Length(X0)cnt>=k, "FuncDeriv: Length(X)ptr.p_double[i]*(x->ptr.p_double[i]-x0->ptr.p_double[i]), _state);
g->ptr.p_double[i] = 2*c->ptr.p_double[i]*ae_sqr(x->ptr.p_double[i]-x0->ptr.p_double[i], _state);
}
if( k>m )
{
for(i=m; i<=k-1; i++)
{
*f = *f+ae_sqr(c->ptr.p_double[i], _state);
g->ptr.p_double[i] = 2*c->ptr.p_double[i];
}
}
if( kptr.p_double[i]-x0->ptr.p_double[i], _state);
}
}
return;
}
if( functype==2 )
{
*f = (double)(0);
for(i=0; i<=ae_minint(m, k, _state)-1; i++)
{
*f = *f+c->ptr.p_double[i]*ae_sqr(ae_sin(x->ptr.p_double[i]-x0->ptr.p_double[i], _state), _state);
g->ptr.p_double[i] = ae_sqr(ae_sin(x->ptr.p_double[i]-x0->ptr.p_double[i], _state), _state);
}
if( k>m )
{
for(i=m; i<=k-1; i++)
{
*f = *f+c->ptr.p_double[i]*c->ptr.p_double[i]*c->ptr.p_double[i];
g->ptr.p_double[i] = 3*ae_sqr(c->ptr.p_double[i], _state);
}
}
if( kptr.p_double[i]-x0->ptr.p_double[i], _state), _state);
}
}
return;
}
if( functype==3 )
{
*f = (double)(0);
for(i=0; i<=m-1; i++)
{
*f = *f+ae_sqr(x->ptr.p_double[i]-x0->ptr.p_double[i], _state);
}
for(i=0; i<=k-1; i++)
{
*f = *f+c->ptr.p_double[i]*c->ptr.p_double[i];
}
for(i=0; i<=k-1; i++)
{
g->ptr.p_double[i] = 2*c->ptr.p_double[i];
}
return;
}
}
/*************************************************************************
Test function 1:
F(K, X, Z) = SUM( (power(z_j,3)+alpha*z_j)*x_ij )
here X is a space of points, Z is a space of parameters
*************************************************************************/
static void testlsfitunit_testfunc1(ae_int_t k,
/* Real */ ae_vector* x,
/* Real */ ae_vector* z,
double* f,
ae_bool needf,
/* Real */ ae_vector* g,
ae_bool needg,
ae_state *_state)
{
ae_int_t j;
double v;
double alpha;
alpha = 0.01;
v = (double)(0);
for(j=0; j<=k-1; j++)
{
v = v+(alpha*z->ptr.p_double[j]+ae_pow(z->ptr.p_double[j], (double)(3), _state))*x->ptr.p_double[j];
if( needg )
{
g->ptr.p_double[j] = (alpha+3*ae_pow(z->ptr.p_double[j], (double)(2), _state))*x->ptr.p_double[j];
}
}
if( needf )
{
*f = v;
}
}
/*************************************************************************
Test function 2:
F(X|C) = c_0
here X is a space of points, C is a space of parameters
*************************************************************************/
static void testlsfitunit_testfunc2(/* Real */ ae_vector* x,
ae_int_t nx,
/* Real */ ae_vector* c,
ae_int_t nc,
double* f,
ae_bool needf,
/* Real */ ae_vector* g,
ae_bool needg,
ae_state *_state)
{
ae_assert(nc==1, "TestFunc2: integrity check failure", _state);
if( needf )
{
*f = c->ptr.p_double[0];
}
if( needg )
{
g->ptr.p_double[0] = (double)(1);
}
}
/*************************************************************************
Test function 3:
F(X|C) = c_0 + c_1*x0 + c_2*x0^2 + ...
here X is a space of points, C is a space of parameters
*************************************************************************/
static void testlsfitunit_testfunc3(/* Real */ ae_vector* x,
ae_int_t nx,
/* Real */ ae_vector* c,
ae_int_t nc,
double* f,
ae_bool needf,
/* Real */ ae_vector* g,
ae_bool needg,
ae_state *_state)
{
double v;
ae_int_t i;
ae_assert(nx==1, "TestFunc3: integrity check failure", _state);
v = (double)(0);
for(i=0; i<=nc-1; i++)
{
v = v+c->ptr.p_double[i]*ae_pow(x->ptr.p_double[0], (double)(i), _state);
if( needg )
{
g->ptr.p_double[i] = ae_pow(x->ptr.p_double[0], (double)(i), _state);
}
}
if( needf )
{
*f = v;
}
}
/*************************************************************************
Appends 10 elements to the array
*************************************************************************/
static void testlsfitunit_append10(/* Real */ ae_vector* x,
double v0,
double v1,
double v2,
double v3,
double v4,
double v5,
double v6,
double v7,
double v8,
double v9,
ae_state *_state)
{
rvectorresize(x, x->cnt+10, _state);
x->ptr.p_double[x->cnt-10] = v0;
x->ptr.p_double[x->cnt-9] = v1;
x->ptr.p_double[x->cnt-8] = v2;
x->ptr.p_double[x->cnt-7] = v3;
x->ptr.p_double[x->cnt-6] = v4;
x->ptr.p_double[x->cnt-5] = v5;
x->ptr.p_double[x->cnt-4] = v6;
x->ptr.p_double[x->cnt-3] = v7;
x->ptr.p_double[x->cnt-2] = v8;
x->ptr.p_double[x->cnt-1] = v9;
}
static void testspline2dunit_lconst(spline2dinterpolant* c,
/* Real */ ae_vector* lx,
/* Real */ ae_vector* ly,
ae_int_t m,
ae_int_t n,
double lstep,
double* lc,
double* lcx,
double* lcy,
double* lcxy,
ae_state *_state);
static void testspline2dunit_twodnumder(spline2dinterpolant* c,
double x,
double y,
double h,
double* f,
double* fx,
double* fy,
double* fxy,
ae_state *_state);
static ae_bool testspline2dunit_testunpack(spline2dinterpolant* c,
/* Real */ ae_vector* lx,
/* Real */ ae_vector* ly,
ae_state *_state);
static ae_bool testspline2dunit_testlintrans(spline2dinterpolant* c,
ae_int_t d,
double ax,
double bx,
double ay,
double by,
ae_state *_state);
static void testspline2dunit_unsetspline2d(spline2dinterpolant* c,
ae_state *_state);
static ae_bool testspline2dunit_testspline2dvf(ae_bool silent,
ae_state *_state);
static void testspline2dunit_testfittingprior(ae_bool* errorflag,
ae_state *_state);
static void testspline2dunit_testfittingpenalty(ae_bool* errorflag,
ae_state *_state);
static void testspline2dunit_testfittingblocksolver(ae_bool* errorflag,
ae_state *_state);
static void testspline2dunit_testfittingfastddmsolver(ae_bool* errorflag,
ae_state *_state);
ae_bool testspline2d(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_bool waserrors;
ae_bool blerrors;
ae_bool bcerrors;
ae_bool dserrors;
ae_bool cperrors;
ae_bool sererrors;
ae_bool uperrors;
ae_bool lterrors;
ae_bool syerrors;
ae_bool rlerrors;
ae_bool rcerrors;
ae_bool vferrors;
ae_bool fiterrorsfastddmsolver;
ae_bool fiterrorsblocksolver;
ae_bool fiterrorspenalty;
ae_bool fiterrorsprior;
ae_int_t pass;
ae_int_t passcount;
ae_int_t jobtype;
double lstep;
double h;
ae_vector x;
ae_vector y;
spline2dinterpolant c;
spline2dinterpolant c2;
ae_vector lx;
ae_vector ly;
ae_vector fv1;
ae_vector fvd;
ae_matrix f;
ae_matrix fr;
ae_matrix ft;
double ax;
double ay;
double bx;
double by;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t n;
ae_int_t m;
ae_int_t d;
ae_int_t n2;
ae_int_t m2;
double err;
double t;
double t1;
double t2;
double l1;
double l1x;
double l1y;
double l1xy;
double l2;
double l2x;
double l2y;
double l2xy;
double fm;
double f1;
double f2;
double f3;
double f4;
double v1;
double v1x;
double v1y;
double v1xy;
double v2;
double v2x;
double v2y;
double v2xy;
double mf;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&c, 0, sizeof(c));
memset(&c2, 0, sizeof(c2));
memset(&lx, 0, sizeof(lx));
memset(&ly, 0, sizeof(ly));
memset(&fv1, 0, sizeof(fv1));
memset(&fvd, 0, sizeof(fvd));
memset(&f, 0, sizeof(f));
memset(&fr, 0, sizeof(fr));
memset(&ft, 0, sizeof(ft));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
_spline2dinterpolant_init(&c, _state, ae_true);
_spline2dinterpolant_init(&c2, _state, ae_true);
ae_vector_init(&lx, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ly, 0, DT_REAL, _state, ae_true);
ae_vector_init(&fv1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&fvd, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&f, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&fr, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ft, 0, 0, DT_REAL, _state, ae_true);
waserrors = ae_false;
passcount = 10;
h = 0.00001;
lstep = 0.001;
blerrors = ae_false;
bcerrors = ae_false;
dserrors = ae_false;
cperrors = ae_false;
sererrors = ae_false;
uperrors = ae_false;
lterrors = ae_false;
syerrors = ae_false;
rlerrors = ae_false;
rcerrors = ae_false;
vferrors = ae_false;
fiterrorsfastddmsolver = ae_false;
fiterrorsblocksolver = ae_false;
fiterrorsprior = ae_false;
fiterrorspenalty = ae_false;
/*
* Fitting functions
*/
testspline2dunit_testfittingfastddmsolver(&fiterrorsfastddmsolver, _state);
testspline2dunit_testfittingprior(&fiterrorsprior, _state);
testspline2dunit_testfittingblocksolver(&fiterrorsblocksolver, _state);
testspline2dunit_testfittingpenalty(&fiterrorspenalty, _state);
/*
* Test: bilinear, bicubic
*/
for(n=2; n<=7; n++)
{
for(m=2; m<=7; m++)
{
d = ae_randominteger(2, _state)+2;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, m, _state);
ae_vector_set_length(&lx, 2*n-1, _state);
ae_vector_set_length(&ly, 2*m-1, _state);
ae_matrix_set_length(&f, m, n, _state);
ae_vector_set_length(&fv1, m*n, _state);
ae_vector_set_length(&fvd, m*n*d, _state);
ae_matrix_set_length(&ft, n, m, _state);
for(pass=1; pass<=passcount; pass++)
{
/*
* Prepare task:
* * X and Y stores grid
* * F stores function values
* * LX and LY stores twice dense grid (for Lipschitz testing)
*/
ax = -1-ae_randomreal(_state);
bx = 1+ae_randomreal(_state);
ay = -1-ae_randomreal(_state);
by = 1+ae_randomreal(_state);
for(j=0; j<=n-1; j++)
{
x.ptr.p_double[j] = 0.5*(bx+ax)-0.5*(bx-ax)*ae_cos(ae_pi*(2*j+1)/(2*n), _state);
if( j==0 )
{
x.ptr.p_double[j] = ax;
}
if( j==n-1 )
{
x.ptr.p_double[j] = bx;
}
lx.ptr.p_double[2*j] = x.ptr.p_double[j];
if( j>0 )
{
lx.ptr.p_double[2*j-1] = 0.5*(x.ptr.p_double[j]+x.ptr.p_double[j-1]);
}
}
for(j=0; j<=n-1; j++)
{
k = ae_randominteger(n, _state);
if( k!=j )
{
t = x.ptr.p_double[j];
x.ptr.p_double[j] = x.ptr.p_double[k];
x.ptr.p_double[k] = t;
}
}
for(i=0; i<=m-1; i++)
{
y.ptr.p_double[i] = 0.5*(by+ay)-0.5*(by-ay)*ae_cos(ae_pi*(2*i+1)/(2*m), _state);
if( i==0 )
{
y.ptr.p_double[i] = ay;
}
if( i==m-1 )
{
y.ptr.p_double[i] = by;
}
ly.ptr.p_double[2*i] = y.ptr.p_double[i];
if( i>0 )
{
ly.ptr.p_double[2*i-1] = 0.5*(y.ptr.p_double[i]+y.ptr.p_double[i-1]);
}
}
for(i=0; i<=m-1; i++)
{
k = ae_randominteger(m, _state);
if( k!=i )
{
t = y.ptr.p_double[i];
y.ptr.p_double[i] = y.ptr.p_double[k];
y.ptr.p_double[k] = t;
}
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
f.ptr.pp_double[i][j] = ae_exp(0.6*x.ptr.p_double[j], _state)-ae_exp(-0.3*y.ptr.p_double[i]+0.08*x.ptr.p_double[j], _state)+2*ae_cos(ae_pi*(x.ptr.p_double[j]+1.2*y.ptr.p_double[i]), _state)+0.1*ae_cos(20*x.ptr.p_double[j]+15*y.ptr.p_double[i], _state);
fv1.ptr.p_double[i*n+j] = f.ptr.pp_double[i][j];
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
for(k=0; k<=d-1; k++)
{
fvd.ptr.p_double[d*(n*j+i)+k] = ae_exp(0.6*x.ptr.p_double[i], _state)-ae_exp(-0.3*y.ptr.p_double[j]+0.08*x.ptr.p_double[i], _state)+2*ae_cos(ae_pi*(x.ptr.p_double[i]+1.2*y.ptr.p_double[j]+k), _state)+0.1*ae_cos(20*x.ptr.p_double[i]+15*y.ptr.p_double[j]+k, _state);
}
}
}
/*
* Test scalar bilinear interpolation:
* * interpolation at the nodes
* * linearity
* * continuity
* * differentiation in the inner points
*/
spline2dbuildbilinearv(&x, n, &y, m, &fv1, 1, &c, _state);
err = (double)(0);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
err = ae_maxreal(err, ae_fabs(f.ptr.pp_double[i][j]-spline2dcalc(&c, x.ptr.p_double[j], y.ptr.p_double[i], _state), _state), _state);
}
}
blerrors = blerrors||ae_fp_greater(err,10000*ae_machineepsilon);
err = (double)(0);
for(i=0; i<=m-2; i++)
{
for(j=0; j<=n-2; j++)
{
/*
* Test for linearity between grid points
* (test point - geometric center of the cell)
*/
fm = spline2dcalc(&c, lx.ptr.p_double[2*j+1], ly.ptr.p_double[2*i+1], _state);
f1 = spline2dcalc(&c, lx.ptr.p_double[2*j], ly.ptr.p_double[2*i], _state);
f2 = spline2dcalc(&c, lx.ptr.p_double[2*j+2], ly.ptr.p_double[2*i], _state);
f3 = spline2dcalc(&c, lx.ptr.p_double[2*j+2], ly.ptr.p_double[2*i+2], _state);
f4 = spline2dcalc(&c, lx.ptr.p_double[2*j], ly.ptr.p_double[2*i+2], _state);
err = ae_maxreal(err, ae_fabs(0.25*(f1+f2+f3+f4)-fm, _state), _state);
}
}
blerrors = blerrors||ae_fp_greater(err,10000*ae_machineepsilon);
testspline2dunit_lconst(&c, &lx, &ly, m, n, lstep, &l1, &l1x, &l1y, &l1xy, _state);
testspline2dunit_lconst(&c, &lx, &ly, m, n, lstep/3, &l2, &l2x, &l2y, &l2xy, _state);
blerrors = blerrors||ae_fp_greater(l2/l1,1.2);
err = (double)(0);
for(i=0; i<=m-2; i++)
{
for(j=0; j<=n-2; j++)
{
spline2ddiff(&c, lx.ptr.p_double[2*j+1], ly.ptr.p_double[2*i+1], &v1, &v1x, &v1y, &v1xy, _state);
testspline2dunit_twodnumder(&c, lx.ptr.p_double[2*j+1], ly.ptr.p_double[2*i+1], h, &v2, &v2x, &v2y, &v2xy, _state);
err = ae_maxreal(err, ae_fabs(v1-v2, _state), _state);
err = ae_maxreal(err, ae_fabs(v1x-v2x, _state), _state);
err = ae_maxreal(err, ae_fabs(v1y-v2y, _state), _state);
err = ae_maxreal(err, ae_fabs(v1xy-v2xy, _state), _state);
}
}
dserrors = dserrors||ae_fp_greater(err,1.0E-3);
uperrors = uperrors||!testspline2dunit_testunpack(&c, &lx, &ly, _state);
lterrors = lterrors||!testspline2dunit_testlintrans(&c, 1, ax, bx, ay, by, _state);
/*
* Lin.Trans. test for multicomponent vector function
*/
spline2dbuildbilinearv(&x, n, &y, m, &fvd, d, &c, _state);
lterrors = lterrors||!testspline2dunit_testlintrans(&c, d, ax, bx, ay, by, _state);
/*
* Test bicubic interpolation.
* * interpolation at the nodes
* * smoothness
* * differentiation
*/
spline2dbuildbicubicv(&x, n, &y, m, &fv1, 1, &c, _state);
err = (double)(0);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
err = ae_maxreal(err, ae_fabs(f.ptr.pp_double[i][j]-spline2dcalc(&c, x.ptr.p_double[j], y.ptr.p_double[i], _state), _state), _state);
}
}
bcerrors = bcerrors||ae_fp_greater(err,10000*ae_machineepsilon);
testspline2dunit_lconst(&c, &lx, &ly, m, n, lstep, &l1, &l1x, &l1y, &l1xy, _state);
testspline2dunit_lconst(&c, &lx, &ly, m, n, lstep/3, &l2, &l2x, &l2y, &l2xy, _state);
bcerrors = bcerrors||ae_fp_greater(l2/l1,1.2);
bcerrors = bcerrors||ae_fp_greater(l2x/l1x,1.2);
bcerrors = bcerrors||ae_fp_greater(l2y/l1y,1.2);
if( ae_fp_greater(l2xy,0.01)&&ae_fp_greater(l1xy,0.01) )
{
/*
* Cross-derivative continuity is tested only when
* bigger than 0.01. When the task size is too
* small, the d2F/dXdY is nearly zero and Lipschitz
* constant ratio is ill-conditioned.
*/
bcerrors = bcerrors||ae_fp_greater(l2xy/l1xy,1.2);
}
err = (double)(0);
for(i=0; i<=2*m-2; i++)
{
for(j=0; j<=2*n-2; j++)
{
spline2ddiff(&c, lx.ptr.p_double[j], ly.ptr.p_double[i], &v1, &v1x, &v1y, &v1xy, _state);
testspline2dunit_twodnumder(&c, lx.ptr.p_double[j], ly.ptr.p_double[i], h, &v2, &v2x, &v2y, &v2xy, _state);
err = ae_maxreal(err, ae_fabs(v1-v2, _state), _state);
err = ae_maxreal(err, ae_fabs(v1x-v2x, _state), _state);
err = ae_maxreal(err, ae_fabs(v1y-v2y, _state), _state);
err = ae_maxreal(err, ae_fabs(v1xy-v2xy, _state), _state);
}
}
dserrors = dserrors||ae_fp_greater(err,1.0E-3);
uperrors = uperrors||!testspline2dunit_testunpack(&c, &lx, &ly, _state);
lterrors = lterrors||!testspline2dunit_testlintrans(&c, 1, ax, bx, ay, by, _state);
/*
* Lin.Trans. test for vector-function
*/
spline2dbuildbicubicv(&x, n, &y, m, &fvd, d, &c, _state);
lterrors = lterrors||!testspline2dunit_testlintrans(&c, d, ax, bx, ay, by, _state);
/*
* Copy test
*/
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
spline2dbuildbicubic(&x, &y, &f, m, n, &c, _state);
}
else
{
spline2dbuildbilinear(&x, &y, &f, m, n, &c, _state);
}
testspline2dunit_unsetspline2d(&c2, _state);
spline2dcopy(&c, &c2, _state);
err = (double)(0);
for(i=1; i<=5; i++)
{
t1 = ax+(bx-ax)*ae_randomreal(_state);
t2 = ay+(by-ay)*ae_randomreal(_state);
err = ae_maxreal(err, ae_fabs(spline2dcalc(&c, t1, t2, _state)-spline2dcalc(&c2, t1, t2, _state), _state), _state);
}
cperrors = cperrors||ae_fp_greater(err,10000*ae_machineepsilon);
/*
* Serialization test
*/
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
spline2dbuildbicubic(&x, &y, &f, m, n, &c, _state);
}
else
{
spline2dbuildbilinear(&x, &y, &f, m, n, &c, _state);
}
testspline2dunit_unsetspline2d(&c2, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
spline2dalloc(&_local_serializer, &c, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
spline2dserialize(&_local_serializer, &c, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
spline2dunserialize(&_local_serializer, &c2, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
err = (double)(0);
for(i=1; i<=5; i++)
{
t1 = ax+(bx-ax)*ae_randomreal(_state);
t2 = ay+(by-ay)*ae_randomreal(_state);
err = ae_maxreal(err, ae_fabs(spline2dcalc(&c, t1, t2, _state)-spline2dcalc(&c2, t1, t2, _state), _state), _state);
}
ae_set_error_flag(&sererrors, ae_fp_greater(err,10000*ae_machineepsilon), __FILE__, __LINE__, "testspline2dunit.ap:292");
/*
* Special symmetry test
*/
err = (double)(0);
for(jobtype=0; jobtype<=1; jobtype++)
{
/*
* Prepare
*/
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
ft.ptr.pp_double[j][i] = f.ptr.pp_double[i][j];
}
}
if( jobtype==0 )
{
spline2dbuildbilinear(&x, &y, &f, m, n, &c, _state);
spline2dbuildbilinear(&y, &x, &ft, n, m, &c2, _state);
}
else
{
spline2dbuildbicubic(&x, &y, &f, m, n, &c, _state);
spline2dbuildbicubic(&y, &x, &ft, n, m, &c2, _state);
}
/*
* Test
*/
for(i=1; i<=10; i++)
{
t1 = ax+(bx-ax)*ae_randomreal(_state);
t2 = ay+(by-ay)*ae_randomreal(_state);
err = ae_maxreal(err, ae_fabs(spline2dcalc(&c, t1, t2, _state)-spline2dcalc(&c2, t2, t1, _state), _state), _state);
}
}
syerrors = syerrors||ae_fp_greater(err,10000*ae_machineepsilon);
}
}
}
/*
* Test resample
*/
for(m=2; m<=6; m++)
{
for(n=2; n<=6; n++)
{
ae_matrix_set_length(&f, m-1+1, n-1+1, _state);
ae_vector_set_length(&x, n-1+1, _state);
ae_vector_set_length(&y, m-1+1, _state);
for(j=0; j<=n-1; j++)
{
x.ptr.p_double[j] = (double)j/(double)(n-1);
}
for(i=0; i<=m-1; i++)
{
y.ptr.p_double[i] = (double)i/(double)(m-1);
}
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
f.ptr.pp_double[i][j] = ae_exp(0.6*x.ptr.p_double[j], _state)-ae_exp(-0.3*y.ptr.p_double[i]+0.08*x.ptr.p_double[j], _state)+2*ae_cos(ae_pi*(x.ptr.p_double[j]+1.2*y.ptr.p_double[i]), _state)+0.1*ae_cos(20*x.ptr.p_double[j]+15*y.ptr.p_double[i], _state);
}
}
for(m2=2; m2<=6; m2++)
{
for(n2=2; n2<=6; n2++)
{
for(pass=1; pass<=passcount; pass++)
{
for(jobtype=0; jobtype<=1; jobtype++)
{
if( jobtype==0 )
{
spline2dresamplebilinear(&f, m, n, &fr, m2, n2, _state);
spline2dbuildbilinear(&x, &y, &f, m, n, &c, _state);
}
if( jobtype==1 )
{
spline2dresamplebicubic(&f, m, n, &fr, m2, n2, _state);
spline2dbuildbicubic(&x, &y, &f, m, n, &c, _state);
}
err = (double)(0);
mf = (double)(0);
for(i=0; i<=m2-1; i++)
{
for(j=0; j<=n2-1; j++)
{
v1 = spline2dcalc(&c, (double)j/(double)(n2-1), (double)i/(double)(m2-1), _state);
v2 = fr.ptr.pp_double[i][j];
err = ae_maxreal(err, ae_fabs(v1-v2, _state), _state);
mf = ae_maxreal(mf, ae_fabs(v1, _state), _state);
}
}
if( jobtype==0 )
{
rlerrors = rlerrors||ae_fp_greater(err/mf,10000*ae_machineepsilon);
}
if( jobtype==1 )
{
rcerrors = rcerrors||ae_fp_greater(err/mf,10000*ae_machineepsilon);
}
}
}
}
}
}
}
/*
* Test for vector-function
*/
vferrors = testspline2dunit_testspline2dvf(ae_true, _state);
/*
* Report
*/
waserrors = (((((((((((((blerrors||bcerrors)||dserrors)||cperrors)||sererrors)||uperrors)||lterrors)||syerrors)||rlerrors)||rcerrors)||vferrors)||fiterrorsprior)||fiterrorspenalty)||fiterrorsblocksolver)||fiterrorsfastddmsolver;
if( !silent )
{
printf("TESTING 2D SPLINE\n");
/*
* Normal tests
*/
printf("INTERPOLATION:\n");
printf("* bilinear ");
if( blerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* bicubic ");
if( bcerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* differentiation ");
if( dserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* copying ");
if( cperrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* serialization ");
if( sererrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* unpacking ");
if( uperrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* lin.trans. ");
if( lterrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* special symmetry props ");
if( syerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* vector spline ");
if( vferrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("FITTING:\n");
printf("* linear prior term ");
if( fiterrorsprior )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* nonlinearity penalty term ");
if( fiterrorspenalty )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* block solver ");
if( fiterrorsblocksolver )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* fast DDM solver ");
if( fiterrorsfastddmsolver )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("RESAMPLING:\n");
printf("* bilinear ");
if( rlerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* bicubic ");
if( rcerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
/*
* Summary
*/
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
/*
* end
*/
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Lipschitz constants for spline inself, first and second derivatives.
*************************************************************************/
static void testspline2dunit_lconst(spline2dinterpolant* c,
/* Real */ ae_vector* lx,
/* Real */ ae_vector* ly,
ae_int_t m,
ae_int_t n,
double lstep,
double* lc,
double* lcx,
double* lcy,
double* lcxy,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
double f1;
double f2;
double f3;
double f4;
double fx1;
double fx2;
double fx3;
double fx4;
double fy1;
double fy2;
double fy3;
double fy4;
double fxy1;
double fxy2;
double fxy3;
double fxy4;
double s2lstep;
*lc = 0;
*lcx = 0;
*lcy = 0;
*lcxy = 0;
*lc = (double)(0);
*lcx = (double)(0);
*lcy = (double)(0);
*lcxy = (double)(0);
s2lstep = ae_sqrt((double)(2), _state)*lstep;
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
/*
* Calculate
*/
testspline2dunit_twodnumder(c, lx->ptr.p_double[j]-lstep/2, ly->ptr.p_double[i]-lstep/2, lstep/4, &f1, &fx1, &fy1, &fxy1, _state);
testspline2dunit_twodnumder(c, lx->ptr.p_double[j]+lstep/2, ly->ptr.p_double[i]-lstep/2, lstep/4, &f2, &fx2, &fy2, &fxy2, _state);
testspline2dunit_twodnumder(c, lx->ptr.p_double[j]+lstep/2, ly->ptr.p_double[i]+lstep/2, lstep/4, &f3, &fx3, &fy3, &fxy3, _state);
testspline2dunit_twodnumder(c, lx->ptr.p_double[j]-lstep/2, ly->ptr.p_double[i]+lstep/2, lstep/4, &f4, &fx4, &fy4, &fxy4, _state);
/*
* Lipschitz constant for the function itself
*/
*lc = ae_maxreal(*lc, ae_fabs((f1-f2)/lstep, _state), _state);
*lc = ae_maxreal(*lc, ae_fabs((f2-f3)/lstep, _state), _state);
*lc = ae_maxreal(*lc, ae_fabs((f3-f4)/lstep, _state), _state);
*lc = ae_maxreal(*lc, ae_fabs((f4-f1)/lstep, _state), _state);
*lc = ae_maxreal(*lc, ae_fabs((f1-f3)/s2lstep, _state), _state);
*lc = ae_maxreal(*lc, ae_fabs((f2-f4)/s2lstep, _state), _state);
/*
* Lipschitz constant for the first derivative
*/
*lcx = ae_maxreal(*lcx, ae_fabs((fx1-fx2)/lstep, _state), _state);
*lcx = ae_maxreal(*lcx, ae_fabs((fx2-fx3)/lstep, _state), _state);
*lcx = ae_maxreal(*lcx, ae_fabs((fx3-fx4)/lstep, _state), _state);
*lcx = ae_maxreal(*lcx, ae_fabs((fx4-fx1)/lstep, _state), _state);
*lcx = ae_maxreal(*lcx, ae_fabs((fx1-fx3)/s2lstep, _state), _state);
*lcx = ae_maxreal(*lcx, ae_fabs((fx2-fx4)/s2lstep, _state), _state);
/*
* Lipschitz constant for the first derivative
*/
*lcy = ae_maxreal(*lcy, ae_fabs((fy1-fy2)/lstep, _state), _state);
*lcy = ae_maxreal(*lcy, ae_fabs((fy2-fy3)/lstep, _state), _state);
*lcy = ae_maxreal(*lcy, ae_fabs((fy3-fy4)/lstep, _state), _state);
*lcy = ae_maxreal(*lcy, ae_fabs((fy4-fy1)/lstep, _state), _state);
*lcy = ae_maxreal(*lcy, ae_fabs((fy1-fy3)/s2lstep, _state), _state);
*lcy = ae_maxreal(*lcy, ae_fabs((fy2-fy4)/s2lstep, _state), _state);
/*
* Lipschitz constant for the cross-derivative
*/
*lcxy = ae_maxreal(*lcxy, ae_fabs((fxy1-fxy2)/lstep, _state), _state);
*lcxy = ae_maxreal(*lcxy, ae_fabs((fxy2-fxy3)/lstep, _state), _state);
*lcxy = ae_maxreal(*lcxy, ae_fabs((fxy3-fxy4)/lstep, _state), _state);
*lcxy = ae_maxreal(*lcxy, ae_fabs((fxy4-fxy1)/lstep, _state), _state);
*lcxy = ae_maxreal(*lcxy, ae_fabs((fxy1-fxy3)/s2lstep, _state), _state);
*lcxy = ae_maxreal(*lcxy, ae_fabs((fxy2-fxy4)/s2lstep, _state), _state);
}
}
}
/*************************************************************************
Numerical differentiation.
*************************************************************************/
static void testspline2dunit_twodnumder(spline2dinterpolant* c,
double x,
double y,
double h,
double* f,
double* fx,
double* fy,
double* fxy,
ae_state *_state)
{
*f = 0;
*fx = 0;
*fy = 0;
*fxy = 0;
*f = spline2dcalc(c, x, y, _state);
*fx = (spline2dcalc(c, x+h, y, _state)-spline2dcalc(c, x-h, y, _state))/(2*h);
*fy = (spline2dcalc(c, x, y+h, _state)-spline2dcalc(c, x, y-h, _state))/(2*h);
*fxy = (spline2dcalc(c, x+h, y+h, _state)-spline2dcalc(c, x-h, y+h, _state)-spline2dcalc(c, x+h, y-h, _state)+spline2dcalc(c, x-h, y-h, _state))/ae_sqr(2*h, _state);
}
/*************************************************************************
Unpack test
*************************************************************************/
static ae_bool testspline2dunit_testunpack(spline2dinterpolant* c,
/* Real */ ae_vector* lx,
/* Real */ ae_vector* ly,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_int_t n;
ae_int_t m;
ae_int_t ci;
ae_int_t cj;
ae_int_t p;
double err;
double tx;
double ty;
double v1;
double v2;
ae_int_t pass;
ae_int_t passcount;
ae_matrix tbl;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&tbl, 0, sizeof(tbl));
ae_matrix_init(&tbl, 0, 0, DT_REAL, _state, ae_true);
passcount = 20;
err = (double)(0);
spline2dunpack(c, &m, &n, &tbl, _state);
for(i=0; i<=m-2; i++)
{
for(j=0; j<=n-2; j++)
{
for(pass=1; pass<=passcount; pass++)
{
p = (n-1)*i+j;
tx = (0.001+0.999*ae_randomreal(_state))*(tbl.ptr.pp_double[p][1]-tbl.ptr.pp_double[p][0]);
ty = (0.001+0.999*ae_randomreal(_state))*(tbl.ptr.pp_double[p][3]-tbl.ptr.pp_double[p][2]);
/*
* Interpolation properties
*/
v1 = (double)(0);
for(ci=0; ci<=3; ci++)
{
for(cj=0; cj<=3; cj++)
{
v1 = v1+tbl.ptr.pp_double[p][4+ci*4+cj]*ae_pow(tx, (double)(ci), _state)*ae_pow(ty, (double)(cj), _state);
}
}
v2 = spline2dcalc(c, tbl.ptr.pp_double[p][0]+tx, tbl.ptr.pp_double[p][2]+ty, _state);
err = ae_maxreal(err, ae_fabs(v1-v2, _state), _state);
/*
* Grid correctness
*/
err = ae_maxreal(err, ae_fabs(lx->ptr.p_double[2*j]-tbl.ptr.pp_double[p][0], _state), _state);
err = ae_maxreal(err, ae_fabs(lx->ptr.p_double[2*(j+1)]-tbl.ptr.pp_double[p][1], _state), _state);
err = ae_maxreal(err, ae_fabs(ly->ptr.p_double[2*i]-tbl.ptr.pp_double[p][2], _state), _state);
err = ae_maxreal(err, ae_fabs(ly->ptr.p_double[2*(i+1)]-tbl.ptr.pp_double[p][3], _state), _state);
}
}
}
result = ae_fp_less(err,10000*ae_machineepsilon);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
LinTrans test for scalar
*************************************************************************/
static ae_bool testspline2dunit_testlintrans(spline2dinterpolant* c,
ae_int_t d,
double ax,
double bx,
double ay,
double by,
ae_state *_state)
{
ae_frame _frame_block;
double err;
double a1;
double a2;
double b1;
double b2;
double tx;
double ty;
double vx;
double vy;
ae_vector v1;
ae_vector v2;
ae_int_t pass;
ae_int_t passcount;
ae_int_t xjob;
ae_int_t yjob;
spline2dinterpolant c2;
ae_int_t di;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&v1, 0, sizeof(v1));
memset(&v2, 0, sizeof(v2));
memset(&c2, 0, sizeof(c2));
ae_vector_init(&v1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&v2, 0, DT_REAL, _state, ae_true);
_spline2dinterpolant_init(&c2, _state, ae_true);
passcount = 5;
err = (double)(0);
for(xjob=0; xjob<=1; xjob++)
{
for(yjob=0; yjob<=1; yjob++)
{
for(pass=1; pass<=passcount; pass++)
{
/*
* Prepare
*/
do
{
a1 = 2*ae_randomreal(_state)-1;
}
while(ae_fp_eq(a1,(double)(0)));
a1 = a1*xjob;
b1 = 2*ae_randomreal(_state)-1;
do
{
a2 = 2*ae_randomreal(_state)-1;
}
while(ae_fp_eq(a2,(double)(0)));
a2 = a2*yjob;
b2 = 2*ae_randomreal(_state)-1;
/*
* Test XY
*/
spline2dcopy(c, &c2, _state);
spline2dlintransxy(&c2, a1, b1, a2, b2, _state);
tx = ax+ae_randomreal(_state)*(bx-ax);
ty = ay+ae_randomreal(_state)*(by-ay);
if( xjob==0 )
{
tx = b1;
vx = ax+ae_randomreal(_state)*(bx-ax);
}
else
{
vx = (tx-b1)/a1;
}
if( yjob==0 )
{
ty = b2;
vy = ay+ae_randomreal(_state)*(by-ay);
}
else
{
vy = (ty-b2)/a2;
}
spline2dcalcv(c, tx, ty, &v1, _state);
spline2dcalcv(&c2, vx, vy, &v2, _state);
for(di=0; di<=d-1; di++)
{
err = ae_maxreal(err, ae_fabs(v1.ptr.p_double[di]-v2.ptr.p_double[di], _state), _state);
}
/*
* Test F
*/
spline2dcopy(c, &c2, _state);
spline2dlintransf(&c2, a1, b1, _state);
tx = ax+ae_randomreal(_state)*(bx-ax);
ty = ay+ae_randomreal(_state)*(by-ay);
spline2dcalcv(c, tx, ty, &v1, _state);
spline2dcalcv(&c2, tx, ty, &v2, _state);
for(di=0; di<=d-1; di++)
{
err = ae_maxreal(err, ae_fabs(a1*v1.ptr.p_double[di]+b1-v2.ptr.p_double[di], _state), _state);
}
}
}
}
result = ae_fp_less(err,10000*ae_machineepsilon);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Unset spline, i.e. initialize it with random garbage
*************************************************************************/
static void testspline2dunit_unsetspline2d(spline2dinterpolant* c,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector x;
ae_vector y;
ae_matrix f;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&f, 0, sizeof(f));
_spline2dinterpolant_clear(c);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&f, 0, 0, DT_REAL, _state, ae_true);
ae_vector_set_length(&x, 2, _state);
ae_vector_set_length(&y, 2, _state);
ae_matrix_set_length(&f, 2, 2, _state);
x.ptr.p_double[0] = (double)(-1);
x.ptr.p_double[1] = (double)(1);
y.ptr.p_double[0] = (double)(-1);
y.ptr.p_double[1] = (double)(1);
f.ptr.pp_double[0][0] = (double)(0);
f.ptr.pp_double[0][1] = (double)(0);
f.ptr.pp_double[1][0] = (double)(0);
f.ptr.pp_double[1][1] = (double)(0);
spline2dbuildbilinear(&x, &y, &f, 2, 2, c, _state);
ae_frame_leave(_state);
}
/*************************************************************************
The function check, that follow functions works correctly:
Spline2DBilinearV, Spline2DBicubicV, Spline2DCalcV, Spline2DCalcVI,
Spline2DDiffVI and Spline2DUnpackV.
*************************************************************************/
static ae_bool testspline2dunit_testspline2dvf(ae_bool silent,
ae_state *_state)
{
ae_frame _frame_block;
spline2dinterpolant vc;
spline2dinterpolant sc;
double range;
ae_vector x;
ae_vector y;
ae_vector f;
double rndx;
double rndy;
ae_vector resf;
ae_matrix ef;
double resef;
ae_int_t m;
ae_int_t n;
ae_int_t d;
ae_int_t tstn;
ae_int_t tstm;
ae_int_t tstd;
ae_matrix tsttbl0;
ae_matrix tsttbl1;
double eps;
double st;
ae_int_t p0;
ae_int_t p1;
ae_int_t variant;
ae_int_t pass;
ae_int_t passcount;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t i0;
ae_int_t j0;
double xmin;
double xmax;
double ymin;
double ymax;
double vi;
double vxi;
double vyi;
double vxyi;
double si;
double sxi;
double syi;
double sxyi;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&vc, 0, sizeof(vc));
memset(&sc, 0, sizeof(sc));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&f, 0, sizeof(f));
memset(&resf, 0, sizeof(resf));
memset(&ef, 0, sizeof(ef));
memset(&tsttbl0, 0, sizeof(tsttbl0));
memset(&tsttbl1, 0, sizeof(tsttbl1));
_spline2dinterpolant_init(&vc, _state, ae_true);
_spline2dinterpolant_init(&sc, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&f, 0, DT_REAL, _state, ae_true);
ae_vector_init(&resf, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ef, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&tsttbl0, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&tsttbl1, 0, 0, DT_REAL, _state, ae_true);
eps = 10000.0*ae_machineepsilon;
st = 0.1;
passcount = 5;
result = ae_false;
for(pass=1; pass<=passcount; pass++)
{
for(variant=1; variant<=2; variant++)
{
range = (double)(ae_randominteger(71, _state)+30);
m = ae_randominteger(4, _state)+2;
n = ae_randominteger(4, _state)+2;
d = ae_randominteger(3, _state)+1;
rvectorsetlengthatleast(&x, n, _state);
rvectorsetlengthatleast(&y, m, _state);
rvectorsetlengthatleast(&f, n*m*d, _state);
rmatrixsetlengthatleast(&ef, m, n, _state);
/*
* Build a grid for spline
*/
x.ptr.p_double[0] = range*(2*ae_randomreal(_state)-1);
y.ptr.p_double[0] = range*(2*ae_randomreal(_state)-1);
for(i=1; i<=n-1; i++)
{
x.ptr.p_double[i] = x.ptr.p_double[i-1]+st+ae_randomreal(_state);
}
for(i=1; i<=m-1; i++)
{
y.ptr.p_double[i] = y.ptr.p_double[i-1]+st+ae_randomreal(_state);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
for(k=0; k<=d-1; k++)
{
f.ptr.p_double[d*(n*j+i)+k] = range*(2*ae_randomreal(_state)-1);
}
}
}
xmin = x.ptr.p_double[0];
xmax = x.ptr.p_double[n-1];
ymin = y.ptr.p_double[0];
ymax = y.ptr.p_double[m-1];
/*
* Build a spline
*/
if( variant==1 )
{
spline2dbuildbilinearv(&x, n, &y, m, &f, d, &vc, _state);
}
if( variant==2 )
{
spline2dbuildbicubicv(&x, n, &y, m, &f, d, &vc, _state);
}
/*
* Part of test, which shows that Spline2DBuildBilinearV function
* works correctly.
* And there is test for Spline2DUnpackV.
*/
spline2dunpackv(&vc, &tstm, &tstn, &tstd, &tsttbl1, _state);
if( (tstm!=m||tstn!=n)||tstd!=d )
{
if( !silent )
{
printf("TestSpline2DVF fail Spline2DUnpack:\n");
printf(" TstM=%0d; M=%0d;\n TstN=%0d; N=%0d;\n TstD=%0d; D=%0d.\n",
(int)(tstm),
(int)(m),
(int)(tstn),
(int)(n),
(int)(tstd),
(int)(d));
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(k=0; k<=d-1; k++)
{
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
ef.ptr.pp_double[i][j] = f.ptr.p_double[d*(i*n+j)+k];
}
}
if( variant==1 )
{
spline2dbuildbilinear(&x, &y, &ef, m, n, &sc, _state);
}
if( variant==2 )
{
spline2dbuildbicubic(&x, &y, &ef, m, n, &sc, _state);
}
spline2dunpack(&sc, &tstm, &tstn, &tsttbl0, _state);
if( tstm!=m||tstn!=n )
{
if( !silent )
{
printf("TestSpline2DVF fail Spline2DUnpack:\n");
printf(" TstM=%0d; M=%0d;\n TstN=%0d; N=%0d.\n",
(int)(tstm),
(int)(m),
(int)(tstn),
(int)(n));
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=m-2; i++)
{
for(j=0; j<=n-2; j++)
{
p0 = i*(n-1)+j;
p1 = d*p0;
for(i0=0; i0<=19; i0++)
{
if( ae_fp_neq(tsttbl1.ptr.pp_double[p1+k][i0],tsttbl0.ptr.pp_double[p0][i0]) )
{
if( !silent )
{
printf("TestSpline2DVF: Tbl error\n");
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
}
/*
* Part of test, which shows that functions Spline2DCalcVBuf, Spline2DDiffVI,
* Spline2DCalcVI and Spline2DCalcV work correctly
*/
for(k=0; k<=d-1; k++)
{
/*
* Build 1D spline corresponding to selected dimension (already tested)
*/
for(i0=0; i0<=m-1; i0++)
{
for(j0=0; j0<=n-1; j0++)
{
ef.ptr.pp_double[i0][j0] = f.ptr.p_double[d*(i0*n+j0)+k];
}
}
if( variant==1 )
{
spline2dbuildbilinear(&x, &y, &ef, m, n, &sc, _state);
}
if( variant==2 )
{
spline2dbuildbicubic(&x, &y, &ef, m, n, &sc, _state);
}
/*
* test at grid points
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=m-1; j++)
{
/*
* Test calculation at grid points
*/
spline2dcalcv(&vc, x.ptr.p_double[i], y.ptr.p_double[j], &resf, _state);
resef = spline2dcalc(&sc, x.ptr.p_double[i], y.ptr.p_double[j], _state);
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(resf.ptr.p_double[k]-resef, _state),eps), __FILE__, __LINE__, "testspline2dunit.ap:914");
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(spline2dcalcvi(&vc, x.ptr.p_double[i], y.ptr.p_double[j], k, _state)-resef, _state),eps), __FILE__, __LINE__, "testspline2dunit.ap:915");
/*
* Test differentiation at grid points
*/
spline2ddiffvi(&vc, x.ptr.p_double[i], y.ptr.p_double[j], k, &vi, &vxi, &vyi, &vxyi, _state);
spline2ddiff(&sc, x.ptr.p_double[i], y.ptr.p_double[j], &si, &sxi, &syi, &sxyi, _state);
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vi-si, _state),eps*(ae_fabs(si, _state)+1)), __FILE__, __LINE__, "testspline2dunit.ap:922");
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vxi-sxi, _state),eps*(ae_fabs(sxi, _state)+1)), __FILE__, __LINE__, "testspline2dunit.ap:923");
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vyi-syi, _state),eps*(ae_fabs(syi, _state)+1)), __FILE__, __LINE__, "testspline2dunit.ap:924");
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vxyi-sxyi, _state),eps*(ae_fabs(sxyi, _state)+1)), __FILE__, __LINE__, "testspline2dunit.ap:925");
}
}
/*
* Test at random points
*/
for(i=0; i<=n*m-1; i++)
{
rndx = xmin+(xmax-xmin)*ae_randomreal(_state);
rndy = ymin+(ymax-ymin)*ae_randomreal(_state);
/*
* Test calculation at random points
*/
spline2dcalcv(&vc, rndx, rndy, &resf, _state);
resef = spline2dcalc(&sc, rndx, rndy, _state);
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(resf.ptr.p_double[k]-resef, _state),eps), __FILE__, __LINE__, "testspline2dunit.ap:941");
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(spline2dcalcvi(&vc, rndx, rndy, k, _state)-resef, _state),eps), __FILE__, __LINE__, "testspline2dunit.ap:942");
/*
* Test differentiation at random points
*/
spline2ddiffvi(&vc, rndx, rndy, k, &vi, &vxi, &vyi, &vxyi, _state);
spline2ddiff(&sc, rndx, rndy, &si, &sxi, &syi, &sxyi, _state);
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vi-si, _state),eps*(ae_fabs(si, _state)+1)), __FILE__, __LINE__, "testspline2dunit.ap:949");
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vxi-sxi, _state),eps*(ae_fabs(sxi, _state)+1)), __FILE__, __LINE__, "testspline2dunit.ap:950");
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vyi-syi, _state),eps*(ae_fabs(syi, _state)+1)), __FILE__, __LINE__, "testspline2dunit.ap:951");
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vxyi-sxyi, _state),eps*(ae_fabs(sxyi, _state)+1)), __FILE__, __LINE__, "testspline2dunit.ap:952");
}
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Fitting, properties of linear prior term
*************************************************************************/
static void testspline2dunit_testfittingprior(ae_bool* errorflag,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector kv;
ae_int_t d;
ae_int_t kidx;
ae_int_t areatype;
ae_int_t solvertype;
ae_int_t i;
ae_int_t j;
ae_int_t k;
hqrndstate rs;
double tol;
spline2dbuilder state;
spline2dinterpolant s;
spline2dinterpolant s2;
spline2dinterpolant s3;
spline2dfitreport rep;
spline2dfitreport rep2;
spline2dfitreport rep3;
ae_int_t kx;
ae_int_t ky;
ae_int_t npoints;
ae_matrix xy;
ae_matrix xy2;
ae_matrix xy3;
ae_matrix vterm;
double vprior;
double v;
ae_bool bad;
ae_vector meany;
ae_vector tmp0;
ae_vector tmp1;
ae_frame_make(_state, &_frame_block);
memset(&kv, 0, sizeof(kv));
memset(&rs, 0, sizeof(rs));
memset(&state, 0, sizeof(state));
memset(&s, 0, sizeof(s));
memset(&s2, 0, sizeof(s2));
memset(&s3, 0, sizeof(s3));
memset(&rep, 0, sizeof(rep));
memset(&rep2, 0, sizeof(rep2));
memset(&rep3, 0, sizeof(rep3));
memset(&xy, 0, sizeof(xy));
memset(&xy2, 0, sizeof(xy2));
memset(&xy3, 0, sizeof(xy3));
memset(&vterm, 0, sizeof(vterm));
memset(&meany, 0, sizeof(meany));
memset(&tmp0, 0, sizeof(tmp0));
memset(&tmp1, 0, sizeof(tmp1));
ae_vector_init(&kv, 0, DT_INT, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
_spline2dbuilder_init(&state, _state, ae_true);
_spline2dinterpolant_init(&s, _state, ae_true);
_spline2dinterpolant_init(&s2, _state, ae_true);
_spline2dinterpolant_init(&s3, _state, ae_true);
_spline2dfitreport_init(&rep, _state, ae_true);
_spline2dfitreport_init(&rep2, _state, ae_true);
_spline2dfitreport_init(&rep3, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy3, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&vterm, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&meany, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true);
hqrndrandomize(&rs, _state);
tol = 1.0E-5;
/*
* Check properties of underlying linear prior.
*/
ae_vector_set_length(&kv, 3, _state);
kv.ptr.p_int[0] = 5;
kv.ptr.p_int[1] = 10;
kv.ptr.p_int[2] = 16;
for(kidx=0; kidx<=kv.cnt-1; kidx++)
{
for(d=1; d<=3; d++)
{
for(areatype=0; areatype<=0; areatype++)
{
for(solvertype=1; solvertype<=2; solvertype++)
{
/*
* Select grid size and create builder
*/
kx = 1+hqrnduniformi(&rs, kv.ptr.p_int[kidx], _state);
ky = 1+hqrnduniformi(&rs, kv.ptr.p_int[kidx], _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
kx = kv.ptr.p_int[kidx];
}
else
{
ky = kv.ptr.p_int[kidx];
}
spline2dbuildercreate(d, &state, _state);
spline2dbuildersetgrid(&state, kx, ky, _state);
if( solvertype==1 )
{
spline2dbuildersetalgoblocklls(&state, 0.0, _state);
}
else
{
if( solvertype==2 )
{
spline2dbuildersetalgonaivells(&state, 0.0, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
/*
* Generate perfectly linear dataset, check against linear prior.
* At least 8 points is required to get stable results.
*
* NOTE: we also check that constant term does NOT work.
*/
ae_matrix_set_length(&vterm, d, 3, _state);
for(i=0; i<=d-1; i++)
{
for(j=0; j<=2; j++)
{
vterm.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
npoints = 8+ae_round(10*hqrnduniformr(&rs, _state), _state);
ae_vector_set_length(&meany, d, _state);
for(j=0; j<=d-1; j++)
{
meany.ptr.p_double[j] = (double)(0);
}
ae_matrix_set_length(&xy, npoints, 2+d, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state);
xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state);
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][2+j] = vterm.ptr.pp_double[j][0]*xy.ptr.pp_double[i][0]+vterm.ptr.pp_double[j][1]*xy.ptr.pp_double[i][1]+vterm.ptr.pp_double[j][2];
meany.ptr.p_double[j] = meany.ptr.p_double[j]+xy.ptr.pp_double[i][2+j]/npoints;
}
}
spline2dbuildersetpoints(&state, &xy, npoints, _state);
spline2dbuildersetlinterm(&state, _state);
spline2dfit(&state, &s, &rep, _state);
ae_vector_set_length(&tmp0, 3, _state);
for(k=0; k<=10; k++)
{
tmp0.ptr.p_double[0] = 3*hqrnduniformr(&rs, _state)-1;
tmp0.ptr.p_double[1] = 3*hqrnduniformr(&rs, _state)-1;
tmp0.ptr.p_double[2] = 1.0;
spline2dcalcv(&s, tmp0.ptr.p_double[0], tmp0.ptr.p_double[1], &tmp1, _state);
for(j=0; j<=d-1; j++)
{
v = vterm.ptr.pp_double[j][0]*tmp0.ptr.p_double[0]+vterm.ptr.pp_double[j][1]*tmp0.ptr.p_double[1]+vterm.ptr.pp_double[j][2];
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(tmp1.ptr.p_double[j]-v, _state)/ae_maxreal(ae_fabs(v, _state), (double)(1), _state),tol), __FILE__, __LINE__, "testspline2dunit.ap:1094");
}
}
ae_set_error_flag(errorflag, ae_fp_greater(rep.rmserror,tol), __FILE__, __LINE__, "testspline2dunit.ap:1097");
ae_set_error_flag(errorflag, ae_fp_greater(rep.avgerror,tol), __FILE__, __LINE__, "testspline2dunit.ap:1098");
ae_set_error_flag(errorflag, ae_fp_greater(rep.maxerror,tol), __FILE__, __LINE__, "testspline2dunit.ap:1099");
spline2dbuildersetconstterm(&state, _state);
spline2dfit(&state, &s, &rep, _state);
ae_vector_set_length(&tmp0, 3, _state);
bad = ae_false;
for(k=0; k<=10; k++)
{
tmp0.ptr.p_double[0] = 2+hqrnduniformr(&rs, _state);
tmp0.ptr.p_double[1] = 2+hqrnduniformr(&rs, _state);
tmp0.ptr.p_double[2] = 1.0;
spline2dcalcv(&s, tmp0.ptr.p_double[0], tmp0.ptr.p_double[1], &tmp1, _state);
for(j=0; j<=d-1; j++)
{
v = vterm.ptr.pp_double[j][0]*tmp0.ptr.p_double[0]+vterm.ptr.pp_double[j][1]*tmp0.ptr.p_double[1]+vterm.ptr.pp_double[j][2];
bad = bad||ae_fp_greater(ae_fabs(tmp1.ptr.p_double[j]-v, _state),tol);
}
}
ae_set_error_flag(errorflag, !bad, __FILE__, __LINE__, "testspline2dunit.ap:1118");
/*
* Generate perfectly constant dataset, check against constant prior.
* At least 8 points is required to get stable results.
*/
ae_matrix_set_length(&vterm, d, 3, _state);
for(i=0; i<=d-1; i++)
{
for(j=0; j<=1; j++)
{
vterm.ptr.pp_double[i][j] = (double)(0);
}
vterm.ptr.pp_double[i][2] = hqrndnormal(&rs, _state);
}
npoints = 8+ae_round(10*hqrnduniformr(&rs, _state), _state);
ae_vector_set_length(&meany, d, _state);
for(j=0; j<=d-1; j++)
{
meany.ptr.p_double[j] = (double)(0);
}
ae_matrix_set_length(&xy, npoints, 2+d, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state);
xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state);
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][2+j] = vterm.ptr.pp_double[j][0]*xy.ptr.pp_double[i][0]+vterm.ptr.pp_double[j][1]*xy.ptr.pp_double[i][1]+vterm.ptr.pp_double[j][2];
meany.ptr.p_double[j] = meany.ptr.p_double[j]+xy.ptr.pp_double[i][2+j]/npoints;
}
}
spline2dbuildersetpoints(&state, &xy, npoints, _state);
spline2dbuildersetconstterm(&state, _state);
spline2dfit(&state, &s, &rep, _state);
ae_vector_set_length(&tmp0, 3, _state);
for(k=0; k<=10; k++)
{
tmp0.ptr.p_double[0] = 3*hqrnduniformr(&rs, _state)-1;
tmp0.ptr.p_double[1] = 3*hqrnduniformr(&rs, _state)-1;
tmp0.ptr.p_double[2] = 1.0;
spline2dcalcv(&s, tmp0.ptr.p_double[0], tmp0.ptr.p_double[1], &tmp1, _state);
for(j=0; j<=d-1; j++)
{
v = vterm.ptr.pp_double[j][0]*tmp0.ptr.p_double[0]+vterm.ptr.pp_double[j][1]*tmp0.ptr.p_double[1]+vterm.ptr.pp_double[j][2];
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(tmp1.ptr.p_double[j]-v, _state)/ae_maxreal(ae_fabs(v, _state), (double)(1), _state),tol), __FILE__, __LINE__, "testspline2dunit.ap:1159");
}
}
ae_set_error_flag(errorflag, ae_fp_greater(rep.rmserror,tol), __FILE__, __LINE__, "testspline2dunit.ap:1162");
ae_set_error_flag(errorflag, ae_fp_greater(rep.avgerror,tol), __FILE__, __LINE__, "testspline2dunit.ap:1163");
ae_set_error_flag(errorflag, ae_fp_greater(rep.maxerror,tol), __FILE__, __LINE__, "testspline2dunit.ap:1164");
/*
* Generate perfectly constant dataset, check against user-defined constant prior.
* At least 8 points is required to get stable results.
*/
vprior = hqrndnormal(&rs, _state);
npoints = 8+ae_round(10*hqrnduniformr(&rs, _state), _state);
ae_vector_set_length(&meany, d, _state);
for(j=0; j<=d-1; j++)
{
meany.ptr.p_double[j] = (double)(0);
}
ae_matrix_set_length(&xy, npoints, 2+d, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state);
xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state);
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][2+j] = vprior;
meany.ptr.p_double[j] = meany.ptr.p_double[j]+xy.ptr.pp_double[i][2+j]/npoints;
}
}
spline2dbuildersetpoints(&state, &xy, npoints, _state);
spline2dbuildersetuserterm(&state, vprior, _state);
spline2dfit(&state, &s, &rep, _state);
ae_vector_set_length(&tmp0, 3, _state);
for(k=0; k<=10; k++)
{
tmp0.ptr.p_double[0] = 3*hqrnduniformr(&rs, _state)-1;
tmp0.ptr.p_double[1] = 3*hqrnduniformr(&rs, _state)-1;
tmp0.ptr.p_double[2] = 1.0;
spline2dcalcv(&s, tmp0.ptr.p_double[0], tmp0.ptr.p_double[1], &tmp1, _state);
for(j=0; j<=d-1; j++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(tmp1.ptr.p_double[j]-vprior, _state),tol), __FILE__, __LINE__, "testspline2dunit.ap:1199");
}
}
ae_set_error_flag(errorflag, ae_fp_greater(rep.rmserror,tol), __FILE__, __LINE__, "testspline2dunit.ap:1201");
ae_set_error_flag(errorflag, ae_fp_greater(rep.avgerror,tol), __FILE__, __LINE__, "testspline2dunit.ap:1202");
ae_set_error_flag(errorflag, ae_fp_greater(rep.maxerror,tol), __FILE__, __LINE__, "testspline2dunit.ap:1203");
spline2dbuildersetuserterm(&state, vprior+(2*hqrnduniformi(&rs, 2, _state)-1), _state);
spline2dfit(&state, &s, &rep, _state);
ae_vector_set_length(&tmp0, 3, _state);
for(k=0; k<=10; k++)
{
tmp0.ptr.p_double[0] = 2+hqrnduniformr(&rs, _state);
tmp0.ptr.p_double[1] = 2+hqrnduniformr(&rs, _state);
tmp0.ptr.p_double[2] = 1.0;
spline2dcalcv(&s, tmp0.ptr.p_double[0], tmp0.ptr.p_double[1], &tmp1, _state);
for(j=0; j<=d-1; j++)
{
ae_set_error_flag(errorflag, ae_fp_less_eq(ae_fabs(tmp1.ptr.p_double[j]-vprior, _state),tol), __FILE__, __LINE__, "testspline2dunit.ap:1216");
}
}
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Nonlinearity penalty test
*************************************************************************/
static void testspline2dunit_testfittingpenalty(ae_bool* errorflag,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t kidx;
ae_int_t pidx;
ae_int_t solvertype;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t d;
ae_int_t kx;
ae_int_t ky;
ae_int_t npoints;
ae_matrix xy;
spline2dinterpolant s;
spline2dinterpolant s2;
spline2dfitreport rep;
spline2dfitreport rep2;
hqrndstate rs;
spline2dbuilder state;
double rmserror;
ae_vector penalty;
ae_vector penalty2;
double v;
double v0;
double v1;
double f0;
double f1;
double f2;
double f3;
ae_frame_make(_state, &_frame_block);
memset(&xy, 0, sizeof(xy));
memset(&s, 0, sizeof(s));
memset(&s2, 0, sizeof(s2));
memset(&rep, 0, sizeof(rep));
memset(&rep2, 0, sizeof(rep2));
memset(&rs, 0, sizeof(rs));
memset(&state, 0, sizeof(state));
memset(&penalty, 0, sizeof(penalty));
memset(&penalty2, 0, sizeof(penalty2));
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_spline2dinterpolant_init(&s, _state, ae_true);
_spline2dinterpolant_init(&s2, _state, ae_true);
_spline2dfitreport_init(&rep, _state, ae_true);
_spline2dfitreport_init(&rep2, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
_spline2dbuilder_init(&state, _state, ae_true);
ae_vector_init(&penalty, 0, DT_REAL, _state, ae_true);
ae_vector_init(&penalty2, 0, DT_REAL, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Penalized fitting problem:
* * square KxK grid, K>=8 (points do not "touch" each other by their far fields)
* * four points in the corners, perfectly linear value
* * zero prior term
*
* Check that:
* * with significant nonlinearity penalty we have nearly-linear fit,
* central value is an average of corner values
* * without nonlinearity penalty, central value is zero
*/
for(kidx=3; kidx<=4; kidx++)
{
for(solvertype=1; solvertype<=2; solvertype++)
{
/*
* Generate dataset
*/
kx = ae_round(ae_pow((double)(2), (double)(kidx), _state), _state);
ky = kx;
npoints = 4;
ae_matrix_set_length(&xy, npoints, 3, _state);
xy.ptr.pp_double[0][0] = (double)(-1);
xy.ptr.pp_double[0][1] = (double)(-1);
xy.ptr.pp_double[0][2] = hqrndnormal(&rs, _state);
xy.ptr.pp_double[1][0] = (double)(1);
xy.ptr.pp_double[1][1] = (double)(-1);
xy.ptr.pp_double[1][2] = hqrndnormal(&rs, _state);
xy.ptr.pp_double[2][0] = (double)(-1);
xy.ptr.pp_double[2][1] = (double)(1);
xy.ptr.pp_double[2][2] = hqrndnormal(&rs, _state);
xy.ptr.pp_double[3][0] = (double)(1);
xy.ptr.pp_double[3][1] = (double)(1);
xy.ptr.pp_double[3][2] = xy.ptr.pp_double[0][2]+(xy.ptr.pp_double[1][2]-xy.ptr.pp_double[0][2])+(xy.ptr.pp_double[2][2]-xy.ptr.pp_double[0][2]);
/*
* Create solver, set grid, area and other properties
* according to chosen test mode.
*/
spline2dbuildercreate(1, &state, _state);
spline2dbuildersetgrid(&state, kx, ky, _state);
spline2dbuildersetarea(&state, (double)(-1), (double)(1), (double)(-1), (double)(1), _state);
spline2dbuildersetpoints(&state, &xy, npoints, _state);
spline2dbuildersetzeroterm(&state, _state);
/*
* Check fitting with penalty
*/
if( solvertype==1 )
{
spline2dbuildersetalgoblocklls(&state, 1.0, _state);
}
else
{
if( solvertype==2 )
{
spline2dbuildersetalgonaivells(&state, 1.0, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
spline2dfit(&state, &s, &rep, _state);
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(spline2dcalc(&s, 0.0, 0.0, _state)-0.25*(xy.ptr.pp_double[0][2]+xy.ptr.pp_double[1][2]+xy.ptr.pp_double[2][2]+xy.ptr.pp_double[3][2]), _state),1.0E-4), __FILE__, __LINE__, "testspline2dunit.ap:1305");
/*
* Check fitting without penalty
*/
if( solvertype==1 )
{
spline2dbuildersetalgoblocklls(&state, 0.0, _state);
}
else
{
if( solvertype==2 )
{
spline2dbuildersetalgonaivells(&state, 0.0, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
spline2dfit(&state, &s2, &rep2, _state);
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(spline2dcalc(&s2, 0.0, 0.0, _state), _state),1.0E-4), __FILE__, __LINE__, "testspline2dunit.ap:1318");
}
}
/*
* Solve a sequence of problems with increasing value of penalty coefficient;
* test that increasing penalty coefficient results in:
* * increased residuals
* * decreased value of penalty function
*/
for(solvertype=1; solvertype<=2; solvertype++)
{
for(d=1; d<=3; d++)
{
/*
* Prepare solver and dataset
*/
kx = 6+hqrnduniformi(&rs, 5, _state);
ky = 6+hqrnduniformi(&rs, 5, _state);
npoints = 3*(kx+2)*(ky+2)+30;
ae_matrix_set_length(&xy, npoints, 2+d, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state);
xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state);
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state);
}
}
spline2dbuildercreate(d, &state, _state);
spline2dbuildersetgrid(&state, kx, ky, _state);
if( solvertype==1 )
{
spline2dbuildersetalgoblocklls(&state, 0.0, _state);
}
else
{
if( solvertype==2 )
{
spline2dbuildersetalgonaivells(&state, 0.0, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
spline2dbuildersetarea(&state, (double)(0), (double)(1), (double)(0), (double)(1), _state);
spline2dbuildersetpoints(&state, &xy, npoints, _state);
spline2dbuildersetzeroterm(&state, _state);
/*
* Solve with zero penalty
*/
spline2dfit(&state, &s, &rep, _state);
rmserror = rep.rmserror;
ae_vector_set_length(&penalty, d, _state);
for(k=0; k<=d-1; k++)
{
penalty.ptr.p_double[k] = 0.0;
}
v = 1.0E-3;
for(i=0; i<=kx-1; i++)
{
for(j=0; j<=ky-1; j++)
{
v0 = (double)i/(double)(kx-1);
v1 = (double)j/(double)(ky-1);
for(k=0; k<=d-1; k++)
{
f0 = spline2dcalcvi(&s, v0-v, v1, k, _state);
f1 = spline2dcalcvi(&s, v0, v1, k, _state);
f2 = spline2dcalcvi(&s, v0+v, v1, k, _state);
penalty.ptr.p_double[k] = penalty.ptr.p_double[k]+ae_sqr((f0+f2-2*f1)/ae_sqr(v, _state), _state);
}
for(k=0; k<=d-1; k++)
{
f0 = spline2dcalcvi(&s, v0, v1-v, k, _state);
f1 = spline2dcalcvi(&s, v0, v1, k, _state);
f2 = spline2dcalcvi(&s, v0, v1+v, k, _state);
penalty.ptr.p_double[k] = penalty.ptr.p_double[k]+ae_sqr((f0+f2-2*f1)/ae_sqr(v, _state), _state);
}
for(k=0; k<=d-1; k++)
{
f0 = spline2dcalcvi(&s, v0-v, v1-v, k, _state);
f1 = spline2dcalcvi(&s, v0+v, v1-v, k, _state);
f2 = spline2dcalcvi(&s, v0-v, v1+v, k, _state);
f3 = spline2dcalcvi(&s, v0+v, v1+v, k, _state);
penalty.ptr.p_double[k] = penalty.ptr.p_double[k]+2*ae_sqr((f3-f2-f1+f0)/ae_sqr(v, _state), _state);
}
}
}
/*
* Solve with non-zero penalty
*/
for(pidx=-6; pidx<=3; pidx++)
{
if( solvertype==1 )
{
spline2dbuildersetalgoblocklls(&state, ae_pow((double)(10), (double)pidx/(double)2, _state), _state);
}
else
{
if( solvertype==2 )
{
spline2dbuildersetalgonaivells(&state, ae_pow((double)(10), (double)pidx/(double)2, _state), _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
spline2dfit(&state, &s, &rep, _state);
ae_vector_set_length(&penalty2, d, _state);
for(k=0; k<=d-1; k++)
{
penalty2.ptr.p_double[k] = 0.0;
}
v = 1.0E-3;
for(i=0; i<=kx-1; i++)
{
for(j=0; j<=ky-1; j++)
{
v0 = (double)i/(double)(kx-1);
v1 = (double)j/(double)(ky-1);
for(k=0; k<=d-1; k++)
{
f0 = spline2dcalcvi(&s, v0-v, v1, k, _state);
f1 = spline2dcalcvi(&s, v0, v1, k, _state);
f2 = spline2dcalcvi(&s, v0+v, v1, k, _state);
penalty2.ptr.p_double[k] = penalty2.ptr.p_double[k]+ae_sqr((f0+f2-2*f1)/ae_sqr(v, _state), _state);
}
for(k=0; k<=d-1; k++)
{
f0 = spline2dcalcvi(&s, v0, v1-v, k, _state);
f1 = spline2dcalcvi(&s, v0, v1, k, _state);
f2 = spline2dcalcvi(&s, v0, v1+v, k, _state);
penalty2.ptr.p_double[k] = penalty2.ptr.p_double[k]+ae_sqr((f0+f2-2*f1)/ae_sqr(v, _state), _state);
}
for(k=0; k<=d-1; k++)
{
f0 = spline2dcalcvi(&s, v0-v, v1-v, k, _state);
f1 = spline2dcalcvi(&s, v0+v, v1-v, k, _state);
f2 = spline2dcalcvi(&s, v0-v, v1+v, k, _state);
f3 = spline2dcalcvi(&s, v0+v, v1+v, k, _state);
penalty2.ptr.p_double[k] = penalty2.ptr.p_double[k]+2*ae_sqr((f3-f2-f1+f0)/ae_sqr(v, _state), _state);
}
}
}
ae_set_error_flag(errorflag, ae_fp_less_eq(rep.rmserror,rmserror), __FILE__, __LINE__, "testspline2dunit.ap:1448");
for(k=0; k<=d-1; k++)
{
ae_set_error_flag(errorflag, ae_fp_greater_eq(penalty2.ptr.p_double[k],penalty.ptr.p_double[k]), __FILE__, __LINE__, "testspline2dunit.ap:1450");
}
rmserror = rep.rmserror;
for(k=0; k<=d-1; k++)
{
penalty.ptr.p_double[k] = penalty2.ptr.p_double[k];
}
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Block solver test for fitting functionality
*************************************************************************/
static void testspline2dunit_testfittingblocksolver(ae_bool* errorflag,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector kv;
ae_int_t d;
ae_int_t kidx;
ae_int_t areatype;
ae_int_t gridtype;
ae_int_t solvertype;
ae_int_t i;
ae_int_t j;
ae_int_t k;
hqrndstate rs;
double errtol;
spline2dbuilder state;
spline2dinterpolant s;
spline2dinterpolant s2;
spline2dinterpolant s3;
spline2dfitreport rep;
spline2dfitreport rep2;
spline2dfitreport rep3;
ae_int_t kx;
ae_int_t ky;
double w1;
double xc;
double yc;
ae_int_t npoints;
ae_matrix xy;
ae_matrix xy2;
ae_matrix xy3;
ae_matrix vterm;
ae_int_t priortype;
double mx;
double rmserror;
double avgerror;
double maxerror;
double rss;
double tss;
double r2;
double v;
double v0;
double v1;
ae_vector meany;
ae_vector tmp0;
ae_vector tmp1;
ae_frame_make(_state, &_frame_block);
memset(&kv, 0, sizeof(kv));
memset(&rs, 0, sizeof(rs));
memset(&state, 0, sizeof(state));
memset(&s, 0, sizeof(s));
memset(&s2, 0, sizeof(s2));
memset(&s3, 0, sizeof(s3));
memset(&rep, 0, sizeof(rep));
memset(&rep2, 0, sizeof(rep2));
memset(&rep3, 0, sizeof(rep3));
memset(&xy, 0, sizeof(xy));
memset(&xy2, 0, sizeof(xy2));
memset(&xy3, 0, sizeof(xy3));
memset(&vterm, 0, sizeof(vterm));
memset(&meany, 0, sizeof(meany));
memset(&tmp0, 0, sizeof(tmp0));
memset(&tmp1, 0, sizeof(tmp1));
ae_vector_init(&kv, 0, DT_INT, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
_spline2dbuilder_init(&state, _state, ae_true);
_spline2dinterpolant_init(&s, _state, ae_true);
_spline2dinterpolant_init(&s2, _state, ae_true);
_spline2dinterpolant_init(&s3, _state, ae_true);
_spline2dfitreport_init(&rep, _state, ae_true);
_spline2dfitreport_init(&rep2, _state, ae_true);
_spline2dfitreport_init(&rep3, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy3, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&vterm, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&meany, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tmp1, 0, DT_REAL, _state, ae_true);
hqrndrandomize(&rs, _state);
errtol = 1.0E-6;
/*
* Check that default state (no dataset) results in zero model being returned.
*/
for(priortype=0; priortype<=2; priortype++)
{
for(d=1; d<=3; d++)
{
for(areatype=0; areatype<=1; areatype++)
{
for(gridtype=0; gridtype<=1; gridtype++)
{
for(solvertype=1; solvertype<=2; solvertype++)
{
/*
* Create solver, set grid, area and other properties
* according to chosen test mode.
*/
kx = ae_maxint(4, 1+hqrnduniformi(&rs, 10, _state), _state);
ky = ae_maxint(4, 1+hqrnduniformi(&rs, 10, _state), _state);
spline2dbuildercreate(d, &state, _state);
if( gridtype==1 )
{
spline2dbuildersetgrid(&state, kx, ky, _state);
}
if( solvertype==1 )
{
spline2dbuildersetalgoblocklls(&state, 0.0, _state);
}
else
{
if( solvertype==2 )
{
spline2dbuildersetalgonaivells(&state, 0.0, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
if( areatype==0 )
{
spline2dbuildersetareaauto(&state, _state);
}
else
{
if( areatype==1 )
{
spline2dbuildersetarea(&state, (double)(0), (double)(1), (double)(0), (double)(1), _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
if( priortype==0 )
{
spline2dbuildersetlinterm(&state, _state);
}
else
{
if( priortype==1 )
{
spline2dbuildersetconstterm(&state, _state);
}
else
{
if( priortype==2 )
{
spline2dbuildersetzeroterm(&state, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
spline2dfit(&state, &s, &rep, _state);
/*
* Test
*/
for(j=0; j<=d-1; j++)
{
ae_set_error_flag(errorflag, ae_fp_neq(spline2dcalcvi(&s, hqrndnormal(&rs, _state), hqrndnormal(&rs, _state), j, _state),(double)(0)), __FILE__, __LINE__, "testspline2dunit.ap:1550");
}
ae_set_error_flag(errorflag, ae_fp_neq(rep.rmserror,(double)(0)), __FILE__, __LINE__, "testspline2dunit.ap:1551");
ae_set_error_flag(errorflag, ae_fp_neq(rep.avgerror,(double)(0)), __FILE__, __LINE__, "testspline2dunit.ap:1552");
ae_set_error_flag(errorflag, ae_fp_neq(rep.maxerror,(double)(0)), __FILE__, __LINE__, "testspline2dunit.ap:1553");
ae_set_error_flag(errorflag, ae_fp_neq(rep.r2,(double)(1)), __FILE__, __LINE__, "testspline2dunit.ap:1554");
}
}
}
}
}
/*
* Check properties of regression spline fitting WITHOUT nonlinearity
* penalty. Absence of penalty term allows us to perform several indirect
* tests which are impossible when working under penalty.
*
* Section below performs following tests on completely random dataset:
* * correctness of report fields
* * indirect tests for fitting solver (fitting on residuals from previous fit)
*/
ae_vector_set_length(&kv, 5, _state);
kv.ptr.p_int[0] = 4;
kv.ptr.p_int[1] = 5;
kv.ptr.p_int[2] = 10;
kv.ptr.p_int[3] = 12;
kv.ptr.p_int[4] = 15;
for(kidx=0; kidx<=kv.cnt-1; kidx++)
{
for(d=1; d<=3; d++)
{
for(areatype=0; areatype<=1; areatype++)
{
for(gridtype=1; gridtype<=1; gridtype++)
{
for(solvertype=1; solvertype<=2; solvertype++)
{
/*
* Generate dataset
*/
kx = ae_maxint(4, 1+hqrnduniformi(&rs, kv.ptr.p_int[kidx], _state), _state);
ky = ae_maxint(4, 1+hqrnduniformi(&rs, kv.ptr.p_int[kidx], _state), _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
kx = kv.ptr.p_int[kidx];
}
else
{
ky = kv.ptr.p_int[kidx];
}
w1 = ae_pow((double)(10), hqrndnormal(&rs, _state), _state);
xc = w1*(2*hqrnduniformr(&rs, _state)-1);
yc = w1*(2*hqrnduniformr(&rs, _state)-1);
ae_vector_set_length(&meany, d, _state);
for(j=0; j<=d-1; j++)
{
meany.ptr.p_double[j] = (double)(0);
}
npoints = ae_round((kx+2)*(ky+2)*(3+hqrnduniformr(&rs, _state)), _state);
ae_matrix_set_length(&xy, npoints, 2+d, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = xc+w1*(2*hqrnduniformr(&rs, _state)-1)*kx;
xy.ptr.pp_double[i][1] = yc+w1*(2*hqrnduniformr(&rs, _state)-1)*ky;
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state);
meany.ptr.p_double[j] = meany.ptr.p_double[j]+xy.ptr.pp_double[i][2+j]/npoints;
}
}
/*
* Create solver, set grid, area and other properties
* according to chosen test mode.
*/
spline2dbuildercreate(d, &state, _state);
if( gridtype==1 )
{
spline2dbuildersetgrid(&state, kx, ky, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
if( solvertype==1 )
{
spline2dbuildersetalgoblocklls(&state, 0.0, _state);
}
else
{
if( solvertype==2 )
{
spline2dbuildersetalgonaivells(&state, 0.0, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
if( areatype==0 )
{
spline2dbuildersetareaauto(&state, _state);
}
else
{
if( areatype==1 )
{
spline2dbuildersetarea(&state, xc-w1*kx, xc+w1*kx, yc-w1*ky, yc+w1*ky, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
spline2dbuildersetpoints(&state, &xy, npoints, _state);
spline2dfit(&state, &s, &rep, _state);
/*
* Test report fields
*/
rmserror = (double)(0);
avgerror = (double)(0);
maxerror = (double)(0);
rss = 0.0;
tss = 0.0;
for(i=0; i<=npoints-1; i++)
{
spline2dcalcv(&s, xy.ptr.pp_double[i][0], xy.ptr.pp_double[i][1], &tmp0, _state);
for(j=0; j<=d-1; j++)
{
v = xy.ptr.pp_double[i][2+j]-tmp0.ptr.p_double[j];
rss = rss+v*v;
tss = tss+ae_sqr(xy.ptr.pp_double[i][2+j]-meany.ptr.p_double[j], _state);
rmserror = rmserror+ae_sqr(v, _state);
avgerror = avgerror+ae_fabs(v, _state)/(npoints*d);
maxerror = ae_maxreal(maxerror, ae_fabs(v, _state), _state);
}
}
rmserror = ae_sqrt(rmserror/(npoints*d), _state);
r2 = 1.0-rss/coalesce(tss, (double)(1), _state);
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(rmserror-rep.rmserror, _state),errtol), __FILE__, __LINE__, "testspline2dunit.ap:1654");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(avgerror-rep.avgerror, _state),errtol), __FILE__, __LINE__, "testspline2dunit.ap:1655");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(maxerror-rep.maxerror, _state),errtol), __FILE__, __LINE__, "testspline2dunit.ap:1656");
if( ae_fp_greater(tss,1.0E-3) )
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(r2-rep.r2, _state),errtol), __FILE__, __LINE__, "testspline2dunit.ap:1658");
}
/*
* Minimalistic test for fitting quality: R2 is better than zero
* (zero value = fitting by median value).
*/
ae_set_error_flag(errorflag, ae_fp_less(rep.r2,0.0), __FILE__, __LINE__, "testspline2dunit.ap:1664");
/*
* Indirect test for solver: test that fitting on residuals from
* previous fitting does not significantly decrease residuals.
*
* In our test we require that residuals from residuals are
* greater than 0.8 times original residuals.
*
* In the ideal world, fitting on residuals will return same
* residuals, but during spline construction we made several
* compromises (regularization, pre-model phase). So, we just
* check that residuals are weakly decreased.
*
* NOTE: this test is performed only for significantly non-zero residuals
*/
if( ae_fp_greater(rep.rmserror,0.05) )
{
ae_matrix_set_length(&xy2, npoints, 2+d, _state);
for(i=0; i<=npoints-1; i++)
{
xy2.ptr.pp_double[i][0] = xy.ptr.pp_double[i][0];
xy2.ptr.pp_double[i][1] = xy.ptr.pp_double[i][1];
spline2dcalcv(&s, xy.ptr.pp_double[i][0], xy.ptr.pp_double[i][1], &tmp1, _state);
for(j=0; j<=d-1; j++)
{
xy2.ptr.pp_double[i][2+j] = xy.ptr.pp_double[i][2+j]-tmp1.ptr.p_double[j];
}
}
spline2dbuildersetpoints(&state, &xy2, npoints, _state);
spline2dfit(&state, &s2, &rep2, _state);
ae_set_error_flag(errorflag, ae_fp_less(rep2.rmserror,0.8*rep.rmserror), __FILE__, __LINE__, "testspline2dunit.ap:1693");
}
}
}
}
}
}
/*
* Direct test:
* * points on regular grid which is exactly the same as one used
* for regression, but with some noise added to point locations
* * we test that without penalty we get nearly-zero RMS error
*/
ae_vector_set_length(&kv, 5, _state);
kv.ptr.p_int[0] = 4;
kv.ptr.p_int[1] = 5;
kv.ptr.p_int[2] = 6;
kv.ptr.p_int[3] = 8;
kv.ptr.p_int[4] = 12;
for(kidx=0; kidx<=kv.cnt-1; kidx++)
{
for(d=1; d<=2; d++)
{
for(solvertype=1; solvertype<=2; solvertype++)
{
/*
* Generate dataset
*/
kx = ae_maxint(4, 1+hqrnduniformi(&rs, kv.ptr.p_int[kidx], _state), _state);
ky = ae_maxint(4, 1+hqrnduniformi(&rs, kv.ptr.p_int[kidx], _state), _state);
if( ae_fp_greater(hqrndnormal(&rs, _state),(double)(0)) )
{
kx = kv.ptr.p_int[kidx];
}
else
{
ky = kv.ptr.p_int[kidx];
}
npoints = kx*ky;
ae_matrix_set_length(&xy, npoints, 2+d, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = boundval(i%kx+0.05*hqrndnormal(&rs, _state), (double)(0), (double)(kx-1), _state);
xy.ptr.pp_double[i][1] = boundval(i/kx+0.05*hqrndnormal(&rs, _state), (double)(0), (double)(ky-1), _state);
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state);
}
}
/*
* Create solver, set grid, area and other properties
* according to chosen test mode.
*/
spline2dbuildercreate(d, &state, _state);
spline2dbuildersetgrid(&state, kx, ky, _state);
if( solvertype==1 )
{
spline2dbuildersetalgoblocklls(&state, 0.0, _state);
}
else
{
if( solvertype==2 )
{
spline2dbuildersetalgonaivells(&state, 0.0, _state);
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
spline2dbuildersetareaauto(&state, _state);
spline2dbuildersetpoints(&state, &xy, npoints, _state);
spline2dfit(&state, &s, &rep, _state);
/*
* Test
*/
for(i=0; i<=npoints-1; i++)
{
for(k=0; k<=d-1; k++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(spline2dcalcvi(&s, xy.ptr.pp_double[i][0], xy.ptr.pp_double[i][1], k, _state)-xy.ptr.pp_double[i][2+k], _state),1.0E-6), __FILE__, __LINE__, "testspline2dunit.ap:1754");
}
}
}
}
}
/*
* Compare results obtained with block solver vs naive one
*/
mx = (double)(0);
for(kx=4; kx<=8; kx++)
{
for(ky=4; ky<=8; ky++)
{
for(d=1; d<=2; d++)
{
/*
* Generate dataset
*/
npoints = 300;
ae_matrix_set_length(&xy, npoints, 2+d, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = (kx-1)*hqrnduniformr(&rs, _state);
xy.ptr.pp_double[i][1] = (ky-1)*hqrnduniformr(&rs, _state);
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state);
}
}
/*
* Create solver, set grid, area and other properties
* according to chosen test mode.
*
* NOTE: we perform just one iteration of LSQR in order
* to test subtle differences of two implementations -
* reference one (NaiveLLS) and high-performance one.
*/
spline2dbuildercreate(d, &state, _state);
spline2dbuildersetgrid(&state, kx, ky, _state);
spline2dbuildersetarea(&state, (double)(0), (double)(kx-1), (double)(0), (double)(ky-1), _state);
spline2dbuildersetpoints(&state, &xy, npoints, _state);
state.lsqrcnt = 1;
spline2dbuildersetalgonaivells(&state, 0.0, _state);
spline2dfit(&state, &s, &rep, _state);
spline2dbuildersetalgoblocklls(&state, 0.0, _state);
spline2dfit(&state, &s2, &rep2, _state);
for(i=0; i<=npoints-1; i++)
{
spline2dcalcv(&s, xy.ptr.pp_double[i][0], xy.ptr.pp_double[i][1], &tmp0, _state);
spline2dcalcv(&s2, xy.ptr.pp_double[i][0], xy.ptr.pp_double[i][1], &tmp1, _state);
for(j=0; j<=d-1; j++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(tmp0.ptr.p_double[j]-tmp1.ptr.p_double[j], _state),1.0E-6), __FILE__, __LINE__, "testspline2dunit.ap:1801");
mx = ae_maxreal(mx, ae_fabs(tmp0.ptr.p_double[j]-tmp1.ptr.p_double[j], _state), _state);
}
}
}
}
}
/*
* Investigate stability against minor perturbations
*/
d = 1;
kx = 20;
ky = 20;
npoints = 5*kx*ky;
ae_matrix_set_length(&xy, npoints, 2+d, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = (kx-1)*hqrnduniformr(&rs, _state);
xy.ptr.pp_double[i][1] = (ky-1)*hqrnduniformr(&rs, _state);
xy.ptr.pp_double[i][2] = hqrndnormal(&rs, _state);
}
spline2dbuildercreate(d, &state, _state);
spline2dbuildersetgrid(&state, kx, ky, _state);
spline2dbuildersetarea(&state, (double)(0), (double)(kx-1), (double)(0), (double)(ky-1), _state);
spline2dbuildersetalgoblocklls(&state, 0.001, _state);
spline2dbuildersetpoints(&state, &xy, npoints, _state);
spline2dfit(&state, &s, &rep, _state);
for(i=0; i<=npoints-1; i++)
{
j = i+hqrnduniformi(&rs, npoints-i, _state);
swaprows(&xy, i, j, -1, _state);
xy.ptr.pp_double[i][2] = xy.ptr.pp_double[i][2]+ae_machineepsilon*hqrndnormal(&rs, _state);
}
spline2dbuildersetpoints(&state, &xy, npoints, _state);
spline2dfit(&state, &s2, &rep2, _state);
mx = (double)(0);
maxerror = (double)(0);
for(i=0; i<=npoints-1; i++)
{
v0 = (kx-1)*hqrnduniformr(&rs, _state);
v1 = (ky-1)*hqrnduniformr(&rs, _state);
maxerror = ae_maxreal(maxerror, ae_fabs(spline2dcalc(&s, v0, v1, _state)-spline2dcalc(&s2, v0, v1, _state), _state), _state);
mx = ae_maxreal(mx, ae_fabs(spline2dcalc(&s, v0, v1, _state), _state), _state);
}
ae_set_error_flag(errorflag, ae_fp_greater(maxerror/mx,1.0E-12), __FILE__, __LINE__, "testspline2dunit.ap:1846");
ae_frame_leave(_state);
}
/*************************************************************************
Block solver test for fitting functionality
*************************************************************************/
static void testspline2dunit_testfittingfastddmsolver(ae_bool* errorflag,
ae_state *_state)
{
ae_frame _frame_block;
hqrndstate rs;
ae_int_t pass;
ae_int_t tilesize;
ae_int_t interfacesize;
ae_int_t npoints;
ae_int_t d;
ae_int_t kx;
ae_int_t ky;
ae_int_t kxcur;
ae_int_t kycur;
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v0;
double v1;
double vx;
double vy;
double f0;
double f1;
double f2;
double f3;
double h;
double smax;
double ernd;
double ept;
double emax;
double eavg;
double vmax;
ae_int_t padding;
ae_int_t nlayers;
ae_matrix xy;
ae_matrix xy1;
spline2dbuilder state;
spline2dinterpolant sa0;
spline2dinterpolant sa1;
spline2dinterpolant s1;
spline2dinterpolant s2;
spline2dfitreport rep0;
spline2dfitreport rep1;
spline2dfitreport rep2;
ae_vector meany;
ae_vector lambdaa;
ae_vector penaltya;
ae_vector rmsa;
double rmserror;
double avgerror;
double maxerror;
double rss;
double tss;
double r2;
double v;
ae_frame_make(_state, &_frame_block);
memset(&rs, 0, sizeof(rs));
memset(&xy, 0, sizeof(xy));
memset(&xy1, 0, sizeof(xy1));
memset(&state, 0, sizeof(state));
memset(&sa0, 0, sizeof(sa0));
memset(&sa1, 0, sizeof(sa1));
memset(&s1, 0, sizeof(s1));
memset(&s2, 0, sizeof(s2));
memset(&rep0, 0, sizeof(rep0));
memset(&rep1, 0, sizeof(rep1));
memset(&rep2, 0, sizeof(rep2));
memset(&meany, 0, sizeof(meany));
memset(&lambdaa, 0, sizeof(lambdaa));
memset(&penaltya, 0, sizeof(penaltya));
memset(&rmsa, 0, sizeof(rmsa));
_hqrndstate_init(&rs, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy1, 0, 0, DT_REAL, _state, ae_true);
_spline2dbuilder_init(&state, _state, ae_true);
_spline2dinterpolant_init(&sa0, _state, ae_true);
_spline2dinterpolant_init(&sa1, _state, ae_true);
_spline2dinterpolant_init(&s1, _state, ae_true);
_spline2dinterpolant_init(&s2, _state, ae_true);
_spline2dfitreport_init(&rep0, _state, ae_true);
_spline2dfitreport_init(&rep1, _state, ae_true);
_spline2dfitreport_init(&rep2, _state, ae_true);
ae_vector_init(&meany, 0, DT_REAL, _state, ae_true);
ae_vector_init(&lambdaa, 0, DT_REAL, _state, ae_true);
ae_vector_init(&penaltya, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rmsa, 0, DT_REAL, _state, ae_true);
hqrndrandomize(&rs, _state);
/*
* Basic test:
* * small grid whose size is TileSize+1 or less
* * random dataset
* * compared with single run of naiveLLS
* * we also test correctness of report fields
*/
for(pass=1; pass<=3; pass++)
{
for(d=1; d<=3; d++)
{
tilesize = 8+hqrnduniformi(&rs, 8, _state);
kx = ae_maxint(1+hqrnduniformi(&rs, tilesize+1, _state), 4, _state);
ky = ae_maxint(1+hqrnduniformi(&rs, tilesize+1, _state), 4, _state);
npoints = 10*kx*ky;
ae_matrix_set_length(&xy, npoints, 2+d, _state);
ae_vector_set_length(&meany, d, _state);
for(j=0; j<=d-1; j++)
{
meany.ptr.p_double[j] = (double)(0);
}
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state);
xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state);
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state);
meany.ptr.p_double[j] = meany.ptr.p_double[j]+xy.ptr.pp_double[i][2+j]/npoints;
}
}
/*
* Create solver, set grid, area and other properties.
* Fit with NaiveLLS first.
*/
spline2dbuildercreate(d, &state, _state);
spline2dbuildersetarea(&state, 0.0, 1.0, 0.0, 1.0, _state);
state.maxcoresize = tilesize;
state.adddegreeoffreedom = ae_false;
spline2dbuildersetalgonaivells(&state, 0.0, _state);
spline2dbuildersetpoints(&state, &xy, npoints, _state);
spline2dbuildersetgrid(&state, kx, ky, _state);
spline2dfit(&state, &sa0, &rep0, _state);
/*
* Fit with FastDDM solver with NLayers in [-2,+2]
*/
spline2dbuildersetpoints(&state, &xy, npoints, _state);
spline2dbuildersetgrid(&state, kx, ky, _state);
spline2dbuildersetalgofastddm(&state, hqrnduniformi(&rs, 5, _state)-2, 0.0, _state);
spline2dfit(&state, &s1, &rep1, _state);
/*
* Compare at random locations
*/
smax = 0.0;
ernd = 0.0;
for(k=0; k<=20*kx*ky-1; k++)
{
vx = hqrnduniformr(&rs, _state);
vy = hqrnduniformr(&rs, _state);
for(j=0; j<=d-1; j++)
{
v0 = spline2dcalcvi(&sa0, vx, vy, j, _state);
v1 = spline2dcalcvi(&s1, vx, vy, j, _state);
smax = ae_maxreal(smax, ae_fabs(v0, _state), _state);
ernd = ae_maxreal(ernd, ae_fabs(v0-v1, _state), _state);
}
}
ae_set_error_flag(errorflag, ae_fp_greater(ernd/smax,0.001), __FILE__, __LINE__, "testspline2dunit.ap:1964");
/*
* Test report fields
*/
rmserror = (double)(0);
avgerror = (double)(0);
maxerror = (double)(0);
rss = 0.0;
tss = 0.0;
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=d-1; j++)
{
v = xy.ptr.pp_double[i][2+j]-spline2dcalcvi(&s1, xy.ptr.pp_double[i][0], xy.ptr.pp_double[i][1], j, _state);
rss = rss+v*v;
tss = tss+ae_sqr(xy.ptr.pp_double[i][2+j]-meany.ptr.p_double[j], _state);
rmserror = rmserror+ae_sqr(v, _state);
avgerror = avgerror+ae_fabs(v, _state)/(npoints*d);
maxerror = ae_maxreal(maxerror, ae_fabs(v, _state), _state);
}
}
rmserror = ae_sqrt(rmserror/(npoints*d), _state);
r2 = 1.0-rss/coalesce(tss, (double)(1), _state);
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(rmserror-rep1.rmserror, _state),1.0E-6), __FILE__, __LINE__, "testspline2dunit.ap:1988");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(avgerror-rep1.avgerror, _state),1.0E-6), __FILE__, __LINE__, "testspline2dunit.ap:1989");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(maxerror-rep1.maxerror, _state),1.0E-6), __FILE__, __LINE__, "testspline2dunit.ap:1990");
if( ae_fp_greater(tss,1.0E-3) )
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(r2-rep1.r2, _state),1.0E-6), __FILE__, __LINE__, "testspline2dunit.ap:1992");
}
}
}
/*
* Basic test: two-layer task; "reference" model is built by
* subsequent fitting of two "traditional" splines; test model
* is built by FastDDM algorithm.
*/
tilesize = 15;
for(d=1; d<=2; d++)
{
/*
* Generate dataset
*/
kx = 2*tilesize+1;
ky = 2*tilesize+1;
npoints = kx*ky;
ae_matrix_set_length(&xy, npoints, 2+d, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = boundval(i%kx+0.05*hqrndnormal(&rs, _state), (double)(0), (double)(kx-1), _state);
xy.ptr.pp_double[i][1] = boundval(i/kx+0.05*hqrndnormal(&rs, _state), (double)(0), (double)(ky-1), _state);
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state);
}
}
/*
* Create solver, set grid, area and other properties
*/
spline2dbuildercreate(d, &state, _state);
spline2dbuildersetarea(&state, (double)(0), (double)(kx-1), (double)(0), (double)(ky-1), _state);
state.maxcoresize = tilesize;
/*
* Fit with BlockLLS solver
*/
state.adddegreeoffreedom = ae_false;
spline2dbuildersetalgoblocklls(&state, 0.0, _state);
spline2dbuildersetpoints(&state, &xy, npoints, _state);
spline2dbuildersetgrid(&state, (kx-1)/2+1, (ky-1)/2+1, _state);
spline2dfit(&state, &sa0, &rep0, _state);
ae_matrix_set_length(&xy1, npoints, 2+d, _state);
for(i=0; i<=npoints-1; i++)
{
xy1.ptr.pp_double[i][0] = xy.ptr.pp_double[i][0];
xy1.ptr.pp_double[i][1] = xy.ptr.pp_double[i][1];
for(j=0; j<=d-1; j++)
{
xy1.ptr.pp_double[i][2+j] = xy.ptr.pp_double[i][2+j]-spline2dcalcvi(&sa0, xy.ptr.pp_double[i][0], xy.ptr.pp_double[i][1], j, _state);
}
}
spline2dbuildersetpoints(&state, &xy1, npoints, _state);
spline2dbuildersetgrid(&state, kx, ky, _state);
spline2dfit(&state, &sa1, &rep0, _state);
/*
* Fit with another solver
*/
spline2dbuildersetpoints(&state, &xy, npoints, _state);
spline2dbuildersetgrid(&state, kx, ky, _state);
spline2dbuildersetalgofastddm(&state, 0, 0.0, _state);
spline2dfit(&state, &s1, &rep1, _state);
/*
* Compare
*/
padding = 0;
smax = 0.0;
ernd = 0.0;
for(k=0; k<=20*kx*ky-1; k++)
{
vx = (kx-1-2*padding)*hqrnduniformr(&rs, _state)+padding;
vy = (ky-1-2*padding)*hqrnduniformr(&rs, _state)+padding;
for(j=0; j<=d-1; j++)
{
v0 = spline2dcalcvi(&sa0, vx, vy, j, _state)+spline2dcalcvi(&sa1, vx, vy, j, _state);
v1 = spline2dcalcvi(&s1, vx, vy, j, _state);
smax = ae_maxreal(smax, ae_fabs(v0, _state), _state);
ernd = ae_maxreal(ernd, ae_fabs(v0-v1, _state), _state);
}
}
ae_set_error_flag(errorflag, ae_fp_greater(ernd/smax,0.010), __FILE__, __LINE__, "testspline2dunit.ap:2071");
ept = 0.0;
for(i=0; i<=npoints-1; i++)
{
vx = xy.ptr.pp_double[i][0];
vy = xy.ptr.pp_double[i][1];
for(j=0; j<=d-1; j++)
{
v0 = spline2dcalcvi(&sa0, vx, vy, j, _state)+spline2dcalcvi(&sa1, vx, vy, j, _state);
v1 = spline2dcalcvi(&s1, vx, vy, j, _state);
smax = ae_maxreal(smax, ae_fabs(v0, _state), _state);
ept = ae_maxreal(ept, ae_fabs(v0-v1, _state), _state);
}
}
ae_set_error_flag(errorflag, ae_fp_greater(ept/smax,0.001), __FILE__, __LINE__, "testspline2dunit.ap:2085");
}
/*
* Test correctness of error reporting in multilevel setting:
* * grid whose size is larger than TileSize+1
* * random dataset
* * we just test correctness of report fields
*/
for(pass=1; pass<=2; pass++)
{
for(d=1; d<=2; d++)
{
tilesize = 5+hqrnduniformi(&rs, 3, _state);
kx = ae_maxint(1+hqrnduniformi(&rs, 5*tilesize+1, _state), 4, _state);
ky = ae_maxint(1+hqrnduniformi(&rs, 5*tilesize+1, _state), 4, _state);
npoints = 10*kx*ky;
ae_matrix_set_length(&xy, npoints, 2+d, _state);
ae_vector_set_length(&meany, d, _state);
for(j=0; j<=d-1; j++)
{
meany.ptr.p_double[j] = (double)(0);
}
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state);
xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state);
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state);
meany.ptr.p_double[j] = meany.ptr.p_double[j]+xy.ptr.pp_double[i][2+j]/npoints;
}
}
/*
* Create solver, set grid, area and other properties.
* Fit with FastDDM solver
*/
spline2dbuildercreate(d, &state, _state);
spline2dbuildersetarea(&state, 0.0, 1.0, 0.0, 1.0, _state);
state.maxcoresize = tilesize;
spline2dbuildersetpoints(&state, &xy, npoints, _state);
spline2dbuildersetgrid(&state, kx, ky, _state);
spline2dbuildersetalgofastddm(&state, hqrnduniformi(&rs, 5, _state)-2, 0.0, _state);
spline2dfit(&state, &s1, &rep1, _state);
/*
* Test report fields
*/
rmserror = (double)(0);
avgerror = (double)(0);
maxerror = (double)(0);
rss = 0.0;
tss = 0.0;
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=d-1; j++)
{
v = xy.ptr.pp_double[i][2+j]-spline2dcalcvi(&s1, xy.ptr.pp_double[i][0], xy.ptr.pp_double[i][1], j, _state);
rss = rss+v*v;
tss = tss+ae_sqr(xy.ptr.pp_double[i][2+j]-meany.ptr.p_double[j], _state);
rmserror = rmserror+ae_sqr(v, _state);
avgerror = avgerror+ae_fabs(v, _state)/(npoints*d);
maxerror = ae_maxreal(maxerror, ae_fabs(v, _state), _state);
}
}
rmserror = ae_sqrt(rmserror/(npoints*d), _state);
r2 = 1.0-rss/coalesce(tss, (double)(1), _state);
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(rmserror-rep1.rmserror, _state),1.0E-6), __FILE__, __LINE__, "testspline2dunit.ap:2152");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(avgerror-rep1.avgerror, _state),1.0E-6), __FILE__, __LINE__, "testspline2dunit.ap:2153");
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(maxerror-rep1.maxerror, _state),1.0E-6), __FILE__, __LINE__, "testspline2dunit.ap:2154");
if( ae_fp_greater(tss,1.0E-3) )
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(r2-rep1.r2, _state),1.0E-6), __FILE__, __LINE__, "testspline2dunit.ap:2156");
}
}
}
/*
* Test correctness of handling NLayers>0, NLayers=0 and NLayers<0.
*
* NOTE: we use reduced tile size and interface size, because we do
* not test model quality, just identity with NLayers<=0
*/
d = 1;
tilesize = 5;
interfacesize = 2;
kx = 1+4*(tilesize-hqrnduniformi(&rs, 2, _state));
ky = 1+4*(tilesize-hqrnduniformi(&rs, 2, _state));
nlayers = 3;
npoints = kx*ky;
ae_matrix_set_length(&xy, npoints, 2+d, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state);
xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state);
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state);
}
}
/*
* Create solver, set grid, area and other properties.
*/
spline2dbuildercreate(d, &state, _state);
spline2dbuildersetarea(&state, 0.0, 1.0, 0.0, 1.0, _state);
state.maxcoresize = tilesize;
state.interfacesize = interfacesize;
spline2dbuildersetpoints(&state, &xy, npoints, _state);
spline2dbuildersetgrid(&state, kx, ky, _state);
/*
* Try different NLayers>0, compare with corresponding non-positive values
*/
for(k=1; k<=nlayers+1; k++)
{
spline2dbuildersetalgofastddm(&state, k, 0.0, _state);
spline2dfit(&state, &s1, &rep1, _state);
spline2dbuildersetalgofastddm(&state, imin2(k-nlayers, 0, _state), 0.0, _state);
spline2dfit(&state, &s2, &rep2, _state);
/*
* Test report fields
*/
vmax = (double)(0);
for(i=0; i<=10; i++)
{
vx = hqrnduniformr(&rs, _state);
vy = hqrnduniformr(&rs, _state);
vmax = ae_maxreal(vmax, ae_fabs(spline2dcalc(&s1, vx, vy, _state)-spline2dcalc(&s2, vx, vy, _state), _state), _state);
}
ae_set_error_flag(errorflag, ae_fp_greater(vmax,1.0E-12), __FILE__, __LINE__, "testspline2dunit.ap:2212");
}
/*
* Ability to reproduce target function in multilayer setup:
* * small tile size
* * nearly regular KX*KY dataset, for random KX>TileSize, KY>TileSize
* * (2*KX)x(2*KY) grid, flexible enough
*
* We check that maximum and average errors at nodes are small
*/
vmax = 0.0;
for(pass=1; pass<=10; pass++)
{
d = 1;
tilesize = 5+hqrnduniformi(&rs, 4, _state);
kx = 4+hqrnduniformi(&rs, 4*tilesize+1, _state);
ky = 4+hqrnduniformi(&rs, 4*tilesize+1, _state);
npoints = kx*ky;
ae_matrix_set_length(&xy, npoints, 2+d, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = boundval(i%kx+0.05*hqrndnormal(&rs, _state), (double)(0), (double)(kx-1), _state);
xy.ptr.pp_double[i][1] = boundval(i/kx+0.05*hqrndnormal(&rs, _state), (double)(0), (double)(ky-1), _state);
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state);
}
}
/*
* Create solver, set grid, area and other properties.
*/
spline2dbuildercreate(d, &state, _state);
state.maxcoresize = tilesize;
spline2dbuildersetpoints(&state, &xy, npoints, _state);
spline2dbuildersetgrid(&state, ae_round(2.0*kx, _state), ae_round(2.0*ky, _state), _state);
spline2dbuildersetarea(&state, 0.0, (double)(kx-1), 0.0, (double)(ky-1), _state);
spline2dbuildersetalgofastddm(&state, 0, 0.0, _state);
spline2dfit(&state, &s1, &rep1, _state);
/*
* Compare
*/
emax = 0.0;
eavg = 0.0;
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=d-1; j++)
{
v = ae_fabs(spline2dcalcvi(&s1, xy.ptr.pp_double[i][0], xy.ptr.pp_double[i][1], j, _state)-xy.ptr.pp_double[i][2+j], _state);
emax = ae_maxreal(emax, v, _state);
eavg = eavg+v/(npoints*d);
}
}
ae_set_error_flag(errorflag, ae_fp_greater(emax,0.00100), __FILE__, __LINE__, "testspline2dunit.ap:2265");
ae_set_error_flag(errorflag, ae_fp_greater(eavg,0.00010), __FILE__, __LINE__, "testspline2dunit.ap:2266");
vmax = ae_maxreal(vmax, ae_fabs(emax, _state), _state);
}
/*
* Test that increasing LambdaV results in decrease of S'' integral;
* although (unlike BlockLLS) FastDDM does NOT minimize S'' explicitly,
* it shows similar behavior with respect to regularization, so we can
* expect that penalty decreases.
*
* NOTE: we use ultra-small values of tile size and interface size because
* precision is not important here.
*/
for(pass=0; pass<=2; pass++)
{
d = 1;
tilesize = 5;
kx = 1+4*(tilesize-hqrnduniformi(&rs, 2, _state));
ky = 1+4*(tilesize-hqrnduniformi(&rs, 2, _state));
npoints = -1;
vx = (double)(0);
vy = (double)(0);
if( pass==0 )
{
npoints = 1+ae_round(0.5*kx*ky, _state);
ae_matrix_set_length(&xy, npoints, 2+d, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state);
xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state);
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state);
}
}
vx = (double)1/(double)(kx-1);
vy = (double)1/(double)(ky-1);
}
if( pass==1 )
{
npoints = kx*ky;
ae_matrix_set_length(&xy, npoints, 2+d, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = boundval(i%kx+0.05*hqrndnormal(&rs, _state), (double)(0), (double)(kx-1), _state);
xy.ptr.pp_double[i][1] = boundval(i/kx+0.05*hqrndnormal(&rs, _state), (double)(0), (double)(ky-1), _state);
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state);
}
}
vx = (double)(1);
vy = (double)(1);
}
if( pass==2 )
{
npoints = 1+ae_round(3.0*kx*ky, _state);
ae_matrix_set_length(&xy, npoints, 2+d, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state);
xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state);
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state);
}
}
vx = (double)1/(double)(kx-1);
vy = (double)1/(double)(ky-1);
}
ae_assert(ae_fp_greater(vx,(double)(0)), "Spline2D: unit test failed integrity check", _state);
ae_assert(ae_fp_greater(vy,(double)(0)), "Spline2D: unit test failed integrity check", _state);
/*
* Create solver, set grid, area and other properties.
*/
spline2dbuildercreate(d, &state, _state);
spline2dbuildersetarea(&state, (double)(0), (double)(kx-1), (double)(0), (double)(ky-1), _state);
state.maxcoresize = tilesize;
spline2dbuildersetpoints(&state, &xy, npoints, _state);
spline2dbuildersetgrid(&state, kx, ky, _state);
/*
* Try different values of LambdaV, calculate penalty
*/
ae_vector_set_length(&lambdaa, 4, _state);
lambdaa.ptr.p_double[0] = 0.0;
lambdaa.ptr.p_double[1] = 1.0E-1;
lambdaa.ptr.p_double[2] = 1.0E+1;
lambdaa.ptr.p_double[3] = 1.0E+2;
ae_vector_set_length(&penaltya, lambdaa.cnt, _state);
ae_vector_set_length(&rmsa, lambdaa.cnt, _state);
for(k=0; k<=lambdaa.cnt-1; k++)
{
spline2dbuildersetalgofastddm(&state, 0, lambdaa.ptr.p_double[k], _state);
spline2dfit(&state, &s1, &rep1, _state);
h = 1.0E-4;
v = 0.0;
for(i=0; i<=kx-1; i++)
{
for(j=0; j<=ky-1; j++)
{
v0 = i*vx;
v1 = j*vy;
f0 = spline2dcalc(&s1, v0-h, v1, _state);
f1 = spline2dcalc(&s1, v0, v1, _state);
f2 = spline2dcalc(&s1, v0+h, v1, _state);
v = v+ae_sqr((f0+f2-2*f1)/ae_sqr(h, _state), _state);
f0 = spline2dcalc(&s1, v0, v1-h, _state);
f1 = spline2dcalc(&s1, v0, v1, _state);
f2 = spline2dcalc(&s1, v0, v1+h, _state);
v = v+ae_sqr((f0+f2-2*f1)/ae_sqr(h, _state), _state);
f0 = spline2dcalc(&s1, v0-h, v1-h, _state);
f1 = spline2dcalc(&s1, v0+h, v1-h, _state);
f2 = spline2dcalc(&s1, v0-h, v1+h, _state);
f3 = spline2dcalc(&s1, v0+h, v1+h, _state);
v = v+2*ae_sqr((f3-f2-f1+f0)/ae_sqr(h, _state), _state);
}
}
penaltya.ptr.p_double[k] = v;
rmsa.ptr.p_double[k] = rep1.rmserror;
}
for(k=0; k<=lambdaa.cnt-2; k++)
{
ae_set_error_flag(errorflag, ae_fp_less(penaltya.ptr.p_double[k],penaltya.ptr.p_double[k+1]), __FILE__, __LINE__, "testspline2dunit.ap:2387");
}
}
/*
* Test that refining grid in "K:=2*K-1" fashion results in
* decrease of RMS error; although it seems quite silly test,
* in fact it checks various failures in the algorithm.
*
* NOTE: we set high penalty coefficient in order to avoid nearly
* precise fits (such fits are hard to test reliably)
*
* NOTE: we use ultra-small values of tile size and interface size because
* precision is not important here.
*/
for(pass=0; pass<=2; pass++)
{
d = 1;
tilesize = 5;
kx = 1+4*tilesize;
ky = 1+4*tilesize;
nlayers = 3;
npoints = -1;
if( pass==0 )
{
npoints = 1+ae_round(0.1*kx*ky, _state);
ae_matrix_set_length(&xy, npoints, 2+d, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state);
xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state);
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state);
}
}
vx = (double)1/(double)(kx-1);
vy = (double)1/(double)(ky-1);
}
if( pass==1 )
{
npoints = kx*ky;
ae_matrix_set_length(&xy, npoints, 2+d, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = boundval(i%kx+0.05*hqrndnormal(&rs, _state), (double)(0), (double)(kx-1), _state);
xy.ptr.pp_double[i][1] = boundval(i/kx+0.05*hqrndnormal(&rs, _state), (double)(0), (double)(ky-1), _state);
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state);
}
}
vx = (double)(1);
vy = (double)(1);
}
if( pass==2 )
{
npoints = 1+ae_round(2.0*kx*ky, _state);
ae_matrix_set_length(&xy, npoints, 2+d, _state);
for(i=0; i<=npoints-1; i++)
{
xy.ptr.pp_double[i][0] = hqrnduniformr(&rs, _state);
xy.ptr.pp_double[i][1] = hqrnduniformr(&rs, _state);
for(j=0; j<=d-1; j++)
{
xy.ptr.pp_double[i][2+j] = hqrndnormal(&rs, _state);
}
}
vx = (double)1/(double)(kx-1);
vy = (double)1/(double)(ky-1);
}
/*
* Create solver, set grid, area and other properties.
*/
spline2dbuildercreate(d, &state, _state);
spline2dbuildersetarea(&state, (double)(0), (double)(kx-1), (double)(0), (double)(ky-1), _state);
state.maxcoresize = tilesize;
spline2dbuildersetpoints(&state, &xy, npoints, _state);
/*
* Try different values of LambdaV, calculate penalty
*/
ae_vector_set_length(&rmsa, nlayers, _state);
kxcur = tilesize+1;
kycur = tilesize+1;
for(k=0; k<=rmsa.cnt-1; k++)
{
spline2dbuildersetgrid(&state, kxcur, kycur, _state);
spline2dbuildersetalgofastddm(&state, 0, 0.0, _state);
spline2dfit(&state, &s1, &rep1, _state);
rmsa.ptr.p_double[k] = rep1.rmserror;
kxcur = 2*kxcur-1;
kycur = 2*kycur-1;
}
for(k=0; k<=rmsa.cnt-2; k++)
{
ae_set_error_flag(errorflag, ae_fp_less_eq(rmsa.ptr.p_double[k],rmsa.ptr.p_double[k+1]), __FILE__, __LINE__, "testspline2dunit.ap:2479");
}
}
ae_frame_leave(_state);
}
static double testrbfunit_tol = 1.0E-10;
static ae_int_t testrbfunit_mxits = 0;
static double testrbfunit_heps = 1.0E-12;
static ae_bool testrbfunit_specialtest(ae_state *_state);
static ae_bool testrbfunit_basicrbftest(ae_state *_state);
static ae_bool testrbfunit_irregularrbftest(ae_state *_state);
static ae_bool testrbfunit_linearitymodelrbftest(ae_state *_state);
static ae_bool testrbfunit_serializationtest(ae_state *_state);
static ae_bool testrbfunit_searcherr(/* Real */ ae_matrix* y0,
/* Real */ ae_matrix* y1,
ae_int_t n,
ae_int_t ny,
ae_int_t errtype,
/* Real */ ae_vector* b1,
/* Real */ ae_vector* delta,
ae_state *_state);
static ae_bool testrbfunit_basicmultilayerrbftest(ae_state *_state);
static void testrbfunit_gridcalc23test(ae_bool* errorflag,
ae_state *_state);
static ae_bool testrbfunit_basichrbftest(ae_state *_state);
static ae_bool testrbfunit_scaledhrbftest(ae_state *_state);
static ae_bool testrbfunit_spechrbftest(ae_state *_state);
static ae_bool testrbfunit_gridhrbftest(ae_state *_state);
ae_bool testrbf(ae_bool silent, ae_state *_state)
{
ae_bool specialerrors;
ae_bool basicrbferrors;
ae_bool irregularrbferrors;
ae_bool linearitymodelrbferr;
ae_bool sqrdegmatrixrbferr;
ae_bool sererrors;
ae_bool multilayerrbf1derrors;
ae_bool multilayerrbferrors;
ae_bool gridcalc23errors;
ae_bool hrbfbasicerrors;
ae_bool hrbfscaleerrors;
ae_bool hrbfspecerrors;
ae_bool hrbfgriderrors;
ae_bool hrbferrors;
ae_bool waserrors;
ae_bool result;
/*
* HRBF tests
*/
hrbfbasicerrors = testrbfunit_basichrbftest(_state);
hrbfspecerrors = testrbfunit_spechrbftest(_state);
hrbfscaleerrors = testrbfunit_scaledhrbftest(_state);
hrbfgriderrors = testrbfunit_gridhrbftest(_state);
hrbferrors = ((hrbfbasicerrors||hrbfspecerrors)||hrbfscaleerrors)||hrbfgriderrors;
/*
* Other tests
*/
specialerrors = testrbfunit_specialtest(_state);
basicrbferrors = testrbfunit_basicrbftest(_state);
irregularrbferrors = testrbfunit_irregularrbftest(_state);
linearitymodelrbferr = testrbfunit_linearitymodelrbftest(_state);
sqrdegmatrixrbferr = sqrdegmatrixrbftest(ae_true, _state);
multilayerrbf1derrors = ae_false;
multilayerrbferrors = testrbfunit_basicmultilayerrbftest(_state);
sererrors = testrbfunit_serializationtest(_state);
gridcalc23errors = ae_false;
testrbfunit_gridcalc23test(&gridcalc23errors, _state);
/*
* report
*/
waserrors = ((((((((specialerrors||basicrbferrors)||irregularrbferrors)||linearitymodelrbferr)||sqrdegmatrixrbferr)||sererrors)||multilayerrbf1derrors)||multilayerrbferrors)||gridcalc23errors)||hrbferrors;
if( !silent )
{
printf("TESTING RBF\n");
printf("GENERAL TESTS:\n");
printf("* serialization test: ");
if( sererrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* special properties: ");
if( specialerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("RBF-V2:\n");
printf("* basic HRBF test: ");
if( hrbfbasicerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* scale-related tests: ");
if( hrbfscaleerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* grid calculation tests: ");
if( hrbfgriderrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* special properties: ");
if( hrbfspecerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("RBF-V1:\n");
printf("* basicRBFTest: ");
if( basicrbferrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* irregularRBFTest: ");
if( irregularrbferrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* linearity test: ");
if( linearitymodelrbferr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* SqrDegMatrixRBFTest: ");
if( sqrdegmatrixrbferr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* MultiLayerRBFErrors in 1D test: ");
if( multilayerrbf1derrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* MultiLayerRBFErrors in 2-3D test: ");
if( multilayerrbferrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* GridCalc2/3V: ");
if( gridcalc23errors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
/*
* was errors?
*/
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
return result;
}
/*************************************************************************
The test has to check, that algorithm can solve problems of matrix are
degenerate.
* used model with linear term;
* points locate in a subspace of dimension less than an original space.
-- ALGLIB --
Copyright 13.12.2011 by Bochkanov Sergey
*************************************************************************/
ae_bool sqrdegmatrixrbftest(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
rbfmodel s;
rbfreport rep;
ae_int_t nx;
ae_int_t ny;
ae_int_t k0;
ae_int_t k1;
ae_int_t np;
double sx;
double sy;
double zx;
double px;
double zy;
double py;
double q;
double z;
ae_vector point;
ae_matrix a;
ae_vector d0;
ae_vector d1;
ae_int_t gen;
ae_vector pvd0;
ae_vector pvd1;
double pvdnorm;
double vnorm;
double dd0;
double dd1;
ae_matrix gp;
ae_vector x;
ae_vector y;
ae_int_t unx;
ae_int_t uny;
ae_matrix xwr;
ae_matrix v;
ae_int_t i;
ae_int_t j;
ae_int_t k;
double eps;
ae_int_t modelversion;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&point, 0, sizeof(point));
memset(&a, 0, sizeof(a));
memset(&d0, 0, sizeof(d0));
memset(&d1, 0, sizeof(d1));
memset(&pvd0, 0, sizeof(pvd0));
memset(&pvd1, 0, sizeof(pvd1));
memset(&gp, 0, sizeof(gp));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&xwr, 0, sizeof(xwr));
memset(&v, 0, sizeof(v));
_rbfmodel_init(&s, _state, ae_true);
_rbfreport_init(&rep, _state, ae_true);
ae_vector_init(&point, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&pvd0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&pvd1, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&gp, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xwr, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true);
zx = (double)(10);
px = (double)(15);
zy = (double)(10);
py = (double)(15);
eps = 1.0E-6;
ny = 1;
for(nx=2; nx<=3; nx++)
{
/*
* prepare test problem
*/
sx = ae_pow(zx, px*(ae_randominteger(3, _state)-1), _state);
sy = ae_pow(zy, py*(ae_randominteger(3, _state)-1), _state);
ae_vector_set_length(&x, nx, _state);
ae_vector_set_length(&y, ny, _state);
ae_vector_set_length(&point, nx, _state);
rbfcreate(nx, ny, &s, _state);
rbfsetcond(&s, testrbfunit_heps, testrbfunit_heps, testrbfunit_mxits, _state);
q = 0.25+ae_randomreal(_state);
z = 4.5+ae_randomreal(_state);
rbfsetalgoqnn(&s, q, z, _state);
/*
* start points for grid
*/
for(i=0; i<=nx-1; i++)
{
point.ptr.p_double[i] = sx*(2*ae_randomreal(_state)-1);
}
if( nx==2 )
{
for(k0=2; k0<=4; k0++)
{
rmatrixrndorthogonal(nx, &a, _state);
ae_vector_set_length(&d0, nx, _state);
ae_v_move(&d0.ptr.p_double[0], 1, &a.ptr.pp_double[0][0], a.stride, ae_v_len(0,nx-1));
np = k0;
ae_matrix_set_length(&gp, np, nx+ny, _state);
/*
* create grid
*/
for(i=0; i<=k0-1; i++)
{
gp.ptr.pp_double[i][0] = point.ptr.p_double[0]+sx*i*d0.ptr.p_double[0];
gp.ptr.pp_double[i][1] = point.ptr.p_double[1]+sx*i*d0.ptr.p_double[1];
for(k=0; k<=ny-1; k++)
{
gp.ptr.pp_double[i][nx+k] = sy*(2*ae_randomreal(_state)-1);
}
}
rbfsetpoints(&s, &gp, np, _state);
rbfbuildmodel(&s, &rep, _state);
for(i=0; i<=np-1; i++)
{
x.ptr.p_double[0] = gp.ptr.pp_double[i][0];
x.ptr.p_double[1] = gp.ptr.pp_double[i][1];
rbfcalc(&s, &x, &y, _state);
for(j=0; j<=ny-1; j++)
{
if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
}
if( nx==3 )
{
for(k0=2; k0<=4; k0++)
{
for(k1=2; k1<=4; k1++)
{
for(gen=1; gen<=2; gen++)
{
rmatrixrndorthogonal(nx, &a, _state);
ae_vector_set_length(&d0, nx, _state);
ae_v_move(&d0.ptr.p_double[0], 1, &a.ptr.pp_double[0][0], a.stride, ae_v_len(0,nx-1));
/*
* create grid
*/
np = -1;
if( gen==1 )
{
np = k0;
ae_matrix_set_length(&gp, np, nx+ny, _state);
for(i=0; i<=k0-1; i++)
{
gp.ptr.pp_double[i][0] = point.ptr.p_double[0]+sx*i*d0.ptr.p_double[0];
gp.ptr.pp_double[i][1] = point.ptr.p_double[1]+sx*i*d0.ptr.p_double[1];
gp.ptr.pp_double[i][2] = point.ptr.p_double[2]+sx*i*d0.ptr.p_double[2];
for(k=0; k<=ny-1; k++)
{
gp.ptr.pp_double[i][nx+k] = sy*(2*ae_randomreal(_state)-1);
}
}
}
if( gen==2 )
{
ae_vector_set_length(&d1, nx, _state);
ae_v_move(&d1.ptr.p_double[0], 1, &a.ptr.pp_double[0][1], a.stride, ae_v_len(0,nx-1));
np = k0*k1;
ae_matrix_set_length(&gp, np, nx+ny, _state);
for(i=0; i<=k0-1; i++)
{
for(j=0; j<=k1-1; j++)
{
gp.ptr.pp_double[i*k1+j][0] = sx*i*d0.ptr.p_double[0]+sx*j*d1.ptr.p_double[0];
gp.ptr.pp_double[i*k1+j][1] = sx*i*d0.ptr.p_double[1]+sx*j*d1.ptr.p_double[1];
gp.ptr.pp_double[i*k1+j][2] = sx*i*d0.ptr.p_double[2]+sx*j*d1.ptr.p_double[2];
for(k=0; k<=ny-1; k++)
{
gp.ptr.pp_double[i*k1+j][nx+k] = sy*(2*ae_randomreal(_state)-1);
}
}
}
}
ae_assert(np>=0, "rbf test: integrity error", _state);
rbfsetpoints(&s, &gp, np, _state);
rbfbuildmodel(&s, &rep, _state);
for(i=0; i<=np-1; i++)
{
x.ptr.p_double[0] = gp.ptr.pp_double[i][0];
x.ptr.p_double[1] = gp.ptr.pp_double[i][1];
x.ptr.p_double[2] = gp.ptr.pp_double[i][2];
rbfcalc(&s, &x, &y, _state);
for(j=0; j<=ny-1; j++)
{
if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
if( gen==2 )
{
rbfunpack(&s, &unx, &uny, &xwr, &np, &v, &modelversion, _state);
dd0 = (d0.ptr.p_double[0]*v.ptr.pp_double[0][0]+d0.ptr.p_double[1]*v.ptr.pp_double[0][1]+d0.ptr.p_double[2]*v.ptr.pp_double[0][2])/(d0.ptr.p_double[0]*d0.ptr.p_double[0]+d0.ptr.p_double[1]*d0.ptr.p_double[1]+d0.ptr.p_double[2]*d0.ptr.p_double[2]);
dd1 = (d1.ptr.p_double[0]*v.ptr.pp_double[0][0]+d1.ptr.p_double[1]*v.ptr.pp_double[0][1]+d1.ptr.p_double[2]*v.ptr.pp_double[0][2])/(d1.ptr.p_double[0]*d1.ptr.p_double[0]+d1.ptr.p_double[1]*d1.ptr.p_double[1]+d1.ptr.p_double[2]*d1.ptr.p_double[2]);
ae_vector_set_length(&pvd0, nx, _state);
ae_vector_set_length(&pvd1, nx, _state);
for(i=0; i<=nx-1; i++)
{
pvd0.ptr.p_double[i] = dd0*d0.ptr.p_double[i];
pvd1.ptr.p_double[i] = dd1*d1.ptr.p_double[i];
}
pvdnorm = ae_sqrt(ae_sqr(v.ptr.pp_double[0][0]-pvd0.ptr.p_double[0]-pvd1.ptr.p_double[0], _state)+ae_sqr(v.ptr.pp_double[0][1]-pvd0.ptr.p_double[1]-pvd1.ptr.p_double[1], _state)+ae_sqr(v.ptr.pp_double[0][2]-pvd0.ptr.p_double[2]-pvd1.ptr.p_double[2], _state), _state);
vnorm = ae_sqrt(ae_sqr(v.ptr.pp_double[0][0], _state)+ae_sqr(v.ptr.pp_double[0][1], _state)+ae_sqr(v.ptr.pp_double[0][2], _state), _state);
if( ae_fp_greater(pvdnorm,vnorm*testrbfunit_tol) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Function for testing basic functionality of RBF module on regular grids with
multi-layer algorithm in 1D.
-- ALGLIB --
Copyright 2.03.2012 by Bochkanov Sergey
*************************************************************************/
ae_bool basicmultilayerrbf1dtest(ae_state *_state)
{
ae_frame _frame_block;
rbfmodel s;
rbfreport rep;
ae_int_t nx;
ae_int_t ny;
ae_int_t linterm;
ae_int_t n;
double q;
double r;
ae_int_t errtype;
ae_vector delta;
ae_int_t nlayers;
double a;
double b;
double f1;
double f2;
ae_vector a1;
ae_vector b1;
ae_matrix gp;
ae_vector x;
ae_vector y;
ae_matrix mody0;
ae_matrix mody1;
ae_matrix gy;
ae_vector gpgx0;
ae_vector gpgx1;
ae_int_t pass;
ae_int_t passcount;
ae_int_t i;
ae_int_t j;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&delta, 0, sizeof(delta));
memset(&a1, 0, sizeof(a1));
memset(&b1, 0, sizeof(b1));
memset(&gp, 0, sizeof(gp));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&mody0, 0, sizeof(mody0));
memset(&mody1, 0, sizeof(mody1));
memset(&gy, 0, sizeof(gy));
memset(&gpgx0, 0, sizeof(gpgx0));
memset(&gpgx1, 0, sizeof(gpgx1));
_rbfmodel_init(&s, _state, ae_true);
_rbfreport_init(&rep, _state, ae_true);
ae_vector_init(&delta, 0, DT_REAL, _state, ae_true);
ae_vector_init(&a1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b1, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&gp, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&mody0, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&mody1, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&gy, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&gpgx0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&gpgx1, 0, DT_REAL, _state, ae_true);
a = 1.0;
b = (double)1/(double)9;
f1 = 1.0;
f2 = 10.0;
passcount = 5;
n = 100;
ae_vector_set_length(&gpgx0, n, _state);
ae_vector_set_length(&gpgx1, n, _state);
for(i=0; i<=n-1; i++)
{
gpgx0.ptr.p_double[i] = (double)i/(double)n;
gpgx1.ptr.p_double[i] = (double)(0);
}
r = (double)(1);
for(pass=0; pass<=passcount-1; pass++)
{
nx = ae_randominteger(2, _state)+2;
ny = ae_randominteger(3, _state)+1;
linterm = ae_randominteger(3, _state)+1;
ae_vector_set_length(&x, nx, _state);
ae_vector_set_length(&y, ny, _state);
ae_vector_set_length(&a1, ny, _state);
ae_vector_set_length(&b1, ny, _state);
ae_vector_set_length(&delta, ny, _state);
ae_matrix_set_length(&mody0, n, ny, _state);
ae_matrix_set_length(&mody1, n, ny, _state);
for(i=0; i<=ny-1; i++)
{
a1.ptr.p_double[i] = a+0.01*a*(2*ae_randomreal(_state)-1);
b1.ptr.p_double[i] = b+0.01*b*(2*ae_randomreal(_state)-1);
delta.ptr.p_double[i] = 0.35*b1.ptr.p_double[i];
}
ae_matrix_set_length(&gp, n, nx+ny, _state);
/*
* create grid
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=nx-1; j++)
{
gp.ptr.pp_double[i][j] = (double)(0);
}
gp.ptr.pp_double[i][0] = (double)i/(double)n;
for(j=0; j<=ny-1; j++)
{
gp.ptr.pp_double[i][nx+j] = a1.ptr.p_double[j]*ae_cos(f1*2*ae_pi*gp.ptr.pp_double[i][0], _state)+b1.ptr.p_double[j]*ae_cos(f2*2*ae_pi*gp.ptr.pp_double[i][0], _state);
mody0.ptr.pp_double[i][j] = gp.ptr.pp_double[i][nx+j];
}
}
q = (double)(1);
nlayers = 1;
errtype = 1;
/*
* test multilayer algorithm with different parameters
*/
while(ae_fp_greater_eq(q,1/(2*f2)))
{
rbfcreate(nx, ny, &s, _state);
rbfsetalgomultilayer(&s, r, nlayers, 0.0, _state);
if( linterm==1 )
{
rbfsetlinterm(&s, _state);
}
if( linterm==2 )
{
rbfsetconstterm(&s, _state);
}
if( linterm==3 )
{
rbfsetzeroterm(&s, _state);
}
rbfsetpoints(&s, &gp, n, _state);
rbfbuildmodel(&s, &rep, _state);
if( ny==1 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=nx-1; j++)
{
x.ptr.p_double[j] = gp.ptr.pp_double[i][j];
}
if( nx==2 )
{
mody1.ptr.pp_double[i][0] = rbfcalc2(&s, x.ptr.p_double[0], x.ptr.p_double[1], _state);
}
else
{
if( nx==3 )
{
mody1.ptr.pp_double[i][0] = rbfcalc3(&s, x.ptr.p_double[0], x.ptr.p_double[1], x.ptr.p_double[2], _state);
}
else
{
ae_assert(ae_false, "BasicMultiLayerRBFTest1D: Invalid variable NX(NX neither 2 nor 3)", _state);
}
}
}
if( testrbfunit_searcherr(&mody0, &mody1, n, ny, errtype, &b1, &delta, _state) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
if( nx==2 )
{
rbfgridcalc2(&s, &gpgx0, n, &gpgx1, n, &gy, _state);
for(i=0; i<=n-1; i++)
{
mody1.ptr.pp_double[i][0] = gy.ptr.pp_double[i][0];
}
}
if( testrbfunit_searcherr(&mody0, &mody1, n, ny, errtype, &b1, &delta, _state) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=nx-1; j++)
{
x.ptr.p_double[j] = gp.ptr.pp_double[i][j];
}
rbfcalc(&s, &x, &y, _state);
for(j=0; j<=ny-1; j++)
{
mody1.ptr.pp_double[i][j] = y.ptr.p_double[j];
}
}
if( testrbfunit_searcherr(&mody0, &mody1, n, ny, errtype, &b1, &delta, _state) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=nx-1; j++)
{
x.ptr.p_double[j] = gp.ptr.pp_double[i][j];
}
rbfcalcbuf(&s, &x, &y, _state);
for(j=0; j<=ny-1; j++)
{
mody1.ptr.pp_double[i][j] = y.ptr.p_double[j];
}
}
if( testrbfunit_searcherr(&mody0, &mody1, n, ny, errtype, &b1, &delta, _state) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
q = q/2;
nlayers = nlayers+1;
if( errtype==1&&ae_fp_less_eq(q,1/f2) )
{
errtype = 2;
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function tests special cases:
* uninitialized RBF model will correctly return zero values
* RBF correctly handles 1 or 2 distinct points
* when we have many uniformly spaced points and one outlier, filter which
is applied to radii, makes all radii equal (RBF-QNN).
* RBF-ML with NLayers=0 gives linear model
* Hierarchical RBF with NLayers=0 gives linear model
-- ALGLIB --
Copyright 13.12.2011 by Bochkanov Sergey
*************************************************************************/
static ae_bool testrbfunit_specialtest(ae_state *_state)
{
ae_frame _frame_block;
rbfmodel s;
rbfreport rep;
ae_int_t n;
ae_int_t nx;
ae_int_t ny;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t t;
ae_matrix xy;
ae_matrix vf;
ae_vector x;
ae_vector y;
ae_int_t termtype;
double errtol;
ae_int_t tmpnx;
ae_int_t tmpny;
ae_int_t tmpnc;
ae_matrix xwr;
ae_matrix v;
double sx;
double z;
double va;
double vb;
double vc;
double vd;
ae_int_t modelversion;
double vv;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&xy, 0, sizeof(xy));
memset(&vf, 0, sizeof(vf));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&xwr, 0, sizeof(xwr));
memset(&v, 0, sizeof(v));
_rbfmodel_init(&s, _state, ae_true);
_rbfreport_init(&rep, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&vf, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xwr, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true);
errtol = 1.0E-9;
result = ae_false;
/*
* Create model in the default state (no parameters/points specified).
* With probability 0.5 we do one of the following:
* * test that default state of the model is a zero model (all Calc()
* functions return zero)
* * call RBFBuildModel() (without specifying anything) and test that
* all Calc() functions return zero.
*
* NOTE: because NX varies between 1 and 4, both V1 (old) and V2 RBFs
* are tested.
*/
for(nx=1; nx<=4; nx++)
{
for(ny=1; ny<=3; ny++)
{
rbfcreate(nx, ny, &s, _state);
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
rbfbuildmodel(&s, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:202");
ae_frame_leave(_state);
return result;
}
}
ae_vector_set_length(&x, nx, _state);
ae_vector_set_length(&y, 1, _state);
for(i=0; i<=nx-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
rbfcalc(&s, &x, &y, _state);
if( y.cnt!=ny )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:213");
ae_frame_leave(_state);
return result;
}
for(i=0; i<=ny-1; i++)
{
if( ae_fp_neq(y.ptr.p_double[i],(double)(0)) )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:219");
ae_frame_leave(_state);
return result;
}
}
}
}
/*
* Create default model with 1 point and different types of linear term.
* Test algorithm on such dataset.
*
* NOTE: because NX varies between 1 and 4, both V1 (old) and V2 RBFs
* are tested.
*/
for(nx=1; nx<=4; nx++)
{
for(ny=1; ny<=3; ny++)
{
rbfcreate(nx, ny, &s, _state);
for(termtype=0; termtype<=1; termtype++)
{
if( termtype==0 )
{
rbfsetlinterm(&s, _state);
}
if( termtype==1 )
{
rbfsetconstterm(&s, _state);
}
ae_matrix_set_length(&xy, 1, nx+ny, _state);
for(i=0; i<=nx+ny-1; i++)
{
xy.ptr.pp_double[0][i] = 2*ae_randomreal(_state)-1;
}
rbfsetpoints(&s, &xy, 1, _state);
rbfbuildmodel(&s, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:248");
ae_frame_leave(_state);
return result;
}
/*
* First, test that model exactly reproduces our dataset in the specified point
*/
ae_vector_set_length(&x, nx, _state);
for(i=0; i<=nx-1; i++)
{
x.ptr.p_double[i] = xy.ptr.pp_double[0][i];
}
rbfcalc(&s, &x, &y, _state);
if( y.cnt!=ny )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:261");
ae_frame_leave(_state);
return result;
}
for(i=0; i<=ny-1; i++)
{
if( ae_fp_greater(ae_fabs(y.ptr.p_double[i]-xy.ptr.pp_double[0][nx+i], _state),errtol) )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:267");
ae_frame_leave(_state);
return result;
}
}
/*
* Second, test that model is constant
*/
for(i=0; i<=nx-1; i++)
{
x.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
rbfcalc(&s, &x, &y, _state);
if( y.cnt!=ny )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:279");
ae_frame_leave(_state);
return result;
}
for(i=0; i<=ny-1; i++)
{
if( ae_fp_greater(ae_fabs(y.ptr.p_double[i]-xy.ptr.pp_double[0][nx+i], _state),errtol) )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:285");
ae_frame_leave(_state);
return result;
}
}
}
}
}
/*
* Create model with 2 points and different types of linear term.
* Test algorithm on such dataset.
*/
for(nx=2; nx<=3; nx++)
{
for(ny=1; ny<=3; ny++)
{
rbfcreate(nx, ny, &s, _state);
for(termtype=0; termtype<=1; termtype++)
{
if( termtype==0 )
{
rbfsetlinterm(&s, _state);
}
if( termtype==1 )
{
rbfsetconstterm(&s, _state);
}
if( termtype==2 )
{
rbfsetzeroterm(&s, _state);
}
ae_matrix_set_length(&xy, 2, nx+ny, _state);
for(i=0; i<=nx+ny-1; i++)
{
xy.ptr.pp_double[0][i] = 2*ae_randomreal(_state)-1;
}
for(i=0; i<=nx+ny-1; i++)
{
xy.ptr.pp_double[1][i] = xy.ptr.pp_double[0][i]+1.0;
}
rbfsetpoints(&s, &xy, 2, _state);
rbfbuildmodel(&s, &rep, _state);
if( rep.terminationtype<=0 )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(j=0; j<=1; j++)
{
ae_vector_set_length(&x, nx, _state);
for(i=0; i<=nx-1; i++)
{
x.ptr.p_double[i] = xy.ptr.pp_double[j][i];
}
rbfcalc(&s, &x, &y, _state);
if( y.cnt!=ny )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=ny-1; i++)
{
if( ae_fp_greater(ae_fabs(y.ptr.p_double[i]-xy.ptr.pp_double[j][nx+i], _state),errtol) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
}
}
/*
* Generate a set of points (xi,yi) = (SX*i,0), and one
* outlier (x_far,y_far)=(-1000*SX,0).
*
* Radii filtering should place a bound on the radius of outlier.
*/
for(nx=2; nx<=3; nx++)
{
for(ny=1; ny<=3; ny++)
{
sx = ae_exp(-5+10*ae_randomreal(_state), _state);
rbfcreate(nx, ny, &s, _state);
ae_matrix_set_length(&xy, 20, nx+ny, _state);
for(i=0; i<=xy.rows-1; i++)
{
xy.ptr.pp_double[i][0] = sx*i;
for(j=1; j<=nx-1; j++)
{
xy.ptr.pp_double[i][j] = (double)(0);
}
for(j=0; j<=ny-1; j++)
{
xy.ptr.pp_double[i][nx+j] = ae_randomreal(_state);
}
}
xy.ptr.pp_double[xy.rows-1][0] = -1000*sx;
rbfsetpoints(&s, &xy, xy.rows, _state);
/*
* Try random Z from [1,5]
*/
z = 1+ae_randomreal(_state)*4;
rbfsetalgoqnn(&s, 1.0, z, _state);
rbfbuildmodel(&s, &rep, _state);
if( rep.terminationtype<=0 )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
rbfunpack(&s, &tmpnx, &tmpny, &xwr, &tmpnc, &v, &modelversion, _state);
if( ((((tmpnx!=nx||tmpny!=ny)||tmpnc!=xy.rows)||xwr.cols!=nx+ny+1)||xwr.rows!=tmpnc)||modelversion!=1 )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=tmpnc-2; i++)
{
if( ae_fp_greater(ae_fabs(xwr.ptr.pp_double[i][nx+ny]-sx, _state),errtol) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
if( ae_fp_greater(ae_fabs(xwr.ptr.pp_double[tmpnc-1][nx+ny]-z*sx, _state),errtol) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
/*
* RBF-ML with NLayers=0 gives us linear model.
*
* In order to perform this test, we use test function which
* is perfectly linear and see whether RBF model is able to
* reproduce such function.
*/
n = 5;
for(ny=1; ny<=3; ny++)
{
va = 2*ae_randomreal(_state)-1;
vb = 2*ae_randomreal(_state)-1;
vc = 2*ae_randomreal(_state)-1;
vd = 2*ae_randomreal(_state)-1;
/*
* Test NX=2.
* Generate linear function using random coefficients VA/VB/VC.
* Function is K-dimensional vector-valued, each component has slightly
* different coefficients.
*/
ae_matrix_set_length(&xy, n*n, 2+ny, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
xy.ptr.pp_double[n*i+j][0] = (double)(i);
xy.ptr.pp_double[n*i+j][1] = (double)(j);
for(k=0; k<=ny-1; k++)
{
xy.ptr.pp_double[n*i+j][2+k] = (va+0.1*k)*i+(vb+0.2*k)*j+(vc+0.3*k);
}
}
}
rbfcreate(2, ny, &s, _state);
rbfsetpoints(&s, &xy, n*n, _state);
rbfsetalgomultilayer(&s, 1.0, 0, 0.01, _state);
rbfbuildmodel(&s, &rep, _state);
if( rep.terminationtype<=0 )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
ae_vector_set_length(&x, 2, _state);
x.ptr.p_double[0] = (n-1)*ae_randomreal(_state);
x.ptr.p_double[1] = (n-1)*ae_randomreal(_state);
if( ny==1&&ae_fp_greater(ae_fabs(rbfcalc2(&s, x.ptr.p_double[0], x.ptr.p_double[1], _state)-(va*x.ptr.p_double[0]+vb*x.ptr.p_double[1]+vc), _state),errtol) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
rbfcalc(&s, &x, &y, _state);
for(k=0; k<=ny-1; k++)
{
if( ae_fp_greater(ae_fabs(y.ptr.p_double[k]-((va+0.1*k)*x.ptr.p_double[0]+(vb+0.2*k)*x.ptr.p_double[1]+(vc+0.3*k)), _state),errtol) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
/*
* Test NX=3.
* Generate linear function using random coefficients VA/VB/VC/VC.
* Function is K-dimensional vector-valued, each component has slightly
* different coefficients.
*/
ae_matrix_set_length(&xy, n*n*n, 3+ny, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
for(t=0; t<=n-1; t++)
{
xy.ptr.pp_double[n*n*i+n*j+t][0] = (double)(i);
xy.ptr.pp_double[n*n*i+n*j+t][1] = (double)(j);
xy.ptr.pp_double[n*n*i+n*j+t][2] = (double)(t);
for(k=0; k<=ny-1; k++)
{
xy.ptr.pp_double[n*n*i+n*j+t][3+k] = (va+0.1*k)*i+(vb+0.2*k)*j+(vc+0.3*k)*t+(vd+0.4*k);
}
}
}
}
rbfcreate(3, ny, &s, _state);
rbfsetpoints(&s, &xy, n*n*n, _state);
rbfsetalgomultilayer(&s, 1.0, 0, 0.01, _state);
rbfbuildmodel(&s, &rep, _state);
if( rep.terminationtype<=0 )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
ae_vector_set_length(&x, 3, _state);
x.ptr.p_double[0] = (n-1)*ae_randomreal(_state);
x.ptr.p_double[1] = (n-1)*ae_randomreal(_state);
x.ptr.p_double[2] = (n-1)*ae_randomreal(_state);
if( ny==1&&ae_fp_greater(ae_fabs(rbfcalc3(&s, x.ptr.p_double[0], x.ptr.p_double[1], x.ptr.p_double[2], _state)-(va*x.ptr.p_double[0]+vb*x.ptr.p_double[1]+vc*x.ptr.p_double[2]+vd), _state),errtol) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
rbfcalc(&s, &x, &y, _state);
for(k=0; k<=ny-1; k++)
{
if( ae_fp_greater(ae_fabs(y.ptr.p_double[k]-((va+0.1*k)*x.ptr.p_double[0]+(vb+0.2*k)*x.ptr.p_double[1]+(vc+0.3*k)*x.ptr.p_double[2]+(vd+0.4*k)), _state),errtol) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
/*
* HierarchicalRBF with NLayers=0 gives us linear model.
*
* In order to perform this test, we use test function which
* is perfectly linear and see whether RBF model is able to
* reproduce such function.
*/
n = 15;
for(nx=1; nx<=5; nx++)
{
for(ny=1; ny<=3; ny++)
{
ae_matrix_set_length(&vf, ny, nx+1, _state);
for(i=0; i<=ny-1; i++)
{
for(j=0; j<=nx; j++)
{
vf.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
ae_matrix_set_length(&xy, n, nx+ny, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=nx-1; j++)
{
xy.ptr.pp_double[i][j] = ae_randomreal(_state);
}
for(j=0; j<=ny-1; j++)
{
xy.ptr.pp_double[i][nx+j] = vf.ptr.pp_double[j][nx];
for(k=0; k<=nx-1; k++)
{
xy.ptr.pp_double[i][nx+j] = xy.ptr.pp_double[i][nx+j]+vf.ptr.pp_double[j][k]*xy.ptr.pp_double[i][k];
}
}
}
rbfcreate(nx, ny, &s, _state);
rbfsetpoints(&s, &xy, n, _state);
rbfsetalgohierarchical(&s, 1.0, 0, 0.0, _state);
rbfbuildmodel(&s, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:525");
ae_frame_leave(_state);
return result;
}
ae_vector_set_length(&x, nx, _state);
for(i=0; i<=nx-1; i++)
{
x.ptr.p_double[i] = ae_randomreal(_state);
}
rbfcalc(&s, &x, &y, _state);
for(k=0; k<=ny-1; k++)
{
vv = vf.ptr.pp_double[k][nx];
for(j=0; j<=nx-1; j++)
{
vv = vv+vf.ptr.pp_double[k][j]*x.ptr.p_double[j];
}
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vv-y.ptr.p_double[k], _state),errtol), __FILE__, __LINE__, "testrbfunit.ap:537");
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Function for testing basic functionality of RBF module on regular grids.
-- ALGLIB --
Copyright 13.12.2011 by Bochkanov Sergey
*************************************************************************/
static ae_bool testrbfunit_basicrbftest(ae_state *_state)
{
ae_frame _frame_block;
rbfmodel s;
rbfreport rep;
rbfcalcbuffer calcbuf;
ae_int_t nx;
ae_int_t ny;
ae_int_t k0;
ae_int_t k1;
ae_int_t k2;
ae_int_t linterm;
ae_int_t np;
double sx;
double sy;
double zx;
double px;
double zy;
double py;
double q;
double z;
ae_vector point;
ae_matrix gp;
ae_vector x;
ae_vector y;
ae_matrix gy;
ae_int_t unx;
ae_int_t uny;
ae_matrix xwr;
ae_matrix v;
ae_vector gpgx0;
ae_vector gpgx1;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t l;
ae_int_t fidx;
double eps;
ae_int_t modelversion;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&calcbuf, 0, sizeof(calcbuf));
memset(&point, 0, sizeof(point));
memset(&gp, 0, sizeof(gp));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&gy, 0, sizeof(gy));
memset(&xwr, 0, sizeof(xwr));
memset(&v, 0, sizeof(v));
memset(&gpgx0, 0, sizeof(gpgx0));
memset(&gpgx1, 0, sizeof(gpgx1));
_rbfmodel_init(&s, _state, ae_true);
_rbfreport_init(&rep, _state, ae_true);
_rbfcalcbuffer_init(&calcbuf, _state, ae_true);
ae_vector_init(&point, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&gp, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&gy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xwr, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&gpgx0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&gpgx1, 0, DT_REAL, _state, ae_true);
zx = (double)(10);
px = (double)(15);
zy = (double)(10);
py = (double)(15);
eps = 1.0E-6;
/*
* Problem types:
* * 2 and 3-dimensional problems
* * problems with zero, constant, linear terms
* * different scalings of X and Y values (1.0, 1E-15, 1E+15)
* * regular grids different grid sizes (from 2 to 4 points for each dimension)
*
* We check that:
* * RBF model correctly reproduces function value (testes with different Calc() functions)
* * unpacked model containt correct radii
* * linear term has correct form
*/
for(nx=2; nx<=3; nx++)
{
for(ny=1; ny<=3; ny++)
{
for(linterm=1; linterm<=3; linterm++)
{
/*
* prepare test problem
*/
sx = ae_pow(zx, px*(ae_randominteger(3, _state)-1), _state);
sy = ae_pow(zy, py*(ae_randominteger(3, _state)-1), _state);
ae_vector_set_length(&x, nx, _state);
ae_vector_set_length(&y, ny, _state);
ae_vector_set_length(&point, nx, _state);
rbfcreate(nx, ny, &s, _state);
rbfsetcond(&s, testrbfunit_heps, testrbfunit_heps, testrbfunit_mxits, _state);
q = 0.25+ae_randomreal(_state);
z = 4.5+ae_randomreal(_state);
rbfsetalgoqnn(&s, q, z, _state);
if( linterm==1 )
{
rbfsetlinterm(&s, _state);
}
if( linterm==2 )
{
rbfsetconstterm(&s, _state);
}
if( linterm==3 )
{
rbfsetzeroterm(&s, _state);
}
/*
* start points for grid
*/
for(i=0; i<=nx-1; i++)
{
point.ptr.p_double[i] = sx*(2*ae_randomreal(_state)-1);
}
/*
* 2-dimensional test problem
*/
if( nx==2 )
{
for(k0=2; k0<=4; k0++)
{
for(k1=2; k1<=4; k1++)
{
np = k0*k1;
ae_matrix_set_length(&gp, np, nx+ny, _state);
/*
* create grid
*/
for(i=0; i<=k0-1; i++)
{
for(j=0; j<=k1-1; j++)
{
gp.ptr.pp_double[i*k1+j][0] = point.ptr.p_double[0]+sx*i;
gp.ptr.pp_double[i*k1+j][1] = point.ptr.p_double[1]+sx*j;
for(k=0; k<=ny-1; k++)
{
gp.ptr.pp_double[i*k1+j][nx+k] = sy*(2*ae_randomreal(_state)-1);
}
}
}
rbfsetpoints(&s, &gp, np, _state);
rbfbuildmodel(&s, &rep, _state);
rbfcreatecalcbuffer(&s, &calcbuf, _state);
if( ny==1 )
{
ae_vector_set_length(&gpgx0, k0, _state);
ae_vector_set_length(&gpgx1, k1, _state);
for(i=0; i<=k0-1; i++)
{
gpgx0.ptr.p_double[i] = point.ptr.p_double[0]+sx*i;
}
for(i=0; i<=k1-1; i++)
{
gpgx1.ptr.p_double[i] = point.ptr.p_double[1]+sx*i;
}
rbfgridcalc2(&s, &gpgx0, k0, &gpgx1, k1, &gy, _state);
for(i=0; i<=k0-1; i++)
{
for(j=0; j<=k1-1; j++)
{
if( ae_fp_greater(ae_fabs(gy.ptr.pp_double[i][j]-gp.ptr.pp_double[i*k1+j][nx], _state),sy*eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
for(i=0; i<=np-1; i++)
{
/*
* For each row we randomly choose a function to test
* and call it. We do not call multiple functions per
* row because carry-over effects may mask errors in
* some function (say, it is possible that function
* simply returns results from previous call of some
* other function which were stored in the RBF model;
* in this case, previous call with same parameters
* may hide deficiencies in the function).
*/
x.ptr.p_double[0] = gp.ptr.pp_double[i][0];
x.ptr.p_double[1] = gp.ptr.pp_double[i][1];
fidx = ae_randominteger(4, _state);
if( fidx==0&&ny==1 )
{
y.ptr.p_double[0] = rbfcalc2(&s, x.ptr.p_double[0], x.ptr.p_double[1], _state);
if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx]-y.ptr.p_double[0], _state),sy*eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
if( fidx==1 )
{
rbfcalc(&s, &x, &y, _state);
for(j=0; j<=ny-1; j++)
{
if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
if( fidx==2 )
{
rbfcalcbuf(&s, &x, &y, _state);
for(j=0; j<=ny-1; j++)
{
if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
if( fidx==3 )
{
rbftscalcbuf(&s, &calcbuf, &x, &y, _state);
for(j=0; j<=ny-1; j++)
{
if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
/*
* test for RBFUnpack
*/
rbfunpack(&s, &unx, &uny, &xwr, &np, &v, &modelversion, _state);
if( (((((nx!=unx||ny!=uny)||xwr.rows!=np)||xwr.cols!=nx+ny+1)||v.rows!=ny)||v.cols!=nx+1)||modelversion!=1 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:735");
ae_frame_leave(_state);
return result;
}
for(i=0; i<=np-1; i++)
{
if( ae_fp_greater(ae_fabs(xwr.ptr.pp_double[i][unx+uny]-q*sx, _state),sx*eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
if( linterm==2 )
{
for(i=0; i<=unx-1; i++)
{
for(j=0; j<=uny-1; j++)
{
if( ae_fp_neq(v.ptr.pp_double[j][i],(double)(0)) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
if( linterm==3 )
{
for(i=0; i<=unx; i++)
{
for(j=0; j<=uny-1; j++)
{
if( ae_fp_neq(v.ptr.pp_double[j][i],(double)(0)) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
}
}
}
/*
* 3-dimensional test problems
*/
if( nx==3 )
{
for(k0=2; k0<=4; k0++)
{
for(k1=2; k1<=4; k1++)
{
for(k2=2; k2<=4; k2++)
{
np = k0*k1*k2;
ae_matrix_set_length(&gp, np, nx+ny, _state);
/*
* create grid
*/
for(i=0; i<=k0-1; i++)
{
for(j=0; j<=k1-1; j++)
{
for(k=0; k<=k2-1; k++)
{
gp.ptr.pp_double[(i*k1+j)*k2+k][0] = point.ptr.p_double[0]+sx*i;
gp.ptr.pp_double[(i*k1+j)*k2+k][1] = point.ptr.p_double[1]+sx*j;
gp.ptr.pp_double[(i*k1+j)*k2+k][2] = point.ptr.p_double[2]+sx*k;
for(l=0; l<=ny-1; l++)
{
gp.ptr.pp_double[(i*k1+j)*k2+k][nx+l] = sy*(2*ae_randomreal(_state)-1);
}
}
}
}
rbfsetpoints(&s, &gp, np, _state);
rbfbuildmodel(&s, &rep, _state);
rbfcreatecalcbuffer(&s, &calcbuf, _state);
for(i=0; i<=np-1; i++)
{
/*
* For each row we randomly choose a function to test
* and call it. We do not call multiple functions per
* row because carry-over effects may mask errors in
* some function (say, it is possible that function
* simply returns results from previous call of some
* other function which were stored in the RBF model;
* in this case, previous call with same parameters
* may hide deficiencies in the function).
*/
x.ptr.p_double[0] = gp.ptr.pp_double[i][0];
x.ptr.p_double[1] = gp.ptr.pp_double[i][1];
x.ptr.p_double[2] = gp.ptr.pp_double[i][2];
fidx = ae_randominteger(4, _state);
if( fidx==0&&ny==1 )
{
y.ptr.p_double[0] = rbfcalc3(&s, x.ptr.p_double[0], x.ptr.p_double[1], x.ptr.p_double[2], _state);
if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx]-y.ptr.p_double[0], _state),sy*eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
if( fidx==1 )
{
rbfcalc(&s, &x, &y, _state);
for(j=0; j<=ny-1; j++)
{
if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
if( fidx==2 )
{
rbfcalcbuf(&s, &x, &y, _state);
for(j=0; j<=ny-1; j++)
{
if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
if( fidx==3 )
{
rbftscalcbuf(&s, &calcbuf, &x, &y, _state);
for(j=0; j<=ny-1; j++)
{
if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
/*
* test for RBFUnpack
*/
rbfunpack(&s, &unx, &uny, &xwr, &np, &v, &modelversion, _state);
if( (((((nx!=unx||ny!=uny)||xwr.rows!=np)||xwr.cols!=nx+ny+1)||v.rows!=ny)||v.cols!=nx+1)||modelversion!=1 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:852");
ae_frame_leave(_state);
return result;
}
for(i=0; i<=np-1; i++)
{
if( ae_fp_greater(ae_fabs(xwr.ptr.pp_double[i][unx+uny]-q*sx, _state),sx*eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
if( linterm==2 )
{
for(i=0; i<=unx-1; i++)
{
for(j=0; j<=uny-1; j++)
{
if( ae_fp_neq(v.ptr.pp_double[j][i],(double)(0)) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
if( linterm==3 )
{
for(i=0; i<=unx; i++)
{
for(j=0; j<=uny-1; j++)
{
if( ae_fp_neq(v.ptr.pp_double[j][i],(double)(0)) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
}
}
}
}
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Function for testing RBF module on irregular grids.
-- ALGLIB --
Copyright 13.12.2011 by Bochkanov Sergey
*************************************************************************/
static ae_bool testrbfunit_irregularrbftest(ae_state *_state)
{
ae_frame _frame_block;
rbfmodel s;
rbfreport rep;
ae_int_t nx;
ae_int_t ny;
ae_int_t k0;
ae_int_t k1;
ae_int_t k2;
ae_int_t linterm;
ae_int_t np;
double sx;
double sy;
double zx;
double px;
double zy;
double py;
double q;
double z;
ae_vector point;
ae_matrix gp;
ae_vector x;
ae_vector y;
ae_matrix gy;
double noiselevel;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t l;
double eps;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&point, 0, sizeof(point));
memset(&gp, 0, sizeof(gp));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&gy, 0, sizeof(gy));
_rbfmodel_init(&s, _state, ae_true);
_rbfreport_init(&rep, _state, ae_true);
ae_vector_init(&point, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&gp, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&gy, 0, 0, DT_REAL, _state, ae_true);
zx = (double)(10);
px = (double)(15);
zy = (double)(10);
py = (double)(15);
noiselevel = 0.1;
eps = 1.0E-6;
/*
* Problem types:
* * 2 and 3-dimensional problems
* * problems with zero, constant, linear terms
* * different scalings of X and Y values (1.0, 1E-15, 1E+15)
* * noisy grids, which are just regular grids with different grid sizes
* (from 2 to 4 points for each dimension) and moderate amount of random
* noise added to all node positions.
*
* We check that:
* * RBF model correctly reproduces function value (testes with different Calc() functions)
*/
for(nx=2; nx<=3; nx++)
{
for(ny=1; ny<=3; ny++)
{
for(linterm=1; linterm<=3; linterm++)
{
/*
* prepare test problem
*/
sx = ae_pow(zx, px*(ae_randominteger(3, _state)-1), _state);
sy = ae_pow(zy, py*(ae_randominteger(3, _state)-1), _state);
ae_vector_set_length(&x, nx, _state);
ae_vector_set_length(&y, ny, _state);
ae_vector_set_length(&point, nx, _state);
rbfcreate(nx, ny, &s, _state);
rbfsetcond(&s, testrbfunit_heps, testrbfunit_heps, testrbfunit_mxits, _state);
q = 0.25+ae_randomreal(_state);
z = 4.5+ae_randomreal(_state);
rbfsetalgoqnn(&s, q, z, _state);
if( linterm==1 )
{
rbfsetlinterm(&s, _state);
}
if( linterm==2 )
{
rbfsetconstterm(&s, _state);
}
if( linterm==3 )
{
rbfsetzeroterm(&s, _state);
}
/*
* start points for grid
*/
for(i=0; i<=nx-1; i++)
{
point.ptr.p_double[i] = sx*(2*ae_randomreal(_state)-1);
}
/*
* 2-dimensional test problems
*/
if( nx==2 )
{
for(k0=2; k0<=4; k0++)
{
for(k1=2; k1<=4; k1++)
{
np = k0*k1;
ae_matrix_set_length(&gp, np, nx+ny, _state);
/*
* create grid
*/
for(i=0; i<=k0-1; i++)
{
for(j=0; j<=k1-1; j++)
{
gp.ptr.pp_double[i*k1+j][0] = point.ptr.p_double[0]+sx*i+noiselevel*sx*(2*ae_randomreal(_state)-1);
gp.ptr.pp_double[i*k1+j][1] = point.ptr.p_double[1]+sx*j+noiselevel*sx*(2*ae_randomreal(_state)-1);
for(k=0; k<=ny-1; k++)
{
gp.ptr.pp_double[i*k1+j][nx+k] = sy*(2*ae_randomreal(_state)-1);
}
}
}
rbfsetpoints(&s, &gp, np, _state);
rbfbuildmodel(&s, &rep, _state);
for(i=0; i<=np-1; i++)
{
x.ptr.p_double[0] = gp.ptr.pp_double[i][0];
x.ptr.p_double[1] = gp.ptr.pp_double[i][1];
if( ny==1 )
{
y.ptr.p_double[0] = rbfcalc2(&s, x.ptr.p_double[0], x.ptr.p_double[1], _state);
if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx]-y.ptr.p_double[0], _state),sy*eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
rbfcalc(&s, &x, &y, _state);
for(j=0; j<=ny-1; j++)
{
if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
rbfcalcbuf(&s, &x, &y, _state);
for(j=0; j<=ny-1; j++)
{
if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
}
}
/*
* 2-dimensional test problems
*/
if( nx==3 )
{
for(k0=2; k0<=4; k0++)
{
for(k1=2; k1<=4; k1++)
{
for(k2=2; k2<=4; k2++)
{
np = k0*k1*k2;
ae_matrix_set_length(&gp, np, nx+ny, _state);
/*
* create grid
*/
for(i=0; i<=k0-1; i++)
{
for(j=0; j<=k1-1; j++)
{
for(k=0; k<=k2-1; k++)
{
gp.ptr.pp_double[(i*k1+j)*k2+k][0] = point.ptr.p_double[0]+sx*i+noiselevel*sx*(2*ae_randomreal(_state)-1);
gp.ptr.pp_double[(i*k1+j)*k2+k][1] = point.ptr.p_double[1]+sx*j+noiselevel*sx*(2*ae_randomreal(_state)-1);
gp.ptr.pp_double[(i*k1+j)*k2+k][2] = point.ptr.p_double[2]+sx*k+noiselevel*sx*(2*ae_randomreal(_state)-1);
for(l=0; l<=ny-1; l++)
{
gp.ptr.pp_double[(i*k1+j)*k2+k][nx+l] = sy*(2*ae_randomreal(_state)-1);
}
}
}
}
rbfsetpoints(&s, &gp, np, _state);
rbfbuildmodel(&s, &rep, _state);
for(i=0; i<=np-1; i++)
{
x.ptr.p_double[0] = gp.ptr.pp_double[i][0];
x.ptr.p_double[1] = gp.ptr.pp_double[i][1];
x.ptr.p_double[2] = gp.ptr.pp_double[i][2];
if( ny==1 )
{
y.ptr.p_double[0] = rbfcalc3(&s, x.ptr.p_double[0], x.ptr.p_double[1], x.ptr.p_double[2], _state);
if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx]-y.ptr.p_double[0], _state),sy*eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
rbfcalc(&s, &x, &y, _state);
for(j=0; j<=ny-1; j++)
{
if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
rbfcalcbuf(&s, &x, &y, _state);
for(j=0; j<=ny-1; j++)
{
if( ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),sy*eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
}
}
}
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
The test does check, that algorithm can build linear model for the data
sets, when Y depends on X linearly.
-- ALGLIB --
Copyright 13.12.2011 by Bochkanov Sergey
*************************************************************************/
static ae_bool testrbfunit_linearitymodelrbftest(ae_state *_state)
{
ae_frame _frame_block;
rbfmodel s;
rbfreport rep;
ae_int_t nx;
ae_int_t ny;
ae_int_t k0;
ae_int_t k1;
ae_int_t k2;
ae_int_t linterm;
ae_int_t np;
double sx;
double sy;
double zx;
double px;
double zy;
double py;
double q;
double z;
ae_vector point;
ae_vector a;
ae_matrix gp;
ae_vector x;
ae_vector y;
ae_int_t unx;
ae_int_t uny;
ae_matrix xwr;
ae_matrix v;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t l;
ae_int_t modelversion;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&point, 0, sizeof(point));
memset(&a, 0, sizeof(a));
memset(&gp, 0, sizeof(gp));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&xwr, 0, sizeof(xwr));
memset(&v, 0, sizeof(v));
_rbfmodel_init(&s, _state, ae_true);
_rbfreport_init(&rep, _state, ae_true);
ae_vector_init(&point, 0, DT_REAL, _state, ae_true);
ae_vector_init(&a, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&gp, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xwr, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&v, 0, 0, DT_REAL, _state, ae_true);
zx = (double)(10);
px = (double)(15);
zy = (double)(10);
py = (double)(15);
ny = 1;
for(nx=2; nx<=3; nx++)
{
for(linterm=1; linterm<=3; linterm++)
{
/*
* prepare test problem
*/
sx = ae_pow(zx, px*(ae_randominteger(3, _state)-1), _state);
sy = ae_pow(zy, py*(ae_randominteger(3, _state)-1), _state);
ae_vector_set_length(&x, nx, _state);
ae_vector_set_length(&y, ny, _state);
ae_vector_set_length(&point, nx, _state);
rbfcreate(nx, ny, &s, _state);
q = 0.25+ae_randomreal(_state);
z = 4.5+ae_randomreal(_state);
rbfsetalgoqnn(&s, q, z, _state);
ae_vector_set_length(&a, nx+1, _state);
if( linterm==1 )
{
rbfsetlinterm(&s, _state);
for(i=0; i<=nx-1; i++)
{
a.ptr.p_double[i] = sy*(2*ae_randomreal(_state)-1)/sx;
}
a.ptr.p_double[nx] = sy*(2*ae_randomreal(_state)-1);
}
if( linterm==2 )
{
rbfsetconstterm(&s, _state);
for(i=0; i<=nx-1; i++)
{
a.ptr.p_double[i] = (double)(0);
}
a.ptr.p_double[nx] = sy*(2*ae_randomreal(_state)-1);
}
if( linterm==3 )
{
rbfsetzeroterm(&s, _state);
for(i=0; i<=nx; i++)
{
a.ptr.p_double[i] = (double)(0);
}
}
/*
* start points for grid
*/
for(i=0; i<=nx-1; i++)
{
point.ptr.p_double[i] = sx*(2*ae_randomreal(_state)-1);
}
if( nx==2 )
{
for(k0=2; k0<=4; k0++)
{
for(k1=2; k1<=4; k1++)
{
np = k0*k1;
ae_matrix_set_length(&gp, np, nx+ny, _state);
/*
* create grid
*/
for(i=0; i<=k0-1; i++)
{
for(j=0; j<=k1-1; j++)
{
gp.ptr.pp_double[i*k1+j][0] = point.ptr.p_double[0]+sx*i;
gp.ptr.pp_double[i*k1+j][1] = point.ptr.p_double[1]+sx*j;
gp.ptr.pp_double[i*k1+j][nx] = a.ptr.p_double[nx];
for(k=0; k<=nx-1; k++)
{
gp.ptr.pp_double[i*k1+j][nx] = gp.ptr.pp_double[i*k1+j][nx]+gp.ptr.pp_double[i*k1+j][k]*a.ptr.p_double[k];
}
}
}
rbfsetpoints(&s, &gp, np, _state);
rbfbuildmodel(&s, &rep, _state);
/*
* test for RBFUnpack
*/
rbfunpack(&s, &unx, &uny, &xwr, &np, &v, &modelversion, _state);
if( (((((nx!=unx||ny!=uny)||xwr.rows!=np)||xwr.cols!=nx+ny+1)||v.rows!=ny)||v.cols!=nx+1)||modelversion!=1 )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=nx-1; i++)
{
if( ae_fp_greater(ae_fabs(v.ptr.pp_double[0][i]-a.ptr.p_double[i], _state),sy/sx*testrbfunit_tol) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
if( ae_fp_greater(ae_fabs(v.ptr.pp_double[0][nx]-a.ptr.p_double[nx], _state),sy*testrbfunit_tol) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=np-1; i++)
{
if( ae_fp_greater(ae_fabs(xwr.ptr.pp_double[i][unx], _state),sy*testrbfunit_tol) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
}
if( nx==3 )
{
for(k0=2; k0<=4; k0++)
{
for(k1=2; k1<=4; k1++)
{
for(k2=2; k2<=4; k2++)
{
np = k0*k1*k2;
ae_matrix_set_length(&gp, np, nx+ny, _state);
/*
* create grid
*/
for(i=0; i<=k0-1; i++)
{
for(j=0; j<=k1-1; j++)
{
for(k=0; k<=k2-1; k++)
{
gp.ptr.pp_double[(i*k1+j)*k2+k][0] = point.ptr.p_double[0]+sx*i;
gp.ptr.pp_double[(i*k1+j)*k2+k][1] = point.ptr.p_double[1]+sx*j;
gp.ptr.pp_double[(i*k1+j)*k2+k][2] = point.ptr.p_double[2]+sx*k;
gp.ptr.pp_double[(i*k1+j)*k2+k][nx] = a.ptr.p_double[nx];
for(l=0; l<=nx-1; l++)
{
gp.ptr.pp_double[(i*k1+j)*k2+k][nx] = gp.ptr.pp_double[(i*k1+j)*k2+k][nx]+gp.ptr.pp_double[(i*k1+j)*k2+k][l]*a.ptr.p_double[l];
}
}
}
}
rbfsetpoints(&s, &gp, np, _state);
rbfbuildmodel(&s, &rep, _state);
/*
* test for RBFUnpack
*/
rbfunpack(&s, &unx, &uny, &xwr, &np, &v, &modelversion, _state);
if( (((((nx!=unx||ny!=uny)||xwr.rows!=np)||xwr.cols!=nx+ny+1)||v.rows!=ny)||v.cols!=nx+1)||modelversion!=1 )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=nx-1; i++)
{
if( ae_fp_greater(ae_fabs(v.ptr.pp_double[0][i]-a.ptr.p_double[i], _state),sy/sx*testrbfunit_tol) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
if( ae_fp_greater(ae_fabs(v.ptr.pp_double[0][nx]-a.ptr.p_double[nx], _state),sy*testrbfunit_tol) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=np-1; i++)
{
if( ae_fp_greater(ae_fabs(xwr.ptr.pp_double[i][unx], _state),sy*testrbfunit_tol) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
}
}
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function tests serialization
-- ALGLIB --
Copyright 02.02.2012 by Bochkanov Sergey
*************************************************************************/
static ae_bool testrbfunit_serializationtest(ae_state *_state)
{
ae_frame _frame_block;
rbfmodel s;
rbfmodel s2;
rbfreport rep;
ae_int_t n;
ae_int_t nx;
ae_int_t ny;
ae_int_t k0;
ae_int_t k1;
ae_int_t k2;
ae_int_t i;
ae_int_t i0;
ae_int_t i1;
ae_int_t i2;
ae_int_t j;
ae_int_t k;
double rbase;
ae_int_t nlayers;
ae_int_t bf;
ae_int_t gridsize;
ae_matrix xy;
ae_vector testpoint;
ae_vector y0;
ae_vector y1;
ae_vector scalevec;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&s2, 0, sizeof(s2));
memset(&rep, 0, sizeof(rep));
memset(&xy, 0, sizeof(xy));
memset(&testpoint, 0, sizeof(testpoint));
memset(&y0, 0, sizeof(y0));
memset(&y1, 0, sizeof(y1));
memset(&scalevec, 0, sizeof(scalevec));
_rbfmodel_init(&s, _state, ae_true);
_rbfmodel_init(&s2, _state, ae_true);
_rbfreport_init(&rep, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&testpoint, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&scalevec, 0, DT_REAL, _state, ae_true);
result = ae_false;
/*
* This function generates random 2 or 3 dimensional problem,
* builds RBF model (QNN is used), serializes/unserializes it, then compares
* models by calculating model value at some random point.
*
* Additionally we test that new model (one which was restored
* after serialization) has lost all model construction settings,
* i.e. if we call RBFBuildModel() on a NEW model, we will get
* empty (zero) model.
*/
for(nx=2; nx<=3; nx++)
{
for(ny=1; ny<=2; ny++)
{
/*
* prepare test problem
*/
rbfcreate(nx, ny, &s, _state);
rbfsetalgoqnn(&s, 1.0, 5.0, _state);
rbfsetlinterm(&s, _state);
if( nx==2 )
{
/*
* 2-dimensional problem
*/
k0 = 2+ae_randominteger(4, _state);
k1 = 2+ae_randominteger(4, _state);
ae_matrix_set_length(&xy, k0*k1, nx+ny, _state);
for(i0=0; i0<=k0-1; i0++)
{
for(i1=0; i1<=k1-1; i1++)
{
xy.ptr.pp_double[i0*k1+i1][0] = i0+0.1*(2*ae_randomreal(_state)-1);
xy.ptr.pp_double[i0*k1+i1][1] = i1+0.1*(2*ae_randomreal(_state)-1);
for(j=0; j<=ny-1; j++)
{
xy.ptr.pp_double[i0*k1+i1][nx+j] = 2*ae_randomreal(_state)-1;
}
}
}
ae_vector_set_length(&testpoint, nx, _state);
testpoint.ptr.p_double[0] = ae_randomreal(_state)*(k0-1);
testpoint.ptr.p_double[1] = ae_randomreal(_state)*(k1-1);
}
else
{
/*
* 3-dimensional problem
*/
k0 = 2+ae_randominteger(4, _state);
k1 = 2+ae_randominteger(4, _state);
k2 = 2+ae_randominteger(4, _state);
ae_matrix_set_length(&xy, k0*k1*k2, nx+ny, _state);
for(i0=0; i0<=k0-1; i0++)
{
for(i1=0; i1<=k1-1; i1++)
{
for(i2=0; i2<=k2-1; i2++)
{
xy.ptr.pp_double[i0*k1*k2+i1*k2+i2][0] = i0+0.1*(2*ae_randomreal(_state)-1);
xy.ptr.pp_double[i0*k1*k2+i1*k2+i2][1] = i1+0.1*(2*ae_randomreal(_state)-1);
xy.ptr.pp_double[i0*k1*k2+i1*k2+i2][2] = i2+0.1*(2*ae_randomreal(_state)-1);
for(j=0; j<=ny-1; j++)
{
xy.ptr.pp_double[i0*k1*k2+i1*k2+i2][nx+j] = 2*ae_randomreal(_state)-1;
}
}
}
}
ae_vector_set_length(&testpoint, nx, _state);
testpoint.ptr.p_double[0] = ae_randomreal(_state)*(k0-1);
testpoint.ptr.p_double[1] = ae_randomreal(_state)*(k1-1);
testpoint.ptr.p_double[2] = ae_randomreal(_state)*(k2-1);
}
rbfsetpoints(&s, &xy, xy.rows, _state);
/*
* Build model, serialize, compare
*/
rbfbuildmodel(&s, &rep, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
rbfalloc(&_local_serializer, &s, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
rbfserialize(&_local_serializer, &s, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
rbfunserialize(&_local_serializer, &s2, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
rbfcalc(&s, &testpoint, &y0, _state);
rbfcalc(&s2, &testpoint, &y1, _state);
if( y0.cnt!=ny||y1.cnt!=ny )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(j=0; j<=ny-1; j++)
{
if( ae_fp_neq(y0.ptr.p_double[j],y1.ptr.p_double[j]) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
/*
* Check that calling RBFBuildModel() on S2 (new model)
* will result in construction of zero model, i.e. test
* that serialization restores model, but not dataset
* which was used to build model.
*/
rbfbuildmodel(&s2, &rep, _state);
rbfcalc(&s2, &testpoint, &y1, _state);
if( y1.cnt!=ny )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(j=0; j<=ny-1; j++)
{
if( ae_fp_neq(y1.ptr.p_double[j],(double)(0)) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
/*
* This function generates random 2 or 3 dimensional problem,
* builds model using RBF-ML algo, serializes/unserializes it,
* then compares models by calculating model value at some
* random point.
*
* Additionally we test that new model (one which was restored
* after serialization) has lost all model construction settings,
* i.e. if we call RBFBuildModel() on a NEW model, we will get
* empty (zero) model.
*/
for(nx=2; nx<=3; nx++)
{
for(ny=1; ny<=2; ny++)
{
/*
* prepare test problem
*/
rbfcreate(nx, ny, &s, _state);
rbfsetalgomultilayer(&s, 5.0, 5, 1.0E-3, _state);
rbfsetlinterm(&s, _state);
if( nx==2 )
{
/*
* 2-dimensional problem
*/
k0 = 2+ae_randominteger(4, _state);
k1 = 2+ae_randominteger(4, _state);
ae_matrix_set_length(&xy, k0*k1, nx+ny, _state);
for(i0=0; i0<=k0-1; i0++)
{
for(i1=0; i1<=k1-1; i1++)
{
xy.ptr.pp_double[i0*k1+i1][0] = i0+0.1*(2*ae_randomreal(_state)-1);
xy.ptr.pp_double[i0*k1+i1][1] = i1+0.1*(2*ae_randomreal(_state)-1);
for(j=0; j<=ny-1; j++)
{
xy.ptr.pp_double[i0*k1+i1][nx+j] = 2*ae_randomreal(_state)-1;
}
}
}
ae_vector_set_length(&testpoint, nx, _state);
testpoint.ptr.p_double[0] = ae_randomreal(_state)*(k0-1);
testpoint.ptr.p_double[1] = ae_randomreal(_state)*(k1-1);
}
else
{
/*
* 3-dimensional problem
*/
k0 = 2+ae_randominteger(4, _state);
k1 = 2+ae_randominteger(4, _state);
k2 = 2+ae_randominteger(4, _state);
ae_matrix_set_length(&xy, k0*k1*k2, nx+ny, _state);
for(i0=0; i0<=k0-1; i0++)
{
for(i1=0; i1<=k1-1; i1++)
{
for(i2=0; i2<=k2-1; i2++)
{
xy.ptr.pp_double[i0*k1*k2+i1*k2+i2][0] = i0+0.1*(2*ae_randomreal(_state)-1);
xy.ptr.pp_double[i0*k1*k2+i1*k2+i2][1] = i1+0.1*(2*ae_randomreal(_state)-1);
xy.ptr.pp_double[i0*k1*k2+i1*k2+i2][2] = i2+0.1*(2*ae_randomreal(_state)-1);
for(j=0; j<=ny-1; j++)
{
xy.ptr.pp_double[i0*k1*k2+i1*k2+i2][nx+j] = 2*ae_randomreal(_state)-1;
}
}
}
}
ae_vector_set_length(&testpoint, nx, _state);
testpoint.ptr.p_double[0] = ae_randomreal(_state)*(k0-1);
testpoint.ptr.p_double[1] = ae_randomreal(_state)*(k1-1);
testpoint.ptr.p_double[2] = ae_randomreal(_state)*(k2-1);
}
rbfsetpoints(&s, &xy, xy.rows, _state);
/*
* Build model, serialize, compare
*/
rbfbuildmodel(&s, &rep, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
rbfalloc(&_local_serializer, &s, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
rbfserialize(&_local_serializer, &s, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
rbfunserialize(&_local_serializer, &s2, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
rbfcalc(&s, &testpoint, &y0, _state);
rbfcalc(&s2, &testpoint, &y1, _state);
if( y0.cnt!=ny||y1.cnt!=ny )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(j=0; j<=ny-1; j++)
{
if( ae_fp_neq(y0.ptr.p_double[j],y1.ptr.p_double[j]) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
/*
* Check that calling RBFBuildModel() on S2 (new model)
* will result in construction of zero model, i.e. test
* that serialization restores model, but not dataset
* which was used to build model.
*/
rbfbuildmodel(&s2, &rep, _state);
rbfcalc(&s2, &testpoint, &y1, _state);
if( y1.cnt!=ny )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(j=0; j<=ny-1; j++)
{
if( ae_fp_neq(y1.ptr.p_double[j],(double)(0)) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
/*
* This function generates random 1...4-dimensional problem,
* builds model using RBF-H algo, serializes/unserializes it,
* then compares models by calculating model value at some
* random point.
*
* NOTE: we choose at random whether to use default scaling -
* or user-supplied one.
*
* Additionally we test that new model (one which was restored
* after serialization) has lost all model construction settings,
* i.e. if we call RBFBuildModel() on a NEW model, we will get
* empty (zero) model.
*/
for(nx=1; nx<=4; nx++)
{
for(ny=1; ny<=2; ny++)
{
/*
* problem setup
*/
n = 150;
rbase = 0.33;
nlayers = 5;
gridsize = ae_round(ae_pow((double)(n), (double)1/(double)nx, _state), _state)+1;
bf = ae_randominteger(2, _state);
n = ae_round(ae_pow((double)(gridsize), (double)(nx), _state), _state);
ae_matrix_set_length(&xy, n, nx+ny, _state);
ae_assert(gridsize>1, "Assertion failed", _state);
ae_assert(ae_fp_eq((double)(n),ae_pow((double)(gridsize), (double)(nx), _state)), "Assertion failed", _state);
for(i=0; i<=n-1; i++)
{
k = i;
for(j=0; j<=nx-1; j++)
{
xy.ptr.pp_double[i][j] = (double)(k%gridsize)/(double)(gridsize-1);
k = k/gridsize;
}
for(j=0; j<=ny-1; j++)
{
xy.ptr.pp_double[i][nx+j] = ae_randomreal(_state)-0.5;
}
}
ae_vector_set_length(&testpoint, nx, _state);
for(j=0; j<=nx-1; j++)
{
testpoint.ptr.p_double[j] = ae_randomreal(_state);
}
ae_vector_set_length(&scalevec, nx, _state);
for(j=0; j<=nx-1; j++)
{
scalevec.ptr.p_double[j] = ae_pow((double)(2), 2*ae_randomreal(_state)-1, _state);
}
/*
* prepare test problem
*/
rbfcreate(nx, ny, &s, _state);
rbfsetv2bf(&s, bf, _state);
rbfsetalgohierarchical(&s, rbase, nlayers, 0.0, _state);
rbfsetlinterm(&s, _state);
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
rbfsetpoints(&s, &xy, xy.rows, _state);
}
else
{
rbfsetpointsandscales(&s, &xy, xy.rows, &scalevec, _state);
}
/*
* Build model, serialize, compare
*/
rbfbuildmodel(&s, &rep, _state);
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
rbfalloc(&_local_serializer, &s, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
rbfserialize(&_local_serializer, &s, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
rbfunserialize(&_local_serializer, &s2, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
rbfcalc(&s, &testpoint, &y0, _state);
rbfcalc(&s2, &testpoint, &y1, _state);
if( y0.cnt!=ny||y1.cnt!=ny )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(j=0; j<=ny-1; j++)
{
if( ae_fp_neq(y0.ptr.p_double[j],y1.ptr.p_double[j]) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
/*
* Check that calling RBFBuildModel() on S2 (new model)
* will result in construction of zero model, i.e. test
* that serialization restores model, but not dataset
* which was used to build model.
*/
rbfbuildmodel(&s2, &rep, _state);
rbfcalc(&s2, &testpoint, &y1, _state);
if( y1.cnt!=ny )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(j=0; j<=ny-1; j++)
{
if( ae_fp_neq(y1.ptr.p_double[j],(double)(0)) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
ae_frame_leave(_state);
return result;
}
static ae_bool testrbfunit_searcherr(/* Real */ ae_matrix* y0,
/* Real */ ae_matrix* y1,
ae_int_t n,
ae_int_t ny,
ae_int_t errtype,
/* Real */ ae_vector* b1,
/* Real */ ae_vector* delta,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix _y0;
ae_matrix _y1;
ae_vector _b1;
ae_vector _delta;
double oralerr;
double iralerr;
ae_vector irerr;
ae_vector orerr;
ae_int_t lb;
ae_int_t rb;
ae_int_t i;
ae_int_t j;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&_y0, 0, sizeof(_y0));
memset(&_y1, 0, sizeof(_y1));
memset(&_b1, 0, sizeof(_b1));
memset(&_delta, 0, sizeof(_delta));
memset(&irerr, 0, sizeof(irerr));
memset(&orerr, 0, sizeof(orerr));
ae_matrix_init_copy(&_y0, y0, _state, ae_true);
y0 = &_y0;
ae_matrix_init_copy(&_y1, y1, _state, ae_true);
y1 = &_y1;
ae_vector_init_copy(&_b1, b1, _state, ae_true);
b1 = &_b1;
ae_vector_init_copy(&_delta, delta, _state, ae_true);
delta = &_delta;
ae_vector_init(&irerr, 0, DT_REAL, _state, ae_true);
ae_vector_init(&orerr, 0, DT_REAL, _state, ae_true);
ae_assert(n>0, "SearchErr: invalid parameter N(N<=0).", _state);
ae_assert(ny>0, "SearchErr: invalid parameter NY(NY<=0).", _state);
oralerr = 1.0E-1;
iralerr = 1.0E-2;
lb = 25;
rb = 75;
ae_vector_set_length(&orerr, ny, _state);
ae_vector_set_length(&irerr, ny, _state);
for(j=0; j<=ny-1; j++)
{
orerr.ptr.p_double[j] = (double)(0);
irerr.ptr.p_double[j] = (double)(0);
}
if( errtype==1 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=ny-1; j++)
{
if( ae_fp_less(orerr.ptr.p_double[j],ae_fabs(y0->ptr.pp_double[i][j]-y1->ptr.pp_double[i][j], _state)) )
{
orerr.ptr.p_double[j] = ae_fabs(y0->ptr.pp_double[i][j]-y1->ptr.pp_double[i][j], _state);
}
}
}
for(i=0; i<=ny-1; i++)
{
if( ae_fp_greater(orerr.ptr.p_double[i],b1->ptr.p_double[i]+delta->ptr.p_double[i])||ae_fp_less(orerr.ptr.p_double[i],b1->ptr.p_double[i]-delta->ptr.p_double[i]) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
else
{
if( errtype==2 )
{
for(i=0; i<=n-1; i++)
{
for(j=0; j<=ny-1; j++)
{
if( i>lb&&iptr.pp_double[i][j]-y1->ptr.pp_double[i][j], _state)) )
{
irerr.ptr.p_double[j] = ae_fabs(y0->ptr.pp_double[i][j]-y1->ptr.pp_double[i][j], _state);
}
}
else
{
if( ae_fp_less(orerr.ptr.p_double[j],ae_fabs(y0->ptr.pp_double[i][j]-y1->ptr.pp_double[i][j], _state)) )
{
orerr.ptr.p_double[j] = ae_fabs(y0->ptr.pp_double[i][j]-y1->ptr.pp_double[i][j], _state);
}
}
}
}
for(i=0; i<=ny-1; i++)
{
if( ae_fp_greater(orerr.ptr.p_double[i],oralerr)||ae_fp_greater(irerr.ptr.p_double[i],iralerr) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
else
{
ae_assert(ae_false, "SearchErr: invalid argument ErrType(ErrType neither 1 nor 2)", _state);
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Function for testing basic functionality of RBF module on regular grids with
multi-layer algorithm in 2-3D.
-- ALGLIB --
Copyright 2.03.2012 by Bochkanov Sergey
*************************************************************************/
static ae_bool testrbfunit_basicmultilayerrbftest(ae_state *_state)
{
ae_frame _frame_block;
rbfmodel s;
rbfreport rep;
rbfcalcbuffer calcbuf;
ae_int_t nx;
ae_int_t ny;
ae_int_t k0;
ae_int_t k1;
ae_int_t k2;
ae_int_t linterm;
ae_int_t np;
double q;
ae_int_t layers;
double eps;
ae_int_t range;
double s1;
double s2;
double gstep;
ae_vector point;
ae_matrix gp;
ae_vector x;
ae_vector y;
ae_matrix gy;
ae_vector gpgx0;
ae_vector gpgx1;
ae_vector gpgx2;
ae_vector gcy;
ae_int_t pass;
ae_int_t passcount;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t l;
ae_int_t fidx;
double r0;
ae_int_t margin;
ae_int_t gridsize;
double threshold;
double v;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&calcbuf, 0, sizeof(calcbuf));
memset(&point, 0, sizeof(point));
memset(&gp, 0, sizeof(gp));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&gy, 0, sizeof(gy));
memset(&gpgx0, 0, sizeof(gpgx0));
memset(&gpgx1, 0, sizeof(gpgx1));
memset(&gpgx2, 0, sizeof(gpgx2));
memset(&gcy, 0, sizeof(gcy));
_rbfmodel_init(&s, _state, ae_true);
_rbfreport_init(&rep, _state, ae_true);
_rbfcalcbuffer_init(&calcbuf, _state, ae_true);
ae_vector_init(&point, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&gp, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&gy, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&gpgx0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&gpgx1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&gpgx2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&gcy, 0, DT_REAL, _state, ae_true);
result = ae_false;
range = 10;
passcount = 10;
eps = 1.0E-6;
/*
* Test that RBF model with sufficient layers will exactly reproduce
* target function.
*/
for(pass=0; pass<=passcount-1; pass++)
{
/*
* prepare test problem
*/
k0 = 6+ae_randominteger(3, _state);
k1 = 6+ae_randominteger(3, _state);
k2 = 6+ae_randominteger(3, _state);
s1 = ae_pow((double)(range), (double)(ae_randominteger(3, _state)-1), _state);
s2 = ae_pow((double)(range), (double)(ae_randominteger(3, _state)-1), _state);
nx = ae_randominteger(2, _state)+2;
ny = ae_randominteger(2, _state)+1;
linterm = ae_randominteger(3, _state)+1;
layers = 5;
gstep = s1/6;
q = s1;
/*
* Create RBF structure and auxiliary structures
*/
ae_vector_set_length(&x, nx, _state);
ae_vector_set_length(&y, ny, _state);
ae_vector_set_length(&point, nx, _state);
rbfcreate(nx, ny, &s, _state);
rbfsetalgomultilayer(&s, q, layers, 0.0, _state);
if( linterm==1 )
{
rbfsetlinterm(&s, _state);
}
if( linterm==2 )
{
rbfsetconstterm(&s, _state);
}
if( linterm==3 )
{
rbfsetzeroterm(&s, _state);
}
for(i=0; i<=nx-1; i++)
{
point.ptr.p_double[i] = s1*(2*ae_randomreal(_state)-1);
}
/*
* 2-dimensional test problem
*/
if( nx==2 )
{
np = k0*k1;
ae_matrix_set_length(&gp, np, nx+ny, _state);
/*
* create grid
*/
for(i=0; i<=k0-1; i++)
{
for(j=0; j<=k1-1; j++)
{
gp.ptr.pp_double[i*k1+j][0] = point.ptr.p_double[0]+gstep*i;
gp.ptr.pp_double[i*k1+j][1] = point.ptr.p_double[1]+gstep*j;
for(k=0; k<=ny-1; k++)
{
gp.ptr.pp_double[i*k1+j][nx+k] = s2*(2*ae_randomreal(_state)-1);
}
}
}
rbfsetpoints(&s, &gp, np, _state);
rbfbuildmodel(&s, &rep, _state);
rbfcreatecalcbuffer(&s, &calcbuf, _state);
if( ny==1 )
{
ae_vector_set_length(&gpgx0, k0, _state);
ae_vector_set_length(&gpgx1, k1, _state);
for(i=0; i<=k0-1; i++)
{
gpgx0.ptr.p_double[i] = point.ptr.p_double[0]+gstep*i;
}
for(i=0; i<=k1-1; i++)
{
gpgx1.ptr.p_double[i] = point.ptr.p_double[1]+gstep*i;
}
rbfgridcalc2(&s, &gpgx0, k0, &gpgx1, k1, &gy, _state);
for(i=0; i<=k0-1; i++)
{
for(j=0; j<=k1-1; j++)
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(gy.ptr.pp_double[i][j]-gp.ptr.pp_double[i*k1+j][nx], _state),s2*eps), __FILE__, __LINE__, "testrbfunit.ap:2216");
}
}
}
for(i=0; i<=np-1; i++)
{
/*
* For each row we randomly choose a function to test
* and call it. We do not call multiple functions per
* row because carry-over effects may mask errors in
* some function (say, it is possible that function
* simply returns results from previous call of some
* other function which were stored in the RBF model;
* in this case, previous call with same parameters
* may hide deficiencies in the function).
*/
x.ptr.p_double[0] = gp.ptr.pp_double[i][0];
x.ptr.p_double[1] = gp.ptr.pp_double[i][1];
fidx = ae_randominteger(4, _state);
if( fidx==0&&ny!=1 )
{
continue;
}
if( fidx==0 )
{
y.ptr.p_double[0] = rbfcalc2(&s, x.ptr.p_double[0], x.ptr.p_double[1], _state);
}
if( fidx==1 )
{
rbfcalc(&s, &x, &y, _state);
}
if( fidx==2 )
{
rbfcalcbuf(&s, &x, &y, _state);
}
if( fidx==3 )
{
rbftscalcbuf(&s, &calcbuf, &x, &y, _state);
}
for(j=0; j<=ny-1; j++)
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),s2*eps), __FILE__, __LINE__, "testrbfunit.ap:2244");
}
}
}
/*
* 3-dimensional test problems
*/
if( nx==3 )
{
np = k0*k1*k2;
ae_matrix_set_length(&gp, np, nx+ny, _state);
/*
* create grid, build model
*/
ae_vector_set_length(&gpgx0, k0, _state);
ae_vector_set_length(&gpgx1, k1, _state);
ae_vector_set_length(&gpgx2, k2, _state);
for(i=0; i<=k0-1; i++)
{
gpgx0.ptr.p_double[i] = point.ptr.p_double[0]+gstep*i;
}
for(i=0; i<=k1-1; i++)
{
gpgx1.ptr.p_double[i] = point.ptr.p_double[1]+gstep*i;
}
for(i=0; i<=k2-1; i++)
{
gpgx2.ptr.p_double[i] = point.ptr.p_double[2]+gstep*i;
}
for(i=0; i<=k0-1; i++)
{
for(j=0; j<=k1-1; j++)
{
for(k=0; k<=k2-1; k++)
{
gp.ptr.pp_double[(i*k1+j)*k2+k][0] = gpgx0.ptr.p_double[i];
gp.ptr.pp_double[(i*k1+j)*k2+k][1] = gpgx1.ptr.p_double[j];
gp.ptr.pp_double[(i*k1+j)*k2+k][2] = gpgx2.ptr.p_double[k];
for(l=0; l<=ny-1; l++)
{
gp.ptr.pp_double[(i*k1+j)*k2+k][nx+l] = s2*(2*ae_randomreal(_state)-1);
}
}
}
}
rbfsetpoints(&s, &gp, np, _state);
rbfbuildmodel(&s, &rep, _state);
rbfcreatecalcbuffer(&s, &calcbuf, _state);
/*
* Test RBFCalc3(), RBFCalc() and RBFCalcBuf() vs expected values on the grid (we expect good fit).
*/
for(i=0; i<=np-1; i++)
{
/*
* For each row we randomly choose a function to test
* and call it. We do not call multiple functions per
* row because carry-over effects may mask errors in
* some function (say, it is possible that function
* simply returns results from previous call of some
* other function which were stored in the RBF model;
* in this case, previous call with same parameters
* may hide deficiencies in the function).
*/
x.ptr.p_double[0] = gp.ptr.pp_double[i][0];
x.ptr.p_double[1] = gp.ptr.pp_double[i][1];
x.ptr.p_double[2] = gp.ptr.pp_double[i][2];
fidx = ae_randominteger(4, _state);
if( fidx==0&&ny!=1 )
{
continue;
}
if( fidx==0 )
{
y.ptr.p_double[0] = rbfcalc3(&s, x.ptr.p_double[0], x.ptr.p_double[1], x.ptr.p_double[2], _state);
}
if( fidx==1 )
{
rbfcalc(&s, &x, &y, _state);
}
if( fidx==2 )
{
rbfcalcbuf(&s, &x, &y, _state);
}
if( fidx==3 )
{
rbftscalcbuf(&s, &calcbuf, &x, &y, _state);
}
for(j=0; j<=ny-1; j++)
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(gp.ptr.pp_double[i][nx+j]-y.ptr.p_double[j], _state),s2*eps), __FILE__, __LINE__, "testrbfunit.ap:2312");
}
}
/*
* Test RBFGridCalc3V vs RBFCalc()
*/
rbfgridcalc3v(&s, &gpgx0, k0, &gpgx1, k1, &gpgx2, k2, &gcy, _state);
for(i=0; i<=k0-1; i++)
{
for(j=0; j<=k1-1; j++)
{
for(k=0; k<=k2-1; k++)
{
x.ptr.p_double[0] = gpgx0.ptr.p_double[i];
x.ptr.p_double[1] = gpgx1.ptr.p_double[j];
x.ptr.p_double[2] = gpgx2.ptr.p_double[k];
rbfcalcbuf(&s, &x, &y, _state);
for(l=0; l<=ny-1; l++)
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(y.ptr.p_double[l]-gcy.ptr.p_double[l+ny*(i+j*k0+k*k0*k1)], _state),1.0E-9*s2), __FILE__, __LINE__, "testrbfunit.ap:2329");
}
}
}
}
}
}
/*
* Test smoothing properties of RBF model: model with just one layer
* and large initial radius will produce "average" value of neighbors.
*
* In order to test it we create regular grid, fill it with regular
* +1/-1 pattern, and test model values in the inner points. Model
* values should be around zero (we use handcrafted threshold to test
* it). Radius is chosen to be several times larger than grid step.
*
* We perform test for 2D model, because same behavior is expected
* regardless of dimensionality.
*/
r0 = (double)(3);
margin = 5;
gridsize = 2*margin+20;
threshold = 0.1;
nx = 2;
ny = 1;
rbfcreate(nx, ny, &s, _state);
rbfsetalgomultilayer(&s, r0, 1, 0.0, _state);
rbfsetzeroterm(&s, _state);
ae_matrix_set_length(&gp, gridsize*gridsize, nx+ny, _state);
for(i=0; i<=gridsize-1; i++)
{
for(j=0; j<=gridsize-1; j++)
{
gp.ptr.pp_double[i*gridsize+j][0] = (double)(i);
gp.ptr.pp_double[i*gridsize+j][1] = (double)(j);
gp.ptr.pp_double[i*gridsize+j][2] = 0.10*ae_randomreal(_state)-0.05+(2*((i+j)%2)-1);
}
}
rbfsetpoints(&s, &gp, gridsize*gridsize, _state);
rbfbuildmodel(&s, &rep, _state);
v = 0.0;
for(i=margin; i<=gridsize-margin-1; i++)
{
for(j=margin; j<=gridsize-margin-1; j++)
{
v = ae_maxreal(v, ae_fabs(rbfcalc2(&s, (double)(i), (double)(j), _state), _state), _state);
}
}
ae_set_error_flag(&result, ae_fp_greater(v,threshold), __FILE__, __LINE__, "testrbfunit.ap:2376");
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Function for testing basic functionality of RBF module on regular grids with
multi-layer algorithm in 2-3D.
-- ALGLIB --
Copyright 2.03.2012 by Bochkanov Sergey
*************************************************************************/
static void testrbfunit_gridcalc23test(ae_bool* errorflag,
ae_state *_state)
{
ae_frame _frame_block;
rbfmodel s;
rbfreport rep;
hqrndstate rs;
ae_int_t pass;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t l;
double perturbation;
ae_vector kx;
double sx;
double sy;
ae_int_t nx;
ae_int_t ny;
ae_int_t linterm;
ae_int_t layers;
ae_int_t npoints;
ae_matrix xy;
ae_vector gf;
ae_vector rf;
ae_vector x0;
ae_vector x1;
ae_vector x2;
ae_vector gy;
ae_vector gy2;
ae_vector x;
ae_vector y;
double sparsity;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&rs, 0, sizeof(rs));
memset(&kx, 0, sizeof(kx));
memset(&xy, 0, sizeof(xy));
memset(&gf, 0, sizeof(gf));
memset(&rf, 0, sizeof(rf));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&x2, 0, sizeof(x2));
memset(&gy, 0, sizeof(gy));
memset(&gy2, 0, sizeof(gy2));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
_rbfmodel_init(&s, _state, ae_true);
_rbfreport_init(&rep, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
ae_vector_init(&kx, 0, DT_INT, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&gf, 0, DT_BOOL, _state, ae_true);
ae_vector_init(&rf, 0, DT_BOOL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&gy, 0, DT_REAL, _state, ae_true);
ae_vector_init(&gy2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
hqrndrandomize(&rs, _state);
for(pass=0; pass<=24; pass++)
{
/*
* prepare test problem
*/
ae_vector_set_length(&kx, 3, _state);
for(i=0; i<=2; i++)
{
/*
* 66% of cases - large grid
*/
if( hqrnduniformi(&rs, 3, _state)==0 )
{
kx.ptr.p_int[i] = ae_round(10*ae_pow((double)(10), hqrnduniformr(&rs, _state), _state), _state);
continue;
}
/*
* 33% of cases - small grid
*/
k = hqrnduniformi(&rs, 3, _state);
if( k==0 )
{
kx.ptr.p_int[i] = 1;
}
if( k==1 )
{
kx.ptr.p_int[i] = 2;
}
if( k==2 )
{
kx.ptr.p_int[i] = 10;
}
}
sx = ae_pow((double)(10), (double)(hqrnduniformi(&rs, 3, _state)-1), _state);
sy = ae_pow((double)(10), (double)(hqrnduniformi(&rs, 3, _state)-1), _state);
nx = 3;
ny = 1+hqrnduniformi(&rs, 5, _state);
linterm = hqrnduniformi(&rs, 3, _state)+1;
layers = hqrnduniformi(&rs, 3, _state)+1;
npoints = 100;
ae_matrix_set_length(&xy, npoints, nx+ny, _state);
for(i=0; i<=npoints-1; i++)
{
for(j=0; j<=nx-1; j++)
{
xy.ptr.pp_double[i][j] = hqrnduniformr(&rs, _state)*sx;
}
for(j=0; j<=ny-1; j++)
{
xy.ptr.pp_double[i][nx+j] = hqrnduniformr(&rs, _state)*sy;
}
}
/*
* Create RBF model
*/
rbfcreate(nx, ny, &s, _state);
rbfsetalgomultilayer(&s, 0.1*sx, layers, 0.0, _state);
if( linterm==1 )
{
rbfsetlinterm(&s, _state);
}
if( linterm==2 )
{
rbfsetconstterm(&s, _state);
}
if( linterm==3 )
{
rbfsetzeroterm(&s, _state);
}
rbfsetpoints(&s, &xy, npoints, _state);
rbfbuildmodel(&s, &rep, _state);
ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testrbfunit.ap:2473");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
/*
* Prepare test grid
*/
ae_vector_set_length(&x0, kx.ptr.p_int[0], _state);
for(i=0; i<=kx.ptr.p_int[0]-1; i++)
{
perturbation = 0.5*(hqrnduniformr(&rs, _state)-0.5);
x0.ptr.p_double[i] = sx*(i+perturbation)/kx.ptr.p_int[0];
}
ae_vector_set_length(&x1, kx.ptr.p_int[1], _state);
for(i=0; i<=kx.ptr.p_int[1]-1; i++)
{
perturbation = 0.5*(hqrnduniformr(&rs, _state)-0.5);
x1.ptr.p_double[i] = sx*(i+perturbation)/kx.ptr.p_int[1];
}
ae_vector_set_length(&x2, kx.ptr.p_int[2], _state);
for(i=0; i<=kx.ptr.p_int[2]-1; i++)
{
perturbation = 0.5*(hqrnduniformr(&rs, _state)-0.5);
x2.ptr.p_double[i] = sx*(i+perturbation)/kx.ptr.p_int[2];
}
/*
* Test calculation on grid
*/
ae_vector_set_length(&x, nx, _state);
ae_vector_set_length(&y, ny, _state);
unsetrealarray(&gy, _state);
rbfgridcalc3v(&s, &x0, kx.ptr.p_int[0], &x1, kx.ptr.p_int[1], &x2, kx.ptr.p_int[2], &gy, _state);
for(i=0; i<=kx.ptr.p_int[0]-1; i++)
{
for(j=0; j<=kx.ptr.p_int[1]-1; j++)
{
for(k=0; k<=kx.ptr.p_int[2]-1; k++)
{
x.ptr.p_double[0] = x0.ptr.p_double[i];
x.ptr.p_double[1] = x1.ptr.p_double[j];
x.ptr.p_double[2] = x2.ptr.p_double[k];
rbfcalcbuf(&s, &x, &y, _state);
for(l=0; l<=ny-1; l++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(y.ptr.p_double[l]-gy.ptr.p_double[l+ny*(i+j*kx.ptr.p_int[0]+k*kx.ptr.p_int[0]*kx.ptr.p_int[1])], _state),1.0E-9*sy), __FILE__, __LINE__, "testrbfunit.ap:2516");
}
}
}
}
/*
* Test calculation on subset of regular grid:
* * select sparsity coefficient (from 1.0 to 0.001)
* * fill bitmap array
* * Test 1: compare full and subset versions
* * Test 2: check sparsity. Subset function may perform additional
* evaluations because it processes data micro-row by micro-row.
* So, we can't check that all elements which were not flagged
* are zero - some of them may become non-zero. However, if entire
* row is empty, we can reasonably expect (informal guarantee)
* that it is not processed. So, we check empty (completely
* unflagged) rows
*
*/
sparsity = ae_pow((double)(10), (double)(-hqrnduniformi(&rs, 4, _state)), _state);
ae_vector_set_length(&gf, kx.ptr.p_int[0]*kx.ptr.p_int[1]*kx.ptr.p_int[2], _state);
ae_vector_set_length(&rf, kx.ptr.p_int[1]*kx.ptr.p_int[2], _state);
for(i=0; i<=kx.ptr.p_int[1]*kx.ptr.p_int[2]-1; i++)
{
rf.ptr.p_bool[i] = ae_false;
}
for(i=0; i<=kx.ptr.p_int[0]*kx.ptr.p_int[1]*kx.ptr.p_int[2]-1; i++)
{
gf.ptr.p_bool[i] = ae_fp_less(hqrnduniformr(&rs, _state),sparsity);
if( gf.ptr.p_bool[i] )
{
rf.ptr.p_bool[i/kx.ptr.p_int[0]] = ae_true;
}
}
ae_vector_set_length(&x, nx, _state);
ae_vector_set_length(&y, ny, _state);
unsetrealarray(&gy, _state);
unsetrealarray(&gy2, _state);
rbfgridcalc3vsubset(&s, &x0, kx.ptr.p_int[0], &x1, kx.ptr.p_int[1], &x2, kx.ptr.p_int[2], &gf, &gy, _state);
rbfgridcalc3v(&s, &x0, kx.ptr.p_int[0], &x1, kx.ptr.p_int[1], &x2, kx.ptr.p_int[2], &gy2, _state);
for(i=0; i<=ny*kx.ptr.p_int[0]*kx.ptr.p_int[1]*kx.ptr.p_int[2]-1; i++)
{
ae_set_error_flag(errorflag, gf.ptr.p_bool[i/ny]&&ae_fp_greater(ae_fabs(gy.ptr.p_double[i]-gy2.ptr.p_double[i], _state),1.0E-9*sy), __FILE__, __LINE__, "testrbfunit.ap:2558");
ae_set_error_flag(errorflag, !rf.ptr.p_bool[i/(ny*kx.ptr.p_int[0])]&&ae_fp_neq(gy.ptr.p_double[i],0.0), __FILE__, __LINE__, "testrbfunit.ap:2559");
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Function for testing basic functionality of RBF module with hierarchical
algorithm.
-- ALGLIB --
Copyright 20.06.2016 by Bochkanov Sergey
*************************************************************************/
static ae_bool testrbfunit_basichrbftest(ae_state *_state)
{
ae_frame _frame_block;
rbfmodel s;
rbfmodel s2;
rbfreport rep;
rbfcalcbuffer tsbuf;
ae_int_t nx;
ae_int_t ny;
ae_int_t linterm;
ae_int_t bf;
double rbase;
ae_int_t nlayers;
double errtol;
double scalefactor;
ae_matrix xy;
ae_matrix xytest;
ae_matrix uxwr;
ae_matrix uv;
ae_matrix xy2;
ae_vector x;
ae_vector y;
ae_vector y2;
ae_vector xzero;
ae_vector yref;
ae_vector scalevec;
ae_int_t n;
ae_int_t ntest;
ae_int_t gridsize;
ae_int_t i;
ae_int_t j;
ae_int_t k;
double r0;
ae_int_t margin;
double threshold;
double v;
ae_int_t functype;
ae_int_t densitytype;
double width;
double lowprec;
double highprec;
ae_int_t modeltype;
ae_int_t shaketype;
double maxerr;
ae_bool fractionalerror;
ae_int_t unx;
ae_int_t uny;
ae_int_t unc;
ae_int_t modelversion;
ae_bool hasscale;
hqrndstate rs;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&s2, 0, sizeof(s2));
memset(&rep, 0, sizeof(rep));
memset(&tsbuf, 0, sizeof(tsbuf));
memset(&xy, 0, sizeof(xy));
memset(&xytest, 0, sizeof(xytest));
memset(&uxwr, 0, sizeof(uxwr));
memset(&uv, 0, sizeof(uv));
memset(&xy2, 0, sizeof(xy2));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&y2, 0, sizeof(y2));
memset(&xzero, 0, sizeof(xzero));
memset(&yref, 0, sizeof(yref));
memset(&scalevec, 0, sizeof(scalevec));
memset(&rs, 0, sizeof(rs));
_rbfmodel_init(&s, _state, ae_true);
_rbfmodel_init(&s2, _state, ae_true);
_rbfreport_init(&rep, _state, ae_true);
_rbfcalcbuffer_init(&tsbuf, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xytest, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&uxwr, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&uv, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xzero, 0, DT_REAL, _state, ae_true);
ae_vector_init(&yref, 0, DT_REAL, _state, ae_true);
ae_vector_init(&scalevec, 0, DT_REAL, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
result = ae_false;
/*
* First test - random problem, ability to build model
* which reproduces function value in all points with
* good precision.
*
* We also test properties of the linear term - that
* model value in far away points is either constant
* or exactly zero (for corresponding kinds of linear
* term).
*
* All dataset points are located in unit cube on
* regular grid. We do not use smoothing for this test.
*
* We use/test following functions:
* * RBFCalc()
* * RBFCalc2()
* * RBFCalc3()
* * RBFCalcBuf()
* * RBFTsCalcBuf()
*/
errtol = 1.0E-6;
for(nx=1; nx<=4; nx++)
{
for(ny=1; ny<=3; ny++)
{
/*
* problem setup
*/
n = 150;
rbase = 0.33;
nlayers = 10;
gridsize = ae_round(ae_pow((double)(n), (double)1/(double)nx, _state), _state)+1;
linterm = 1+ae_randominteger(3, _state);
bf = ae_randominteger(2, _state);
n = ae_round(ae_pow((double)(gridsize), (double)(nx), _state), _state);
ae_matrix_set_length(&xy, n, nx+ny, _state);
ae_assert(gridsize>1, "Assertion failed", _state);
ae_assert(ae_fp_eq((double)(n),ae_pow((double)(gridsize), (double)(nx), _state)), "Assertion failed", _state);
for(i=0; i<=n-1; i++)
{
k = i;
for(j=0; j<=nx-1; j++)
{
xy.ptr.pp_double[i][j] = (double)(k%gridsize)/(double)(gridsize-1);
k = k/gridsize;
}
for(j=0; j<=ny-1; j++)
{
xy.ptr.pp_double[i][nx+j] = ae_randomreal(_state)-0.5;
}
}
/*
* Build model
*/
rbfcreate(nx, ny, &s, _state);
rbfsetv2bf(&s, bf, _state);
rbfsetalgohierarchical(&s, rbase, nlayers, 0.0, _state);
if( linterm==1 )
{
rbfsetlinterm(&s, _state);
}
if( linterm==2 )
{
rbfsetconstterm(&s, _state);
}
if( linterm==3 )
{
rbfsetzeroterm(&s, _state);
}
rbfsetpoints(&s, &xy, n, _state);
rbfbuildmodel(&s, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:2683");
ae_frame_leave(_state);
return result;
}
rbfcreatecalcbuffer(&s, &tsbuf, _state);
/*
* Test ability to reproduce function value
*
* NOTE: we use RBFCalc(XZero) to guarantee that internal state of
* RBF model is "reset" between subsequent calls of different
* functions. It allows us to make sure that we have no bug
* like function simply returning latest result
*/
ae_vector_set_length(&x, nx, _state);
ae_vector_set_length(&xzero, nx, _state);
ae_vector_set_length(&y, ny, _state);
for(j=0; j<=nx-1; j++)
{
xzero.ptr.p_double[j] = (double)(0);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=nx-1; j++)
{
x.ptr.p_double[j] = xy.ptr.pp_double[i][j];
}
rbfcalc(&s, &xzero, &y, _state);
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
ae_vector_set_length(&yref, ny+1, _state);
}
rbfcalc(&s, &x, &yref, _state);
for(j=0; j<=ny-1; j++)
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(yref.ptr.p_double[j]-xy.ptr.pp_double[i][nx+j], _state),errtol), __FILE__, __LINE__, "testrbfunit.ap:2712");
}
ae_set_error_flag(&result, yref.cnt!=ny, __FILE__, __LINE__, "testrbfunit.ap:2713");
if( nx==1&&ny==1 )
{
rbfcalc(&s, &xzero, &y, _state);
ae_set_error_flag(&result, ae_fp_neq(rbfcalc1(&s, x.ptr.p_double[0], _state),yref.ptr.p_double[0]), __FILE__, __LINE__, "testrbfunit.ap:2719");
}
if( nx==2&&ny==1 )
{
rbfcalc(&s, &xzero, &y, _state);
ae_set_error_flag(&result, ae_fp_neq(rbfcalc2(&s, x.ptr.p_double[0], x.ptr.p_double[1], _state),yref.ptr.p_double[0]), __FILE__, __LINE__, "testrbfunit.ap:2726");
}
if( nx==3&&ny==1 )
{
rbfcalc(&s, &xzero, &y, _state);
ae_set_error_flag(&result, ae_fp_neq(rbfcalc3(&s, x.ptr.p_double[0], x.ptr.p_double[1], x.ptr.p_double[2], _state),yref.ptr.p_double[0]), __FILE__, __LINE__, "testrbfunit.ap:2733");
}
rbfcalc(&s, &xzero, &y, _state);
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
ae_vector_set_length(&y, ny+1, _state);
rbfcalcbuf(&s, &x, &y, _state);
ae_set_error_flag(&result, y.cnt!=ny+1, __FILE__, __LINE__, "testrbfunit.ap:2742");
}
else
{
ae_vector_set_length(&y, ny-1, _state);
rbfcalcbuf(&s, &x, &y, _state);
ae_set_error_flag(&result, y.cnt!=ny, __FILE__, __LINE__, "testrbfunit.ap:2748");
}
for(j=0; j<=ny-1; j++)
{
ae_set_error_flag(&result, ae_fp_neq(y.ptr.p_double[j],yref.ptr.p_double[j]), __FILE__, __LINE__, "testrbfunit.ap:2751");
}
rbfcalc(&s, &xzero, &y, _state);
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
ae_vector_set_length(&y, ny+1, _state);
rbftscalcbuf(&s, &tsbuf, &x, &y, _state);
ae_set_error_flag(&result, y.cnt!=ny+1, __FILE__, __LINE__, "testrbfunit.ap:2759");
}
else
{
ae_vector_set_length(&y, ny-1, _state);
rbftscalcbuf(&s, &tsbuf, &x, &y, _state);
ae_set_error_flag(&result, y.cnt!=ny, __FILE__, __LINE__, "testrbfunit.ap:2765");
}
for(j=0; j<=ny-1; j++)
{
ae_set_error_flag(&result, ae_fp_neq(y.ptr.p_double[j],yref.ptr.p_double[j]), __FILE__, __LINE__, "testrbfunit.ap:2768");
}
}
/*
* Test that:
* a) model with zero linear term is zero far away from dataset
* b) model with constant linear term is constant far away from dataset
*/
ae_vector_set_length(&x, nx, _state);
if( linterm==2 )
{
for(j=0; j<=nx-1; j++)
{
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
x.ptr.p_double[j] = 1+1000*rbase;
}
else
{
x.ptr.p_double[j] = 0-1000*rbase;
}
}
rbfcalc(&s, &x, &y, _state);
for(j=0; j<=nx-1; j++)
{
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
x.ptr.p_double[j] = 1+1000*rbase;
}
else
{
x.ptr.p_double[j] = 0-1000*rbase;
}
}
rbfcalc(&s, &x, &y2, _state);
for(j=0; j<=ny-1; j++)
{
ae_set_error_flag(&result, ae_fp_neq(y.ptr.p_double[j],y2.ptr.p_double[j]), __FILE__, __LINE__, "testrbfunit.ap:2792");
}
}
if( linterm==3 )
{
for(j=0; j<=nx-1; j++)
{
if( ae_fp_greater(ae_randomreal(_state),0.5) )
{
x.ptr.p_double[j] = 1+1000*rbase;
}
else
{
x.ptr.p_double[j] = 0-1000*rbase;
}
}
rbfcalc(&s, &x, &y, _state);
for(j=0; j<=ny-1; j++)
{
ae_set_error_flag(&result, ae_fp_neq(y.ptr.p_double[j],(double)(0)), __FILE__, __LINE__, "testrbfunit.ap:2803");
}
}
}
}
/*
* Test rbfunpack()
*/
for(nx=1; nx<=2; nx++)
{
for(ny=1; ny<=2; ny++)
{
/*
* problem setup
*/
n = 150;
rbase = 0.33;
nlayers = 5;
gridsize = ae_round(ae_pow((double)(n), (double)1/(double)nx, _state), _state)+1;
linterm = 1+ae_randominteger(3, _state);
bf = ae_randominteger(2, _state);
n = ae_round(ae_pow((double)(gridsize), (double)(nx), _state), _state);
ae_matrix_set_length(&xy, n, nx+ny, _state);
ae_assert(gridsize>1, "Assertion failed", _state);
ae_assert(ae_fp_eq((double)(n),ae_pow((double)(gridsize), (double)(nx), _state)), "Assertion failed", _state);
for(i=0; i<=n-1; i++)
{
k = i;
for(j=0; j<=nx-1; j++)
{
xy.ptr.pp_double[i][j] = (double)(k%gridsize)/(double)(gridsize-1);
k = k/gridsize;
}
for(j=0; j<=ny-1; j++)
{
xy.ptr.pp_double[i][nx+j] = ae_randomreal(_state)-0.5;
}
}
hasscale = ae_randominteger(2, _state)==0;
ae_vector_set_length(&scalevec, nx, _state);
if( hasscale )
{
for(j=0; j<=nx-1; j++)
{
scalevec.ptr.p_double[j] = ae_pow((double)(2), 2*ae_randomreal(_state)-1, _state);
}
}
/*
* Build model
*/
rbfcreate(nx, ny, &s, _state);
rbfsetv2bf(&s, bf, _state);
rbfsetalgohierarchical(&s, rbase, nlayers, 0.0, _state);
if( linterm==1 )
{
rbfsetlinterm(&s, _state);
}
if( linterm==2 )
{
rbfsetconstterm(&s, _state);
}
if( linterm==3 )
{
rbfsetzeroterm(&s, _state);
}
if( hasscale )
{
rbfsetpointsandscales(&s, &xy, n, &scalevec, _state);
}
else
{
rbfsetpoints(&s, &xy, n, _state);
}
rbfbuildmodel(&s, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:2864");
ae_frame_leave(_state);
return result;
}
/*
* Test RBFUnpack()
*/
rbfunpack(&s, &unx, &uny, &uxwr, &unc, &uv, &modelversion, _state);
if( modelversion!=2 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:2874");
ae_frame_leave(_state);
return result;
}
if( unx!=nx||uny!=ny )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:2879");
ae_frame_leave(_state);
return result;
}
if( uv.cols!=nx+1||uv.rows!=ny )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:2884");
ae_frame_leave(_state);
return result;
}
if( linterm==2 )
{
for(i=0; i<=ny-1; i++)
{
for(j=0; j<=nx-1; j++)
{
ae_set_error_flag(&result, ae_fp_neq(uv.ptr.pp_double[i][j],(double)(0)), __FILE__, __LINE__, "testrbfunit.ap:2891");
}
}
}
if( linterm==3 )
{
for(i=0; i<=ny-1; i++)
{
for(j=0; j<=nx; j++)
{
ae_set_error_flag(&result, ae_fp_neq(uv.ptr.pp_double[i][j],(double)(0)), __FILE__, __LINE__, "testrbfunit.ap:2897");
}
}
}
ae_vector_set_length(&x, nx, _state);
ae_vector_set_length(&y, ny, _state);
for(i=0; i<=9; i++)
{
for(j=0; j<=nx-1; j++)
{
x.ptr.p_double[j] = ae_randomreal(_state);
}
rbfcalc(&s, &x, &yref, _state);
for(j=0; j<=ny-1; j++)
{
y.ptr.p_double[j] = uv.ptr.pp_double[j][nx];
for(k=0; k<=nx-1; k++)
{
y.ptr.p_double[j] = y.ptr.p_double[j]+x.ptr.p_double[k]*uv.ptr.pp_double[j][k];
}
}
for(k=0; k<=unc-1; k++)
{
v = (double)(0);
for(j=0; j<=nx-1; j++)
{
v = v+ae_sqr(uxwr.ptr.pp_double[k][j]-x.ptr.p_double[j], _state)/ae_sqr(uxwr.ptr.pp_double[k][nx+ny+j], _state);
}
if( ae_fp_less(v,rbfv2farradius(bf, _state)*rbfv2farradius(bf, _state)) )
{
v = rbfv2basisfunc(bf, v, _state);
}
else
{
v = (double)(0);
}
for(j=0; j<=ny-1; j++)
{
y.ptr.p_double[j] = y.ptr.p_double[j]+v*uxwr.ptr.pp_double[k][nx+j];
}
}
for(j=0; j<=ny-1; j++)
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(y.ptr.p_double[j]-yref.ptr.p_double[j], _state),1.0E-9), __FILE__, __LINE__, "testrbfunit.ap:2932");
}
}
}
}
/*
* Test that smooth 1D function is reproduced (between nodes)
* with good precision. We test two model types: model with
* three layers and moderate initial radius, and model with
* large initial radius and large number of layers.
*
* This test:
* * generates test function on [-Width,+Width]. Two sets of
* nodes are generated - "model" ones and "test" ones.
* * builds RBF model using "model" dataset
* * test model using "test" dataset. Test points are more
* dense and are spread in [-0.9*Width, +0.9*Width] (reduced
* interval is used because RBF models are too bad near the
* boundaries).
*
* NOTE: we calculate maximum error for given function type
* and grid density over all modifications of the task,
* and only after that we perform comparison with tolerance
* level. It allows easier debugging.
*/
for(functype=0; functype<=2; functype++)
{
for(densitytype=0; densitytype<=1; densitytype++)
{
/*
* Select tolerance
*/
lowprec = (double)(-999999);
highprec = (double)(-999999);
if( functype==0 )
{
lowprec = 1.0E-2;
highprec = 1.0E-3;
}
else
{
if( functype==1 )
{
lowprec = 1.0E-1;
highprec = 1.0E-2;
}
else
{
if( functype==2 )
{
lowprec = 1.0E-3;
highprec = 1.0E-4;
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
if( densitytype==0 )
{
errtol = lowprec;
}
else
{
errtol = highprec;
}
/*
* Test
*/
maxerr = (double)(0);
for(modeltype=0; modeltype<=1; modeltype++)
{
for(shaketype=0; shaketype<=1; shaketype++)
{
/*
* Generate grid
*/
width = (double)(1);
fractionalerror = ae_false;
if( functype==0 )
{
/*
* sin(x) on [-2*pi,+2*pi]
*/
n = 17*ae_round(ae_pow((double)(4), (double)(densitytype), _state), _state);
width = ae_pi;
fractionalerror = ae_false;
}
else
{
if( functype==1 )
{
/*
* exp(x) on [-3,+3]
*/
n = 50*ae_round(ae_pow((double)(4), (double)(densitytype), _state), _state);
width = (double)(3);
fractionalerror = ae_true;
}
else
{
if( functype==2 )
{
/*
* 1/(1+x^2) on [-3,+3]
*/
n = 20*ae_round(ae_pow((double)(4), (double)(densitytype), _state), _state);
width = (double)(3);
fractionalerror = ae_false;
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
ae_matrix_set_length(&xy, n, 2, _state);
for(i=0; i<=n-1; i++)
{
v = shaketype*0.25*(ae_randomreal(_state)-0.5);
v = (i+v)/(n-1);
v = 2*v-1;
xy.ptr.pp_double[i][0] = width*v;
}
ntest = n*10;
ae_matrix_set_length(&xytest, ntest, 2, _state);
for(i=0; i<=ntest-1; i++)
{
xytest.ptr.pp_double[i][0] = 0.9*width*((double)(2*i)/(double)(ntest-1)-1);
}
/*
* Evaluate function
*/
if( functype==0 )
{
/*
* sin(x)
*/
for(i=0; i<=n-1; i++)
{
xy.ptr.pp_double[i][1] = ae_sin(xy.ptr.pp_double[i][0], _state);
}
for(i=0; i<=ntest-1; i++)
{
xytest.ptr.pp_double[i][1] = ae_sin(xytest.ptr.pp_double[i][0], _state);
}
}
else
{
if( functype==1 )
{
/*
* exp(x)
*/
for(i=0; i<=n-1; i++)
{
xy.ptr.pp_double[i][1] = ae_exp(xy.ptr.pp_double[i][0], _state);
}
for(i=0; i<=ntest-1; i++)
{
xytest.ptr.pp_double[i][1] = ae_exp(xytest.ptr.pp_double[i][0], _state);
}
}
else
{
if( functype==2 )
{
/*
* 1/(1+x^2)
*/
for(i=0; i<=n-1; i++)
{
xy.ptr.pp_double[i][1] = 1/(1+ae_sqr(xy.ptr.pp_double[i][0], _state));
}
for(i=0; i<=ntest-1; i++)
{
xytest.ptr.pp_double[i][1] = 1/(1+ae_sqr(xytest.ptr.pp_double[i][0], _state));
}
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
}
/*
* Select model properties and precision
*/
if( modeltype==0 )
{
rbase = 4.0*(2*width/n);
nlayers = 3;
}
else
{
if( modeltype==1 )
{
rbase = 16.0*(2*width/n);
nlayers = 6;
}
else
{
ae_assert(ae_false, "Assertion failed", _state);
}
}
/*
* Build model
*/
bf = ae_randominteger(2, _state);
rbfcreate(1, 1, &s, _state);
rbfsetv2bf(&s, bf, _state);
rbfsetalgohierarchical(&s, rbase, nlayers, 0.0, _state);
rbfsetpoints(&s, &xy, n, _state);
rbfbuildmodel(&s, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3106");
ae_frame_leave(_state);
return result;
}
/*
* Check
*/
ae_vector_set_length(&x, 1, _state);
for(i=0; i<=ntest-1; i++)
{
x.ptr.p_double[0] = xytest.ptr.pp_double[i][0];
rbfcalc(&s, &x, &y, _state);
if( fractionalerror )
{
maxerr = ae_maxreal(maxerr, ae_fabs(y.ptr.p_double[0]-xytest.ptr.pp_double[i][1], _state)/ae_fabs(xytest.ptr.pp_double[i][1], _state), _state);
}
else
{
maxerr = ae_maxreal(maxerr, ae_fabs(y.ptr.p_double[0]-xytest.ptr.pp_double[i][1], _state), _state);
}
}
}
}
/*
* Check error
*/
ae_set_error_flag(&result, ae_fp_greater(maxerr,errtol), __FILE__, __LINE__, "testrbfunit.ap:3128");
}
}
/*
* Scaling test - random problem, we test that after
* scaling of all variables and radius by 2^K (for some K)
* we will get exactly same results (up to the last bit of
* mantissa).
*
* It is very strong requirement for algorithm stability,
* but it is satisfiable in most implementations of RBFs,
* because all operations involving spatial values are usually
* followed by division by radius, and using multiplier which
* is exactly power of 2 results in no changes in numbers
* being returned.
*
* It allows to test different scale-related bugs
* (say, situation when deep in kd-tree search code we compare
* against R instead of R^2).
*
* All dataset points are located in unit cube on
* regular grid.
*
* We do not use smoothing for this test.
*/
for(nx=1; nx<=4; nx++)
{
/*
* problem setup
*/
n = 150;
rbase = 0.33;
nlayers = ae_randominteger(4, _state);
scalefactor = ae_pow((double)(1024), (double)(2*ae_randominteger(2, _state)-1), _state);
gridsize = ae_round(ae_pow((double)(n), (double)1/(double)nx, _state), _state)+1;
ny = 1+ae_randominteger(3, _state);
linterm = 1+ae_randominteger(3, _state);
bf = ae_randominteger(2, _state);
n = ae_round(ae_pow((double)(gridsize), (double)(nx), _state), _state);
ae_matrix_set_length(&xy, n, nx+ny, _state);
ae_matrix_set_length(&xy2, n, nx+ny, _state);
ae_assert(gridsize>1, "Assertion failed", _state);
ae_assert(ae_fp_eq((double)(n),ae_pow((double)(gridsize), (double)(nx), _state)), "Assertion failed", _state);
for(i=0; i<=n-1; i++)
{
k = i;
for(j=0; j<=nx-1; j++)
{
xy.ptr.pp_double[i][j] = (double)(k%gridsize)/(double)(gridsize-1);
xy2.ptr.pp_double[i][j] = xy.ptr.pp_double[i][j]*scalefactor;
k = k/gridsize;
}
for(j=0; j<=ny-1; j++)
{
xy.ptr.pp_double[i][nx+j] = ae_randomreal(_state)-0.5;
xy2.ptr.pp_double[i][nx+j] = xy.ptr.pp_double[i][nx+j];
}
}
/*
* Build model 1
*/
rbfcreate(nx, ny, &s, _state);
rbfsetv2bf(&s, bf, _state);
rbfsetalgohierarchical(&s, rbase, nlayers, 0.0, _state);
if( linterm==1 )
{
rbfsetlinterm(&s, _state);
}
if( linterm==2 )
{
rbfsetconstterm(&s, _state);
}
if( linterm==3 )
{
rbfsetzeroterm(&s, _state);
}
rbfsetpoints(&s, &xy, n, _state);
rbfbuildmodel(&s, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3204");
ae_frame_leave(_state);
return result;
}
/*
* Build model 2
*/
rbfcreate(nx, ny, &s2, _state);
rbfsetv2bf(&s2, bf, _state);
rbfsetalgohierarchical(&s2, rbase*scalefactor, nlayers, 0.0, _state);
if( linterm==1 )
{
rbfsetlinterm(&s2, _state);
}
if( linterm==2 )
{
rbfsetconstterm(&s2, _state);
}
if( linterm==3 )
{
rbfsetzeroterm(&s2, _state);
}
rbfsetpoints(&s2, &xy2, n, _state);
rbfbuildmodel(&s2, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3224");
ae_frame_leave(_state);
return result;
}
/*
* Compare models
*/
ae_vector_set_length(&x, nx, _state);
ae_vector_set_length(&y, ny, _state);
ae_vector_set_length(&y2, ny, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=nx-1; j++)
{
x.ptr.p_double[j] = xy.ptr.pp_double[i][j];
}
rbfcalc(&s, &x, &y, _state);
for(j=0; j<=nx-1; j++)
{
x.ptr.p_double[j] = xy2.ptr.pp_double[i][j];
}
rbfcalc(&s2, &x, &y2, _state);
for(j=0; j<=ny-1; j++)
{
ae_set_error_flag(&result, ae_fp_neq(y.ptr.p_double[j],y2.ptr.p_double[j]), __FILE__, __LINE__, "testrbfunit.ap:3243");
}
}
}
/*
* Test that passing scaled dataset automatically results in V2 model
* being built (even when algorithm type is not set explicitly).
*/
for(nx=1; nx<=4; nx++)
{
for(ny=1; ny<=3; ny++)
{
/*
* problem setup
*/
n = 10;
ae_matrix_set_length(&xy, n, nx+ny, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=nx+ny-1; j++)
{
xy.ptr.pp_double[i][j] = ae_randomreal(_state)-0.5;
}
}
ae_vector_set_length(&scalevec, nx, _state);
for(j=0; j<=nx-1; j++)
{
scalevec.ptr.p_double[j] = ae_pow((double)(2), 2*ae_randomreal(_state)-1, _state);
}
/*
* prepare test problem
*/
rbfcreate(nx, ny, &s, _state);
rbfsetpointsandscales(&s, &xy, xy.rows, &scalevec, _state);
/*
* Build model, check model version
*/
rbfbuildmodel(&s, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3279");
ae_frame_leave(_state);
return result;
}
ae_set_error_flag(&result, rbfgetmodelversion(&s, _state)!=2, __FILE__, __LINE__, "testrbfunit.ap:3282");
}
}
/*
* Test smoothing properties of RBF model: model with just one layer
* and large initial radius will produce "average" value of neighbors.
*
* In order to test it we create regular grid, fill it with regular
* +1/-1 pattern, and test model values in the inner points. Model
* values should be around zero (we use handcrafted threshold to test
* it). Radius is chosen to be several times larger than grid step.
*
* We perform test for 2D model, because same behavior is expected
* regardless of dimensionality.
*/
r0 = (double)(6);
margin = 10;
threshold = 0.005;
gridsize = 2*margin+10;
nx = 2;
ny = 1;
for(bf=0; bf<=1; bf++)
{
rbfcreate(nx, ny, &s, _state);
rbfsetv2bf(&s, bf, _state);
rbfsetalgohierarchical(&s, r0, 1, 1.0E-1, _state);
rbfsetzeroterm(&s, _state);
ae_matrix_set_length(&xy, gridsize*gridsize, nx+ny, _state);
for(i=0; i<=gridsize-1; i++)
{
for(j=0; j<=gridsize-1; j++)
{
xy.ptr.pp_double[i*gridsize+j][0] = (double)(i);
xy.ptr.pp_double[i*gridsize+j][1] = (double)(j);
xy.ptr.pp_double[i*gridsize+j][2] = 0.01*(ae_randomreal(_state)-0.5)+(2*((i+j)%2)-1);
}
}
rbfsetpoints(&s, &xy, gridsize*gridsize, _state);
rbfbuildmodel(&s, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3322");
ae_frame_leave(_state);
return result;
}
v = 0.0;
for(i=margin; i<=gridsize-margin-1; i++)
{
for(j=margin; j<=gridsize-margin-1; j++)
{
v = ae_maxreal(v, ae_fabs(rbfcalc2(&s, (double)(i), (double)(j), _state), _state), _state);
}
}
ae_set_error_flag(&result, ae_fp_greater(v,threshold), __FILE__, __LINE__, "testrbfunit.ap:3329");
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Function for testing scaling-related functionality of RBF module with
hierarchical algorithm.
Returns True on failure (error flag is set).
-- ALGLIB --
Copyright 20.06.2016 by Bochkanov Sergey
*************************************************************************/
static ae_bool testrbfunit_scaledhrbftest(ae_state *_state)
{
ae_frame _frame_block;
rbfmodel s;
rbfmodel s2;
rbfreport rep;
rbfcalcbuffer tsbuf;
ae_int_t nx;
ae_int_t ny;
ae_int_t linterm;
ae_int_t bf;
double rbase;
ae_int_t nlayers;
double errtol;
ae_matrix xy;
ae_matrix xy2;
ae_vector x;
ae_vector y;
ae_vector y2;
ae_vector xzero;
ae_vector yref;
ae_vector scalex;
ae_vector scaley;
ae_vector c0;
ae_vector c1;
ae_int_t n;
ae_int_t gridsize;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t strictness;
double lambdav;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&s2, 0, sizeof(s2));
memset(&rep, 0, sizeof(rep));
memset(&tsbuf, 0, sizeof(tsbuf));
memset(&xy, 0, sizeof(xy));
memset(&xy2, 0, sizeof(xy2));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&y2, 0, sizeof(y2));
memset(&xzero, 0, sizeof(xzero));
memset(&yref, 0, sizeof(yref));
memset(&scalex, 0, sizeof(scalex));
memset(&scaley, 0, sizeof(scaley));
memset(&c0, 0, sizeof(c0));
memset(&c1, 0, sizeof(c1));
_rbfmodel_init(&s, _state, ae_true);
_rbfmodel_init(&s2, _state, ae_true);
_rbfreport_init(&rep, _state, ae_true);
_rbfcalcbuffer_init(&tsbuf, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xzero, 0, DT_REAL, _state, ae_true);
ae_vector_init(&yref, 0, DT_REAL, _state, ae_true);
ae_vector_init(&scalex, 0, DT_REAL, _state, ae_true);
ae_vector_init(&scaley, 0, DT_REAL, _state, ae_true);
ae_vector_init(&c0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&c1, 0, DT_REAL, _state, ae_true);
result = ae_false;
/*
* First test - random problem, test that using scaling
* does not change model significantly (except for
* rounding-related errors).
*
* We test two kinds of scaling:
* * "strict", which is scaling by some power of 2, and
* which should result in bit-to-bit equivalence of results
* * "non-strict", which is scaling by random number, and
* which should result in approximate equivalence
*
* We also apply scaling to Y, in order to test that it
* is correctly handled too.
*/
for(strictness=0; strictness<=1; strictness++)
{
for(nx=1; nx<=2; nx++)
{
for(ny=1; ny<=2; ny++)
{
/*
* problem setup
*/
if( strictness==1 )
{
errtol = (double)(0);
ae_vector_set_length(&scalex, nx, _state);
for(i=0; i<=nx-1; i++)
{
scalex.ptr.p_double[i] = ae_pow((double)(16), (double)(ae_randominteger(3, _state)-1), _state);
}
ae_vector_set_length(&scaley, ny, _state);
for(i=0; i<=ny-1; i++)
{
scaley.ptr.p_double[i] = ae_pow((double)(16), (double)(ae_randominteger(3, _state)-1), _state);
}
}
else
{
errtol = 1.0E-3;
ae_vector_set_length(&scalex, nx, _state);
for(i=0; i<=nx-1; i++)
{
scalex.ptr.p_double[i] = ae_pow((double)(4), 2*ae_randomreal(_state)-1, _state);
}
ae_vector_set_length(&scaley, ny, _state);
for(i=0; i<=ny-1; i++)
{
scaley.ptr.p_double[i] = ae_pow((double)(4), 2*ae_randomreal(_state)-1, _state);
}
}
n = 150;
rbase = 0.33;
nlayers = 2;
gridsize = ae_round(ae_pow((double)(n), (double)1/(double)nx, _state), _state)+1;
linterm = 1+ae_randominteger(3, _state);
bf = ae_randominteger(2, _state);
lambdav = 1.0E-3*ae_randominteger(2, _state);
n = ae_round(ae_pow((double)(gridsize), (double)(nx), _state), _state);
ae_matrix_set_length(&xy, n, nx+ny, _state);
ae_assert(gridsize>1, "Assertion failed", _state);
ae_assert(ae_fp_eq((double)(n),ae_pow((double)(gridsize), (double)(nx), _state)), "Assertion failed", _state);
ae_vector_set_length(&c0, nx, _state);
for(j=0; j<=nx-1; j++)
{
c0.ptr.p_double[j] = ae_randomreal(_state)-0.5;
}
ae_vector_set_length(&c1, ny, _state);
for(j=0; j<=ny-1; j++)
{
c1.ptr.p_double[j] = ae_randomreal(_state)-0.5;
}
for(i=0; i<=n-1; i++)
{
k = i;
for(j=0; j<=nx-1; j++)
{
xy.ptr.pp_double[i][j] = (double)(k%gridsize)/(double)(gridsize-1);
k = k/gridsize;
}
for(j=0; j<=ny-1; j++)
{
xy.ptr.pp_double[i][nx+j] = (double)(0);
for(k=0; k<=nx-1; k++)
{
xy.ptr.pp_double[i][nx+j] = xy.ptr.pp_double[i][nx+j]+c0.ptr.p_double[k]*ae_cos(ae_pi*(1+k)*xy.ptr.pp_double[i][k], _state);
}
xy.ptr.pp_double[i][nx+j] = c1.ptr.p_double[j]*xy.ptr.pp_double[i][nx+j];
}
}
ae_matrix_set_length(&xy2, n, nx+ny, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=nx-1; j++)
{
xy2.ptr.pp_double[i][j] = xy.ptr.pp_double[i][j]*scalex.ptr.p_double[j];
}
for(j=0; j<=ny-1; j++)
{
xy2.ptr.pp_double[i][nx+j] = xy.ptr.pp_double[i][nx+j]*scaley.ptr.p_double[j];
}
}
/*
* Build models
*/
rbfcreate(nx, ny, &s, _state);
rbfsetv2bf(&s, bf, _state);
rbfsetalgohierarchical(&s, rbase, nlayers, lambdav, _state);
if( linterm==1 )
{
rbfsetlinterm(&s, _state);
}
if( linterm==2 )
{
rbfsetconstterm(&s, _state);
}
if( linterm==3 )
{
rbfsetzeroterm(&s, _state);
}
rbfsetpoints(&s, &xy, n, _state);
rbfbuildmodel(&s, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3472");
ae_frame_leave(_state);
return result;
}
rbfcreate(nx, ny, &s2, _state);
rbfsetv2bf(&s2, bf, _state);
rbfsetalgohierarchical(&s2, rbase, nlayers, lambdav, _state);
if( linterm==1 )
{
rbfsetlinterm(&s2, _state);
}
if( linterm==2 )
{
rbfsetconstterm(&s2, _state);
}
if( linterm==3 )
{
rbfsetzeroterm(&s2, _state);
}
rbfsetpointsandscales(&s2, &xy2, n, &scalex, _state);
rbfbuildmodel(&s2, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3488");
ae_frame_leave(_state);
return result;
}
/*
* Compare model values in grid points
*/
ae_vector_set_length(&x, nx, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=nx-1; j++)
{
x.ptr.p_double[j] = xy.ptr.pp_double[i][j];
}
rbfcalc(&s, &x, &y, _state);
for(j=0; j<=nx-1; j++)
{
x.ptr.p_double[j] = xy2.ptr.pp_double[i][j];
}
rbfcalc(&s2, &x, &y2, _state);
for(j=0; j<=ny-1; j++)
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(y.ptr.p_double[j]-y2.ptr.p_double[j]/scaley.ptr.p_double[j], _state),errtol), __FILE__, __LINE__, "testrbfunit.ap:3505");
}
}
/*
* Compare model values in random points
*/
ae_vector_set_length(&x, nx, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=nx-1; j++)
{
x.ptr.p_double[j] = ae_randomreal(_state);
}
rbfcalc(&s, &x, &y, _state);
for(j=0; j<=nx-1; j++)
{
x.ptr.p_double[j] = x.ptr.p_double[j]*scalex.ptr.p_double[j];
}
rbfcalc(&s2, &x, &y2, _state);
for(j=0; j<=ny-1; j++)
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(y.ptr.p_double[j]-y2.ptr.p_double[j]/scaley.ptr.p_double[j], _state),errtol), __FILE__, __LINE__, "testrbfunit.ap:3521");
}
}
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Test special properties of hierarchical RBFs.
Returns True on errors.
-- ALGLIB --
Copyright 20.06.2016 by Bochkanov Sergey
*************************************************************************/
static ae_bool testrbfunit_spechrbftest(ae_state *_state)
{
ae_frame _frame_block;
ae_int_t n;
ae_int_t nx;
ae_int_t ny;
double rbase;
rbfmodel s0;
rbfmodel s1;
rbfreport rep;
ae_int_t nlayers;
ae_matrix xy;
ae_int_t i;
ae_int_t j;
double vdiff;
double d2;
ae_int_t v2its;
hqrndstate rs;
double vref;
double vfunc;
double maxerr;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s0, 0, sizeof(s0));
memset(&s1, 0, sizeof(s1));
memset(&rep, 0, sizeof(rep));
memset(&xy, 0, sizeof(xy));
memset(&rs, 0, sizeof(rs));
_rbfmodel_init(&s0, _state, ae_true);
_rbfmodel_init(&s1, _state, ae_true);
_rbfreport_init(&rep, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
hqrndrandomize(&rs, _state);
result = ae_false;
/*
* Test properties of RBF basis functions - we compare values
* returned by RBFV2BasisFunc() against analytic expressions
* which are approximately modeled by RBFV2BasisFunc().
*/
d2 = 0.0;
while(ae_fp_less(d2,100.0))
{
vref = ae_exp(-d2, _state);
vfunc = rbfv2basisfunc(0, d2, _state);
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vref-vfunc, _state),1.0E-9*vref), __FILE__, __LINE__, "testrbfunit.ap:3563");
d2 = d2+(double)1/(double)64;
}
d2 = 0.0;
maxerr = 0.0;
while(ae_fp_less(d2,16.0))
{
vref = ae_maxreal(1-d2/9, (double)(0), _state)*ae_exp(-d2, _state);
vfunc = rbfv2basisfunc(1, d2, _state);
maxerr = ae_maxreal(maxerr, ae_fabs(vref-vfunc, _state), _state);
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(vref-vfunc, _state),0.005), __FILE__, __LINE__, "testrbfunit.ap:3573");
d2 = d2+(double)1/(double)64;
}
/*
* Test that tiny changes in dataset points introduce tiny
* numerical noise. The noise magnitude depends on the
* properties of the linear solver being used. We compare
* noise magnitude against hard-coded values.
*
* Test sequence:
* * create model #1
* * create model #2 using slightly modified dataset
*/
nx = 2;
ny = 1;
n = 20;
rbase = 2.0;
nlayers = 1;
v2its = 50;
ae_matrix_set_length(&xy, n*n, nx+ny, _state);
for(i=0; i<=n*n-1; i++)
{
xy.ptr.pp_double[i][0] = (double)(i%n);
xy.ptr.pp_double[i][1] = (double)(i/n);
xy.ptr.pp_double[i][2] = ae_sin((double)(i), _state);
}
rbfcreate(nx, ny, &s0, _state);
rbfsetalgohierarchical(&s0, rbase, nlayers, 0.0, _state);
rbfsetv2its(&s0, v2its, _state);
rbfsetpoints(&s0, &xy, n*n, _state);
rbfbuildmodel(&s0, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3608");
ae_frame_leave(_state);
return result;
}
for(i=0; i<=n*n-1; i++)
{
xy.ptr.pp_double[i][0] = xy.ptr.pp_double[i][0]+1.0E-14*ae_sin((double)(3*i), _state);
xy.ptr.pp_double[i][1] = xy.ptr.pp_double[i][1]+1.0E-14*ae_sin((double)(7*i*i), _state);
}
rbfcreate(nx, ny, &s1, _state);
rbfsetalgohierarchical(&s1, rbase, nlayers, 0.0, _state);
rbfsetv2its(&s1, v2its, _state);
rbfsetpoints(&s1, &xy, n*n, _state);
rbfbuildmodel(&s1, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3623");
ae_frame_leave(_state);
return result;
}
vdiff = (double)(0);
for(i=0; i<=n-2; i++)
{
for(j=0; j<=n-2; j++)
{
vdiff = vdiff+ae_fabs(rbfcalc2(&s0, 0.5+i, 0.5+j, _state)-rbfcalc2(&s1, 0.5+i, 0.5+j, _state), _state)/ae_sqr((double)(n-1), _state);
}
}
ae_set_error_flag(&result, ae_fp_greater(vdiff,0.00200)||ae_fp_less(vdiff,0.00001), __FILE__, __LINE__, "testrbfunit.ap:3630");
/*
* Test progress reports: progress before model construction is
* zero, progress after model is built is 1. More detailed tests
* are performed in the multithreaded TestHRBFProgress().
*/
nx = 2;
ny = 1;
n = 20;
rbase = 1.0;
nlayers = 3;
ae_matrix_set_length(&xy, n, nx+ny, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=nx; j++)
{
xy.ptr.pp_double[i][j] = hqrndnormal(&rs, _state);
}
}
rbfcreate(nx, ny, &s0, _state);
rbfsetalgohierarchical(&s0, rbase, nlayers, 0.0, _state);
ae_set_error_flag(&result, ae_fp_neq(rbfpeekprogress(&s0, _state),(double)(0)), __FILE__, __LINE__, "testrbfunit.ap:3652");
rbfbuildmodel(&s0, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testrbfunit.ap:3654");
ae_set_error_flag(&result, ae_fp_neq(rbfpeekprogress(&s0, _state),(double)(1)), __FILE__, __LINE__, "testrbfunit.ap:3655");
rbfcreate(nx, ny, &s0, _state);
rbfsetpoints(&s0, &xy, n, _state);
rbfsetalgohierarchical(&s0, rbase, 0, 0.0, _state);
ae_set_error_flag(&result, ae_fp_neq(rbfpeekprogress(&s0, _state),(double)(0)), __FILE__, __LINE__, "testrbfunit.ap:3661");
rbfbuildmodel(&s0, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testrbfunit.ap:3663");
ae_set_error_flag(&result, ae_fp_neq(rbfpeekprogress(&s0, _state),(double)(1)), __FILE__, __LINE__, "testrbfunit.ap:3664");
rbfcreate(nx, ny, &s0, _state);
rbfsetpoints(&s0, &xy, n, _state);
rbfsetalgohierarchical(&s0, rbase, nlayers, 0.0, _state);
ae_set_error_flag(&result, ae_fp_neq(rbfpeekprogress(&s0, _state),(double)(0)), __FILE__, __LINE__, "testrbfunit.ap:3670");
rbfbuildmodel(&s0, &rep, _state);
ae_set_error_flag(&result, rep.terminationtype<=0, __FILE__, __LINE__, "testrbfunit.ap:3672");
ae_set_error_flag(&result, ae_fp_neq(rbfpeekprogress(&s0, _state),(double)(1)), __FILE__, __LINE__, "testrbfunit.ap:3673");
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Test gridded evaluation of hierarchical RBFs.
Returns True on errors.
-- ALGLIB --
Copyright 20.06.2016 by Bochkanov Sergey
*************************************************************************/
static ae_bool testrbfunit_gridhrbftest(ae_state *_state)
{
ae_frame _frame_block;
rbfmodel s;
rbfreport rep;
ae_int_t linterm;
ae_int_t bf;
double rbase;
ae_int_t nlayers;
ae_int_t nx;
ae_int_t ny;
ae_bool hasscale;
double errtol;
ae_int_t n;
ae_matrix xy;
ae_matrix xy2;
ae_matrix y2;
ae_vector x0;
ae_vector x1;
ae_vector x2;
ae_vector x02;
ae_vector x12;
ae_vector x22;
ae_vector scalevec;
ae_vector scalevec2;
ae_vector needy;
ae_vector rowflags;
ae_int_t n0;
ae_int_t n1;
ae_int_t n2;
ae_int_t nkind;
double v;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t i0;
ae_int_t i1;
ae_int_t i2;
ae_vector x;
ae_vector y;
ae_vector yv;
ae_vector yv2;
double scalefactor;
double lambdav;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&xy, 0, sizeof(xy));
memset(&xy2, 0, sizeof(xy2));
memset(&y2, 0, sizeof(y2));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&x2, 0, sizeof(x2));
memset(&x02, 0, sizeof(x02));
memset(&x12, 0, sizeof(x12));
memset(&x22, 0, sizeof(x22));
memset(&scalevec, 0, sizeof(scalevec));
memset(&scalevec2, 0, sizeof(scalevec2));
memset(&needy, 0, sizeof(needy));
memset(&rowflags, 0, sizeof(rowflags));
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&yv, 0, sizeof(yv));
memset(&yv2, 0, sizeof(yv2));
_rbfmodel_init(&s, _state, ae_true);
_rbfreport_init(&rep, _state, ae_true);
ae_matrix_init(&xy, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&xy2, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&y2, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x02, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x12, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x22, 0, DT_REAL, _state, ae_true);
ae_vector_init(&scalevec, 0, DT_REAL, _state, ae_true);
ae_vector_init(&scalevec2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&needy, 0, DT_BOOL, _state, ae_true);
ae_vector_init(&rowflags, 0, DT_BOOL, _state, ae_true);
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&yv, 0, DT_REAL, _state, ae_true);
ae_vector_init(&yv2, 0, DT_REAL, _state, ae_true);
result = ae_false;
/*
* Test 2-dimensional grid calculation
*/
errtol = 1.0E-12;
nx = 2;
for(ny=1; ny<=4; ny++)
{
for(nkind=0; nkind<=2; nkind++)
{
/*
* problem setup
*/
n = 150;
rbase = 0.10;
nlayers = ae_randominteger(3, _state);
linterm = 1+ae_randominteger(3, _state);
lambdav = 1.0E-3*ae_randominteger(2, _state);
bf = ae_randominteger(2, _state);
ae_matrix_set_length(&xy, n, nx+ny, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=nx-1; j++)
{
xy.ptr.pp_double[i][j] = ae_randomreal(_state);
}
for(j=0; j<=ny-1; j++)
{
xy.ptr.pp_double[i][nx+j] = ae_randomreal(_state)-0.5;
}
}
hasscale = ae_randominteger(2, _state)==0;
if( hasscale )
{
ae_vector_set_length(&scalevec, nx, _state);
for(j=0; j<=nx-1; j++)
{
scalevec.ptr.p_double[j] = ae_pow((double)(2), 2*ae_randomreal(_state)-1, _state);
}
}
/*
* Build model
*/
rbfcreate(nx, ny, &s, _state);
rbfsetv2bf(&s, bf, _state);
rbfsetalgohierarchical(&s, rbase, nlayers, lambdav, _state);
if( linterm==1 )
{
rbfsetlinterm(&s, _state);
}
if( linterm==2 )
{
rbfsetconstterm(&s, _state);
}
if( linterm==3 )
{
rbfsetzeroterm(&s, _state);
}
if( hasscale )
{
rbfsetpointsandscales(&s, &xy, n, &scalevec, _state);
}
else
{
rbfsetpoints(&s, &xy, n, _state);
}
rbfbuildmodel(&s, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3765");
ae_frame_leave(_state);
return result;
}
/*
* Prepare grid to test
*/
n0 = 1+ae_randominteger(50, _state);
n1 = 1+ae_randominteger(50, _state);
if( nkind==1 )
{
k = ae_randominteger(2, _state);
if( k==0 )
{
n0 = 1;
}
if( k==1 )
{
n1 = 1;
}
}
else
{
if( nkind==2 )
{
n0 = 1;
n1 = 1;
}
else
{
ae_assert(nkind==0, "Assertion failed", _state);
}
}
ae_vector_set_length(&x0, n0, _state);
x0.ptr.p_double[0] = ae_randomreal(_state);
for(i=1; i<=n0-1; i++)
{
x0.ptr.p_double[i] = x0.ptr.p_double[i-1]+ae_randomreal(_state)/n0;
}
ae_vector_set_length(&x1, n1, _state);
x1.ptr.p_double[0] = ae_randomreal(_state);
for(i=1; i<=n1-1; i++)
{
x1.ptr.p_double[i] = x1.ptr.p_double[i-1]+ae_randomreal(_state)/n1;
}
ae_vector_set_length(&needy, n0*n1, _state);
v = ae_pow((double)(10), -3*ae_randomreal(_state), _state);
for(i=0; i<=n0*n1-1; i++)
{
needy.ptr.p_bool[i] = ae_fp_less(ae_randomreal(_state),v);
}
/*
* Test at grid
*/
ae_vector_set_length(&x, nx, _state);
rbfgridcalc2v(&s, &x0, n0, &x1, n1, &yv, _state);
for(i0=0; i0<=n0-1; i0++)
{
for(i1=0; i1<=n1-1; i1++)
{
x.ptr.p_double[0] = x0.ptr.p_double[i0];
x.ptr.p_double[1] = x1.ptr.p_double[i1];
rbfcalc(&s, &x, &y, _state);
for(i=0; i<=ny-1; i++)
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(y.ptr.p_double[i]-yv.ptr.p_double[i+ny*(i0+i1*n0)], _state),errtol), __FILE__, __LINE__, "testrbfunit.ap:3814");
}
}
}
/*
* Test calculation on subset of regular grid:
* * Test 1: compare full and subset versions
* * Test 2: check sparsity. Subset function may perform additional
* evaluations because it processes data micro-row by micro-row.
* So, we can't check that all elements which were not flagged
* are zero - some of them may become non-zero. However, if entire
* row is empty, we can reasonably expect (informal guarantee)
* that it is not processed. So, we check empty (completely
* unflagged) rows
*
*/
unsetrealarray(&yv2, _state);
rbfgridcalc2vsubset(&s, &x0, n0, &x1, n1, &needy, &yv2, _state);
for(i=0; i<=ny*n0*n1-1; i++)
{
ae_set_error_flag(&result, needy.ptr.p_bool[i/ny]&&ae_fp_greater(ae_fabs(yv.ptr.p_double[i]-yv2.ptr.p_double[i], _state),errtol), __FILE__, __LINE__, "testrbfunit.ap:3833");
}
/*
* Test legacy function
*/
rbfgridcalc2(&s, &x0, n0, &x1, n1, &y2, _state);
for(i=0; i<=n0*n1-1; i++)
{
if( ny==1 )
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(yv.ptr.p_double[i]-y2.ptr.pp_double[i%n0][i/n0], _state),errtol), __FILE__, __LINE__, "testrbfunit.ap:3843");
}
else
{
ae_set_error_flag(&result, ae_fp_neq(y2.ptr.pp_double[i%n0][i/n0],(double)(0)), __FILE__, __LINE__, "testrbfunit.ap:3845");
}
}
/*
* Test that scaling RBase, XY, X0, X1 by some power of 2
* does not change values at grid (quite a strict requirement, but
* ALGLIB implementation of RBF may deal with it).
*/
scalefactor = ae_pow((double)(1024), (double)(2*ae_randominteger(2, _state)-1), _state);
ae_matrix_set_length(&xy2, n, nx+ny, _state);
ae_vector_set_length(&x02, n0, _state);
ae_vector_set_length(&x12, n1, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=nx-1; j++)
{
xy2.ptr.pp_double[i][j] = xy.ptr.pp_double[i][j]*scalefactor;
}
for(j=0; j<=ny-1; j++)
{
xy2.ptr.pp_double[i][nx+j] = xy.ptr.pp_double[i][nx+j];
}
}
for(i=0; i<=n0-1; i++)
{
x02.ptr.p_double[i] = x0.ptr.p_double[i]*scalefactor;
}
for(i=0; i<=n1-1; i++)
{
x12.ptr.p_double[i] = x1.ptr.p_double[i]*scalefactor;
}
if( hasscale )
{
rbfsetpointsandscales(&s, &xy2, n, &scalevec, _state);
}
else
{
rbfsetpoints(&s, &xy2, n, _state);
}
rbfsetv2bf(&s, bf, _state);
rbfsetalgohierarchical(&s, rbase*scalefactor, nlayers, lambdav, _state);
rbfbuildmodel(&s, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3877");
ae_frame_leave(_state);
return result;
}
unsetrealarray(&yv2, _state);
rbfgridcalc2v(&s, &x02, n0, &x12, n1, &yv2, _state);
for(i=0; i<=ny*n0*n1-1; i++)
{
ae_set_error_flag(&result, ae_fp_neq(yv.ptr.p_double[i],yv2.ptr.p_double[i]), __FILE__, __LINE__, "testrbfunit.ap:3883");
}
/*
* Test that scaling RBase and scale vector by some power of 2
* (increase RBase and decreasing scale, or vice versa) does not
* change values at grid (quite a strict requirement, but
* ALGLIB implementation of RBF may deal with it).
*/
scalefactor = ae_pow((double)(1024), (double)(2*ae_randominteger(2, _state)-1), _state);
ae_vector_set_length(&scalevec2, nx, _state);
for(i=0; i<=nx-1; i++)
{
if( hasscale )
{
scalevec2.ptr.p_double[i] = scalevec.ptr.p_double[i];
}
else
{
scalevec2.ptr.p_double[i] = 1.0;
}
scalevec2.ptr.p_double[i] = scalevec2.ptr.p_double[i]/scalefactor;
}
rbfsetpointsandscales(&s, &xy, n, &scalevec2, _state);
rbfsetv2bf(&s, bf, _state);
rbfsetalgohierarchical(&s, rbase*scalefactor, nlayers, lambdav, _state);
rbfbuildmodel(&s, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3907");
ae_frame_leave(_state);
return result;
}
unsetrealarray(&yv2, _state);
rbfgridcalc2v(&s, &x0, n0, &x1, n1, &yv2, _state);
for(i=0; i<=ny*n0*n1-1; i++)
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(yv.ptr.p_double[i]-yv2.ptr.p_double[i], _state),100*ae_machineepsilon*rmax3(ae_fabs(yv.ptr.p_double[i], _state), ae_fabs(yv2.ptr.p_double[i], _state), 1.0, _state)), __FILE__, __LINE__, "testrbfunit.ap:3913");
}
}
}
/*
* Test 3-dimensional grid calculation
*/
errtol = 1.0E-12;
nx = 3;
for(ny=1; ny<=4; ny++)
{
for(nkind=0; nkind<=2; nkind++)
{
/*
* problem setup
*/
n = 150;
rbase = 0.10;
lambdav = 1.0E-3*ae_randominteger(2, _state);
nlayers = ae_randominteger(3, _state);
linterm = 1+ae_randominteger(3, _state);
bf = ae_randominteger(2, _state);
ae_matrix_set_length(&xy, n, nx+ny, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=nx-1; j++)
{
xy.ptr.pp_double[i][j] = ae_randomreal(_state);
}
for(j=0; j<=ny-1; j++)
{
xy.ptr.pp_double[i][nx+j] = ae_randomreal(_state)-0.5;
}
}
hasscale = ae_randominteger(2, _state)==0;
if( hasscale )
{
ae_vector_set_length(&scalevec, nx, _state);
for(j=0; j<=nx-1; j++)
{
scalevec.ptr.p_double[j] = ae_pow((double)(2), 2*ae_randomreal(_state)-1, _state);
}
}
/*
* Build model
*/
rbfcreate(nx, ny, &s, _state);
rbfsetv2bf(&s, bf, _state);
rbfsetalgohierarchical(&s, rbase, nlayers, lambdav, _state);
if( linterm==1 )
{
rbfsetlinterm(&s, _state);
}
if( linterm==2 )
{
rbfsetconstterm(&s, _state);
}
if( linterm==3 )
{
rbfsetzeroterm(&s, _state);
}
if( hasscale )
{
rbfsetpointsandscales(&s, &xy, n, &scalevec, _state);
}
else
{
rbfsetpoints(&s, &xy, n, _state);
}
rbfbuildmodel(&s, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:3968");
ae_frame_leave(_state);
return result;
}
/*
* Prepare grid to test
*/
n0 = 1+ae_randominteger(50, _state);
n1 = 1+ae_randominteger(50, _state);
n2 = 1+ae_randominteger(50, _state);
if( nkind==1 )
{
k = ae_randominteger(3, _state);
if( k==0 )
{
n0 = 1;
}
if( k==1 )
{
n1 = 1;
}
if( k==2 )
{
n2 = 1;
}
}
else
{
if( nkind==2 )
{
n0 = 1;
n1 = 1;
n2 = 1;
}
else
{
ae_assert(nkind==0, "Assertion failed", _state);
}
}
ae_vector_set_length(&x0, n0, _state);
x0.ptr.p_double[0] = ae_randomreal(_state);
for(i=1; i<=n0-1; i++)
{
x0.ptr.p_double[i] = x0.ptr.p_double[i-1]+ae_randomreal(_state)/n0;
}
ae_vector_set_length(&x1, n1, _state);
x1.ptr.p_double[0] = ae_randomreal(_state);
for(i=1; i<=n1-1; i++)
{
x1.ptr.p_double[i] = x1.ptr.p_double[i-1]+ae_randomreal(_state)/n1;
}
ae_vector_set_length(&x2, n2, _state);
x2.ptr.p_double[0] = ae_randomreal(_state);
for(i=1; i<=n2-1; i++)
{
x2.ptr.p_double[i] = x2.ptr.p_double[i-1]+ae_randomreal(_state)/n2;
}
ae_vector_set_length(&needy, n0*n1*n2, _state);
v = ae_pow((double)(10), -3*ae_randomreal(_state), _state);
for(i=0; i<=n0*n1*n2-1; i++)
{
needy.ptr.p_bool[i] = ae_fp_less(ae_randomreal(_state),v);
}
/*
* Test at grid
*/
ae_vector_set_length(&x, nx, _state);
rbfgridcalc3v(&s, &x0, n0, &x1, n1, &x2, n2, &yv, _state);
for(i0=0; i0<=n0-1; i0++)
{
for(i1=0; i1<=n1-1; i1++)
{
for(i2=0; i2<=n2-1; i2++)
{
x.ptr.p_double[0] = x0.ptr.p_double[i0];
x.ptr.p_double[1] = x1.ptr.p_double[i1];
x.ptr.p_double[2] = x2.ptr.p_double[i2];
rbfcalc(&s, &x, &y, _state);
for(i=0; i<=ny-1; i++)
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(y.ptr.p_double[i]-yv.ptr.p_double[i+ny*(i0+i1*n0+i2*n0*n1)], _state),errtol), __FILE__, __LINE__, "testrbfunit.ap:4027");
}
}
}
}
/*
* Test calculation on subset of regular grid:
* * Test 1: compare full and subset versions
* * Test 2: check sparsity. Subset function may perform additional
* evaluations because it processes data micro-row by micro-row.
* So, we can't check that all elements which were not flagged
* are zero - some of them may become non-zero. However, if entire
* row is empty, we can reasonably expect (informal guarantee)
* that it is not processed. So, we check empty (completely
* unflagged) rows
*
*/
ae_vector_set_length(&rowflags, n1*n2, _state);
for(i=0; i<=n1*n2-1; i++)
{
rowflags.ptr.p_bool[i] = ae_false;
}
for(i=0; i<=n0*n1*n2-1; i++)
{
if( needy.ptr.p_bool[i] )
{
rowflags.ptr.p_bool[i/n0] = ae_true;
}
}
unsetrealarray(&yv2, _state);
rbfgridcalc3vsubset(&s, &x0, n0, &x1, n1, &x2, n2, &needy, &yv2, _state);
for(i=0; i<=ny*n0*n1*n2-1; i++)
{
ae_set_error_flag(&result, needy.ptr.p_bool[i/ny]&&ae_fp_greater(ae_fabs(yv.ptr.p_double[i]-yv2.ptr.p_double[i], _state),errtol), __FILE__, __LINE__, "testrbfunit.ap:4054");
ae_set_error_flag(&result, !rowflags.ptr.p_bool[i/(ny*n0)]&&ae_fp_neq(yv2.ptr.p_double[i],0.0), __FILE__, __LINE__, "testrbfunit.ap:4055");
}
/*
* Test that scaling RBase, XY, X0, X1 and X2 by some power of 2
* does not change values at grid (quite a strict requirement, but
* ALGLIB implementation of RBF may deal with it).
*/
scalefactor = ae_pow((double)(1024), (double)(2*ae_randominteger(2, _state)-1), _state);
ae_matrix_set_length(&xy2, n, nx+ny, _state);
ae_vector_set_length(&x02, n0, _state);
ae_vector_set_length(&x12, n1, _state);
ae_vector_set_length(&x22, n2, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=nx-1; j++)
{
xy2.ptr.pp_double[i][j] = xy.ptr.pp_double[i][j]*scalefactor;
}
for(j=0; j<=ny-1; j++)
{
xy2.ptr.pp_double[i][nx+j] = xy.ptr.pp_double[i][nx+j];
}
}
for(i=0; i<=n0-1; i++)
{
x02.ptr.p_double[i] = x0.ptr.p_double[i]*scalefactor;
}
for(i=0; i<=n1-1; i++)
{
x12.ptr.p_double[i] = x1.ptr.p_double[i]*scalefactor;
}
for(i=0; i<=n2-1; i++)
{
x22.ptr.p_double[i] = x2.ptr.p_double[i]*scalefactor;
}
if( hasscale )
{
rbfsetpointsandscales(&s, &xy2, n, &scalevec, _state);
}
else
{
rbfsetpoints(&s, &xy2, n, _state);
}
rbfsetv2bf(&s, bf, _state);
rbfsetalgohierarchical(&s, rbase*scalefactor, nlayers, lambdav, _state);
rbfbuildmodel(&s, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:4090");
ae_frame_leave(_state);
return result;
}
unsetrealarray(&yv2, _state);
rbfgridcalc3v(&s, &x02, n0, &x12, n1, &x22, n2, &yv2, _state);
for(i=0; i<=ny*n0*n1*n2-1; i++)
{
ae_set_error_flag(&result, ae_fp_neq(yv.ptr.p_double[i],yv2.ptr.p_double[i]), __FILE__, __LINE__, "testrbfunit.ap:4096");
}
/*
* Test that scaling RBase and scale vector by some power of 2
* (increase RBase and decreasing scale, or vice versa) does not
* change values at grid (quite a strict requirement, but
* ALGLIB implementation of RBF may deal with it).
*/
scalefactor = ae_pow((double)(1024), (double)(2*ae_randominteger(2, _state)-1), _state);
ae_vector_set_length(&scalevec2, nx, _state);
for(i=0; i<=nx-1; i++)
{
if( hasscale )
{
scalevec2.ptr.p_double[i] = scalevec.ptr.p_double[i];
}
else
{
scalevec2.ptr.p_double[i] = 1.0;
}
scalevec2.ptr.p_double[i] = scalevec2.ptr.p_double[i]/scalefactor;
}
rbfsetpointsandscales(&s, &xy, n, &scalevec2, _state);
rbfsetv2bf(&s, bf, _state);
rbfsetalgohierarchical(&s, rbase*scalefactor, nlayers, lambdav, _state);
rbfbuildmodel(&s, &rep, _state);
if( rep.terminationtype<=0 )
{
ae_set_error_flag(&result, ae_true, __FILE__, __LINE__, "testrbfunit.ap:4120");
ae_frame_leave(_state);
return result;
}
unsetrealarray(&yv2, _state);
rbfgridcalc3v(&s, &x0, n0, &x1, n1, &x2, n2, &yv2, _state);
for(i=0; i<=ny*n0*n1*n2-1; i++)
{
ae_set_error_flag(&result, ae_fp_greater(ae_fabs(yv.ptr.p_double[i]-yv2.ptr.p_double[i], _state),100*ae_machineepsilon*rmax3(ae_fabs(yv.ptr.p_double[i], _state), ae_fabs(yv2.ptr.p_double[i], _state), 1.0, _state)), __FILE__, __LINE__, "testrbfunit.ap:4126");
}
}
}
ae_frame_leave(_state);
return result;
}
ae_bool testhermite(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
double err;
double sumerr;
double cerr;
double threshold;
ae_int_t n;
ae_int_t maxn;
ae_int_t pass;
ae_vector c;
double x;
double v;
ae_bool waserrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&c, 0, sizeof(c));
ae_vector_init(&c, 0, DT_REAL, _state, ae_true);
err = (double)(0);
sumerr = (double)(0);
cerr = (double)(0);
threshold = 1.0E-9;
waserrors = ae_false;
/*
* Testing Hermite polynomials
*/
n = 0;
err = ae_maxreal(err, ae_fabs(hermitecalculate(n, (double)(1), _state)-1, _state), _state);
n = 1;
err = ae_maxreal(err, ae_fabs(hermitecalculate(n, (double)(1), _state)-2, _state), _state);
n = 2;
err = ae_maxreal(err, ae_fabs(hermitecalculate(n, (double)(1), _state)-2, _state), _state);
n = 3;
err = ae_maxreal(err, ae_fabs(hermitecalculate(n, (double)(1), _state)+4, _state), _state);
n = 4;
err = ae_maxreal(err, ae_fabs(hermitecalculate(n, (double)(1), _state)+20, _state), _state);
n = 5;
err = ae_maxreal(err, ae_fabs(hermitecalculate(n, (double)(1), _state)+8, _state), _state);
n = 6;
err = ae_maxreal(err, ae_fabs(hermitecalculate(n, (double)(1), _state)-184, _state), _state);
n = 7;
err = ae_maxreal(err, ae_fabs(hermitecalculate(n, (double)(1), _state)-464, _state), _state);
n = 11;
err = ae_maxreal(err, ae_fabs(hermitecalculate(n, (double)(1), _state)-230848, _state), _state);
n = 12;
err = ae_maxreal(err, ae_fabs(hermitecalculate(n, (double)(1), _state)-280768, _state), _state);
/*
* Testing Clenshaw summation
*/
maxn = 10;
ae_vector_set_length(&c, maxn+1, _state);
for(pass=1; pass<=10; pass++)
{
x = 2*ae_randomreal(_state)-1;
v = (double)(0);
for(n=0; n<=maxn; n++)
{
c.ptr.p_double[n] = 2*ae_randomreal(_state)-1;
v = v+hermitecalculate(n, x, _state)*c.ptr.p_double[n];
sumerr = ae_maxreal(sumerr, ae_fabs(v-hermitesum(&c, n, x, _state), _state), _state);
}
}
/*
* Testing coefficients
*/
hermitecoefficients(0, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-1, _state), _state);
hermitecoefficients(1, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-2, _state), _state);
hermitecoefficients(2, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]+2, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-4, _state), _state);
hermitecoefficients(3, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]+12, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]-8, _state), _state);
hermitecoefficients(4, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-12, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]+48, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[4]-16, _state), _state);
hermitecoefficients(5, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-120, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]+160, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[4]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[5]-32, _state), _state);
hermitecoefficients(6, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]+120, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-720, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[4]+480, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[5]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[6]-64, _state), _state);
/*
* Reporting
*/
waserrors = (ae_fp_greater(err,threshold)||ae_fp_greater(sumerr,threshold))||ae_fp_greater(cerr,threshold);
if( !silent )
{
printf("TESTING CALCULATION OF THE HERMITE POLYNOMIALS\n");
printf("Max error %5.2e\n",
(double)(err));
printf("Summation error %5.2e\n",
(double)(sumerr));
printf("Coefficients error %5.2e\n",
(double)(cerr));
printf("Threshold %5.2e\n",
(double)(threshold));
if( !waserrors )
{
printf("TEST PASSED\n");
}
else
{
printf("TEST FAILED\n");
}
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
ae_bool testlaguerre(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
double err;
double sumerr;
double cerr;
double threshold;
ae_int_t n;
ae_int_t maxn;
ae_int_t pass;
ae_vector c;
double x;
double v;
ae_bool waserrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&c, 0, sizeof(c));
ae_vector_init(&c, 0, DT_REAL, _state, ae_true);
err = (double)(0);
sumerr = (double)(0);
cerr = (double)(0);
threshold = 1.0E-9;
waserrors = ae_false;
/*
* Testing Laguerre polynomials
*/
n = 0;
err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)-1.0000000000, _state), _state);
n = 1;
err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)-0.5000000000, _state), _state);
n = 2;
err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)-0.1250000000, _state), _state);
n = 3;
err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)+0.1458333333, _state), _state);
n = 4;
err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)+0.3307291667, _state), _state);
n = 5;
err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)+0.4455729167, _state), _state);
n = 6;
err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)+0.5041449653, _state), _state);
n = 7;
err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)+0.5183392237, _state), _state);
n = 8;
err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)+0.4983629984, _state), _state);
n = 9;
err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)+0.4529195204, _state), _state);
n = 10;
err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)+0.3893744141, _state), _state);
n = 11;
err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)+0.3139072988, _state), _state);
n = 12;
err = ae_maxreal(err, ae_fabs(laguerrecalculate(n, 0.5, _state)+0.2316496389, _state), _state);
/*
* Testing Clenshaw summation
*/
maxn = 20;
ae_vector_set_length(&c, maxn+1, _state);
for(pass=1; pass<=10; pass++)
{
x = 2*ae_randomreal(_state)-1;
v = (double)(0);
for(n=0; n<=maxn; n++)
{
c.ptr.p_double[n] = 2*ae_randomreal(_state)-1;
v = v+laguerrecalculate(n, x, _state)*c.ptr.p_double[n];
sumerr = ae_maxreal(sumerr, ae_fabs(v-laguerresum(&c, n, x, _state), _state), _state);
}
}
/*
* Testing coefficients
*/
laguerrecoefficients(0, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-1, _state), _state);
laguerrecoefficients(1, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-1, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]+1, _state), _state);
laguerrecoefficients(2, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-(double)2/(double)2, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]+(double)4/(double)2, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-(double)1/(double)2, _state), _state);
laguerrecoefficients(3, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-(double)6/(double)6, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]+(double)18/(double)6, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-(double)9/(double)6, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]+(double)1/(double)6, _state), _state);
laguerrecoefficients(4, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-(double)24/(double)24, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]+(double)96/(double)24, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-(double)72/(double)24, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]+(double)16/(double)24, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[4]-(double)1/(double)24, _state), _state);
laguerrecoefficients(5, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-(double)120/(double)120, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]+(double)600/(double)120, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-(double)600/(double)120, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]+(double)200/(double)120, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[4]-(double)25/(double)120, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[5]+(double)1/(double)120, _state), _state);
laguerrecoefficients(6, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-(double)720/(double)720, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]+(double)4320/(double)720, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-(double)5400/(double)720, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]+(double)2400/(double)720, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[4]-(double)450/(double)720, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[5]+(double)36/(double)720, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[6]-(double)1/(double)720, _state), _state);
/*
* Reporting
*/
waserrors = (ae_fp_greater(err,threshold)||ae_fp_greater(sumerr,threshold))||ae_fp_greater(cerr,threshold);
if( !silent )
{
printf("TESTING CALCULATION OF THE LAGUERRE POLYNOMIALS\n");
printf("Max error %5.2e\n",
(double)(err));
printf("Summation error %5.2e\n",
(double)(sumerr));
printf("Coefficients error %5.2e\n",
(double)(cerr));
printf("Threshold %5.2e\n",
(double)(threshold));
if( !waserrors )
{
printf("TEST PASSED\n");
}
else
{
printf("TEST FAILED\n");
}
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
ae_bool testlegendre(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
double err;
double sumerr;
double cerr;
double threshold;
ae_int_t n;
ae_int_t maxn;
ae_int_t i;
ae_int_t pass;
ae_vector c;
double x;
double v;
double t;
ae_bool waserrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&c, 0, sizeof(c));
ae_vector_init(&c, 0, DT_REAL, _state, ae_true);
err = (double)(0);
sumerr = (double)(0);
cerr = (double)(0);
threshold = 1.0E-9;
waserrors = ae_false;
/*
* Testing Legendre polynomials values
*/
for(n=0; n<=10; n++)
{
legendrecoefficients(n, &c, _state);
for(pass=1; pass<=10; pass++)
{
x = 2*ae_randomreal(_state)-1;
v = legendrecalculate(n, x, _state);
t = (double)(1);
for(i=0; i<=n; i++)
{
v = v-c.ptr.p_double[i]*t;
t = t*x;
}
err = ae_maxreal(err, ae_fabs(v, _state), _state);
}
}
/*
* Testing Clenshaw summation
*/
maxn = 20;
ae_vector_set_length(&c, maxn+1, _state);
for(pass=1; pass<=10; pass++)
{
x = 2*ae_randomreal(_state)-1;
v = (double)(0);
for(n=0; n<=maxn; n++)
{
c.ptr.p_double[n] = 2*ae_randomreal(_state)-1;
v = v+legendrecalculate(n, x, _state)*c.ptr.p_double[n];
sumerr = ae_maxreal(sumerr, ae_fabs(v-legendresum(&c, n, x, _state), _state), _state);
}
}
/*
* Testing coefficients
*/
legendrecoefficients(0, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-1, _state), _state);
legendrecoefficients(1, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-1, _state), _state);
legendrecoefficients(2, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]+(double)1/(double)2, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-(double)3/(double)2, _state), _state);
legendrecoefficients(3, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]+(double)3/(double)2, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]-(double)5/(double)2, _state), _state);
legendrecoefficients(4, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-(double)3/(double)8, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]+(double)30/(double)8, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[4]-(double)35/(double)8, _state), _state);
legendrecoefficients(9, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-(double)315/(double)128, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]+(double)4620/(double)128, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[4]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[5]-(double)18018/(double)128, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[6]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[7]+(double)25740/(double)128, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[8]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[9]-(double)12155/(double)128, _state), _state);
/*
* Reporting
*/
waserrors = (ae_fp_greater(err,threshold)||ae_fp_greater(sumerr,threshold))||ae_fp_greater(cerr,threshold);
if( !silent )
{
printf("TESTING CALCULATION OF THE LEGENDRE POLYNOMIALS\n");
printf("Max error %5.2e\n",
(double)(err));
printf("Summation error %5.2e\n",
(double)(sumerr));
printf("Coefficients error %5.2e\n",
(double)(cerr));
printf("Threshold %5.2e\n",
(double)(threshold));
if( !waserrors )
{
printf("TEST PASSED\n");
}
else
{
printf("TEST FAILED\n");
}
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
ae_bool testchebyshev(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
double err;
double sumerr;
double cerr;
double ferr;
double threshold;
double x;
double v;
ae_int_t pass;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t n;
ae_int_t maxn;
ae_vector c;
ae_vector p1;
ae_vector p2;
ae_matrix a;
ae_bool waserrors;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&c, 0, sizeof(c));
memset(&p1, 0, sizeof(p1));
memset(&p2, 0, sizeof(p2));
memset(&a, 0, sizeof(a));
ae_vector_init(&c, 0, DT_REAL, _state, ae_true);
ae_vector_init(&p1, 0, DT_REAL, _state, ae_true);
ae_vector_init(&p2, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
err = (double)(0);
sumerr = (double)(0);
cerr = (double)(0);
ferr = (double)(0);
threshold = 1.0E-9;
waserrors = ae_false;
/*
* Testing Chebyshev polynomials of the first kind
*/
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 0, 0.00, _state)-1, _state), _state);
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 0, 0.33, _state)-1, _state), _state);
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 0, -0.42, _state)-1, _state), _state);
x = 0.2;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 1, x, _state)-0.2, _state), _state);
x = 0.4;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 1, x, _state)-0.4, _state), _state);
x = 0.6;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 1, x, _state)-0.6, _state), _state);
x = 0.8;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 1, x, _state)-0.8, _state), _state);
x = 1.0;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 1, x, _state)-1.0, _state), _state);
x = 0.2;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 2, x, _state)+0.92, _state), _state);
x = 0.4;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 2, x, _state)+0.68, _state), _state);
x = 0.6;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 2, x, _state)+0.28, _state), _state);
x = 0.8;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 2, x, _state)-0.28, _state), _state);
x = 1.0;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, 2, x, _state)-1.00, _state), _state);
n = 10;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, n, 0.2, _state)-0.4284556288, _state), _state);
n = 11;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, n, 0.2, _state)+0.7996160205, _state), _state);
n = 12;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(1, n, 0.2, _state)+0.7483020370, _state), _state);
/*
* Testing Chebyshev polynomials of the second kind
*/
n = 0;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(2, n, 0.2, _state)-1.0000000000, _state), _state);
n = 1;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(2, n, 0.2, _state)-0.4000000000, _state), _state);
n = 2;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(2, n, 0.2, _state)+0.8400000000, _state), _state);
n = 3;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(2, n, 0.2, _state)+0.7360000000, _state), _state);
n = 4;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(2, n, 0.2, _state)-0.5456000000, _state), _state);
n = 10;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(2, n, 0.2, _state)-0.6128946176, _state), _state);
n = 11;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(2, n, 0.2, _state)+0.6770370970, _state), _state);
n = 12;
err = ae_maxreal(err, ae_fabs(chebyshevcalculate(2, n, 0.2, _state)+0.8837094564, _state), _state);
/*
* Testing Clenshaw summation
*/
maxn = 20;
ae_vector_set_length(&c, maxn+1, _state);
for(k=1; k<=2; k++)
{
for(pass=1; pass<=10; pass++)
{
x = 2*ae_randomreal(_state)-1;
v = (double)(0);
for(n=0; n<=maxn; n++)
{
c.ptr.p_double[n] = 2*ae_randomreal(_state)-1;
v = v+chebyshevcalculate(k, n, x, _state)*c.ptr.p_double[n];
sumerr = ae_maxreal(sumerr, ae_fabs(v-chebyshevsum(&c, k, n, x, _state), _state), _state);
}
}
}
/*
* Testing coefficients
*/
chebyshevcoefficients(0, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-1, _state), _state);
chebyshevcoefficients(1, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-1, _state), _state);
chebyshevcoefficients(2, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]+1, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-2, _state), _state);
chebyshevcoefficients(3, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]+3, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]-4, _state), _state);
chebyshevcoefficients(4, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-1, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]+8, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[4]-8, _state), _state);
chebyshevcoefficients(9, &c, _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[0]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[1]-9, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[2]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[3]+120, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[4]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[5]-432, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[6]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[7]+576, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[8]-0, _state), _state);
cerr = ae_maxreal(cerr, ae_fabs(c.ptr.p_double[9]-256, _state), _state);
/*
* Testing FromChebyshev
*/
maxn = 10;
ae_matrix_set_length(&a, maxn+1, maxn+1, _state);
for(i=0; i<=maxn; i++)
{
for(j=0; j<=maxn; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
chebyshevcoefficients(i, &c, _state);
ae_v_move(&a.ptr.pp_double[i][0], 1, &c.ptr.p_double[0], 1, ae_v_len(0,i));
}
ae_vector_set_length(&c, maxn+1, _state);
ae_vector_set_length(&p1, maxn+1, _state);
for(n=0; n<=maxn; n++)
{
for(pass=1; pass<=10; pass++)
{
for(i=0; i<=n; i++)
{
p1.ptr.p_double[i] = (double)(0);
}
for(i=0; i<=n; i++)
{
c.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
v = c.ptr.p_double[i];
ae_v_addd(&p1.ptr.p_double[0], 1, &a.ptr.pp_double[i][0], 1, ae_v_len(0,i), v);
}
fromchebyshev(&c, n, &p2, _state);
for(i=0; i<=n; i++)
{
ferr = ae_maxreal(ferr, ae_fabs(p1.ptr.p_double[i]-p2.ptr.p_double[i], _state), _state);
}
}
}
/*
* Reporting
*/
waserrors = ((ae_fp_greater(err,threshold)||ae_fp_greater(sumerr,threshold))||ae_fp_greater(cerr,threshold))||ae_fp_greater(ferr,threshold);
if( !silent )
{
printf("TESTING CALCULATION OF THE CHEBYSHEV POLYNOMIALS\n");
printf("Max error against table %5.2e\n",
(double)(err));
printf("Summation error %5.2e\n",
(double)(sumerr));
printf("Coefficients error %5.2e\n",
(double)(cerr));
printf("FrobChebyshev error %5.2e\n",
(double)(ferr));
printf("Threshold %5.2e\n",
(double)(threshold));
if( !waserrors )
{
printf("TEST PASSED\n");
}
else
{
printf("TEST FAILED\n");
}
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
ae_bool testwsr(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_bool waserrors;
ae_vector xa;
ae_int_t n;
ae_int_t i;
double taill;
double tailr;
double tailb;
double taillprev;
double tailrprev;
double ebase;
double eshift;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&xa, 0, sizeof(xa));
ae_vector_init(&xa, 0, DT_REAL, _state, ae_true);
waserrors = ae_false;
/*
* Test monotonicity of tail values for moving value of E
*/
for(n=5; n<=50; n++)
{
/*
* Generate uniform and sorted X spanning [0,1]
*/
ae_vector_set_length(&xa, n, _state);
for(i=0; i<=n-1; i++)
{
xa.ptr.p_double[i] = (double)i/(double)(n-1);
}
/*
* Test N+1 values of E
*/
ebase = -0.5/(n-1);
eshift = (double)1/(double)(n-1);
tailrprev = (double)(0);
taillprev = (double)(1);
for(i=0; i<=n; i++)
{
wilcoxonsignedranktest(&xa, n, ebase+eshift*i, &tailb, &taill, &tailr, _state);
ae_set_error_flag(&waserrors, ae_fp_neq(tailb,2*ae_minreal(taill, tailr, _state)), __FILE__, __LINE__, "testwsrunit.ap:42");
ae_set_error_flag(&waserrors, ae_fp_greater(tailrprev,tailr), __FILE__, __LINE__, "testwsrunit.ap:43");
ae_set_error_flag(&waserrors, ae_fp_less(taillprev,taill), __FILE__, __LINE__, "testwsrunit.ap:44");
tailrprev = tailr;
taillprev = taill;
}
}
/*
* Test for integer overflow in the function: if one crucial
* calculation step is performed in 32-bit integer arithmetics,
* it will return incorrect results.
*
* We use special handcrafted N, such that in 32-bit integer
* arithmetics int32(N*N)<0. Such negative N leads to domain
* error in the sqrt() function.
*/
n = 50000;
ae_vector_set_length(&xa, n, _state);
for(i=0; i<=n-1; i++)
{
xa.ptr.p_double[i] = ae_sin((double)(10*i), _state);
}
wilcoxonsignedranktest(&xa, n, 0.0, &tailb, &taill, &tailr, _state);
ae_set_error_flag(&waserrors, !ae_isfinite(tailb, _state), __FILE__, __LINE__, "testwsrunit.ap:64");
ae_set_error_flag(&waserrors, !ae_isfinite(taill, _state), __FILE__, __LINE__, "testwsrunit.ap:65");
ae_set_error_flag(&waserrors, !ae_isfinite(tailr, _state), __FILE__, __LINE__, "testwsrunit.ap:66");
/*
*
*/
if( !silent )
{
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
ae_bool teststest(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_vector x;
double taill;
double tailr;
double tailb;
ae_bool waserrors;
double eps;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
waserrors = ae_false;
eps = 1.0E-3;
/*
* Test 1
*/
ae_vector_set_length(&x, 6, _state);
x.ptr.p_double[0] = (double)(-3);
x.ptr.p_double[1] = (double)(-2);
x.ptr.p_double[2] = (double)(-1);
x.ptr.p_double[3] = (double)(1);
x.ptr.p_double[4] = (double)(2);
x.ptr.p_double[5] = (double)(3);
onesamplesigntest(&x, 6, 0.0, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_greater(ae_fabs(taill-0.65625, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.65625, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-1.00000, _state),eps);
onesamplesigntest(&x, 6, -1.0, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_greater(ae_fabs(taill-0.81250, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.50000, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-1.00000, _state),eps);
onesamplesigntest(&x, 6, -1.5, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_greater(ae_fabs(taill-0.89062, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.34375, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-0.68750, _state),eps);
onesamplesigntest(&x, 6, -3.0, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_greater(ae_fabs(taill-1.00000, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.03125, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-0.06250, _state),eps);
/*
* Test 2
*/
ae_vector_set_length(&x, 3, _state);
x.ptr.p_double[0] = (double)(2);
x.ptr.p_double[1] = (double)(2);
x.ptr.p_double[2] = (double)(2);
onesamplesigntest(&x, 3, 2.0, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(taill,(double)(1));
waserrors = waserrors||ae_fp_neq(tailr,(double)(1));
waserrors = waserrors||ae_fp_neq(tailb,(double)(1));
/*
* Final report
*/
if( !silent )
{
printf("SIGN TEST: ");
if( !waserrors )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
if( waserrors )
{
printf("TEST SUMMARY: FAILED\n");
}
else
{
printf("TEST SUMMARY: PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
ae_bool teststudentttests(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_bool waserrors;
double eps;
ae_vector x;
ae_vector y;
ae_vector xa;
ae_vector ya;
ae_vector xb;
ae_vector yb;
ae_int_t n;
ae_int_t i;
double taill;
double tailr;
double tailb;
double taill1;
double tailr1;
double tailb1;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&xa, 0, sizeof(xa));
memset(&ya, 0, sizeof(ya));
memset(&xb, 0, sizeof(xb));
memset(&yb, 0, sizeof(yb));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xa, 0, DT_REAL, _state, ae_true);
ae_vector_init(&ya, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xb, 0, DT_REAL, _state, ae_true);
ae_vector_init(&yb, 0, DT_REAL, _state, ae_true);
waserrors = ae_false;
eps = 0.001;
/*
* 1-sample test
*/
n = 8;
ae_vector_set_length(&x, 8, _state);
x.ptr.p_double[0] = -3.0;
x.ptr.p_double[1] = -1.5;
x.ptr.p_double[2] = -1.0;
x.ptr.p_double[3] = -0.5;
x.ptr.p_double[4] = 0.5;
x.ptr.p_double[5] = 1.0;
x.ptr.p_double[6] = 1.5;
x.ptr.p_double[7] = 3.0;
studentttest1(&x, n, 0.0, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-1.00000, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(taill-0.50000, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.50000, _state),eps);
studentttest1(&x, n, 1.0, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-0.17816, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(taill-0.08908, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.91092, _state),eps);
studentttest1(&x, n, -1.0, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-0.17816, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(taill-0.91092, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.08908, _state),eps);
x.ptr.p_double[0] = 1.1;
x.ptr.p_double[1] = 1.1;
x.ptr.p_double[2] = 1.1;
x.ptr.p_double[3] = 1.1;
x.ptr.p_double[4] = 1.1;
x.ptr.p_double[5] = 1.1;
x.ptr.p_double[6] = 1.1;
x.ptr.p_double[7] = 1.1;
studentttest1(&x, n, 1.1, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(tailb,(double)(1));
waserrors = waserrors||ae_fp_neq(taill,(double)(1));
waserrors = waserrors||ae_fp_neq(tailr,(double)(1));
studentttest1(&x, n, 0.0, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(tailb,(double)(0));
waserrors = waserrors||ae_fp_neq(taill,(double)(1));
waserrors = waserrors||ae_fp_neq(tailr,(double)(0));
x.ptr.p_double[7] = 1.1;
studentttest1(&x, 1, 1.1, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(tailb,(double)(1));
waserrors = waserrors||ae_fp_neq(taill,(double)(1));
waserrors = waserrors||ae_fp_neq(tailr,(double)(1));
studentttest1(&x, 1, 0.0, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(tailb,(double)(0));
waserrors = waserrors||ae_fp_neq(taill,(double)(1));
waserrors = waserrors||ae_fp_neq(tailr,(double)(0));
/*
* 2-sample pooled (equal variance) test
*/
n = 8;
ae_vector_set_length(&x, 8, _state);
ae_vector_set_length(&y, 8, _state);
x.ptr.p_double[0] = -3.0;
x.ptr.p_double[1] = -1.5;
x.ptr.p_double[2] = -1.0;
x.ptr.p_double[3] = -0.5;
x.ptr.p_double[4] = 0.5;
x.ptr.p_double[5] = 1.0;
x.ptr.p_double[6] = 1.5;
x.ptr.p_double[7] = 3.0;
y.ptr.p_double[0] = -2.0;
y.ptr.p_double[1] = -0.5;
y.ptr.p_double[2] = 0.0;
y.ptr.p_double[3] = 0.5;
y.ptr.p_double[4] = 1.5;
y.ptr.p_double[5] = 2.0;
y.ptr.p_double[6] = 2.5;
y.ptr.p_double[7] = 4.0;
studentttest2(&x, n, &y, n, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-0.30780, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(taill-0.15390, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.84610, _state),eps);
studentttest2(&x, n, &y, n-1, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-0.53853, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(taill-0.26927, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.73074, _state),eps);
studentttest2(&x, n-1, &y, n, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-0.13829, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(taill-0.06915, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.93086, _state),eps);
x.ptr.p_double[0] = -1.0;
x.ptr.p_double[1] = -1.0;
x.ptr.p_double[2] = -1.0;
x.ptr.p_double[3] = -1.0;
x.ptr.p_double[4] = -1.0;
x.ptr.p_double[5] = -1.0;
x.ptr.p_double[6] = -1.0;
x.ptr.p_double[7] = -1.0;
y.ptr.p_double[0] = 1.0;
y.ptr.p_double[1] = 1.0;
y.ptr.p_double[2] = 1.0;
y.ptr.p_double[3] = 1.0;
y.ptr.p_double[4] = 1.0;
y.ptr.p_double[5] = 1.0;
y.ptr.p_double[6] = 1.0;
y.ptr.p_double[7] = 1.0;
studentttest2(&x, n, &y, n, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(tailb,(double)(0));
waserrors = waserrors||ae_fp_neq(taill,(double)(0));
waserrors = waserrors||ae_fp_neq(tailr,(double)(1));
studentttest2(&x, n, &y, n-1, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(tailb,(double)(0));
waserrors = waserrors||ae_fp_neq(taill,(double)(0));
waserrors = waserrors||ae_fp_neq(tailr,(double)(1));
studentttest2(&x, n, &y, 1, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(tailb,(double)(0));
waserrors = waserrors||ae_fp_neq(taill,(double)(0));
waserrors = waserrors||ae_fp_neq(tailr,(double)(1));
studentttest2(&x, n-1, &y, n, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(tailb,(double)(0));
waserrors = waserrors||ae_fp_neq(taill,(double)(0));
waserrors = waserrors||ae_fp_neq(tailr,(double)(1));
studentttest2(&x, 1, &y, n, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(tailb,(double)(0));
waserrors = waserrors||ae_fp_neq(taill,(double)(0));
waserrors = waserrors||ae_fp_neq(tailr,(double)(1));
studentttest2(&x, 1, &y, 1, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(tailb,(double)(0));
waserrors = waserrors||ae_fp_neq(taill,(double)(0));
waserrors = waserrors||ae_fp_neq(tailr,(double)(1));
studentttest2(&y, 1, &x, 1, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(tailb,(double)(0));
waserrors = waserrors||ae_fp_neq(taill,(double)(1));
waserrors = waserrors||ae_fp_neq(tailr,(double)(0));
x.ptr.p_double[0] = 1.1;
x.ptr.p_double[1] = 1.1;
x.ptr.p_double[2] = 1.1;
x.ptr.p_double[3] = 1.1;
x.ptr.p_double[4] = 1.1;
x.ptr.p_double[5] = 1.1;
x.ptr.p_double[6] = 1.1;
x.ptr.p_double[7] = 1.1;
y.ptr.p_double[0] = 1.1;
y.ptr.p_double[1] = 1.1;
y.ptr.p_double[2] = 1.1;
y.ptr.p_double[3] = 1.1;
y.ptr.p_double[4] = 1.1;
y.ptr.p_double[5] = 1.1;
y.ptr.p_double[6] = 1.1;
y.ptr.p_double[7] = 1.1;
studentttest2(&x, n, &y, n, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(tailb,(double)(1));
waserrors = waserrors||ae_fp_neq(taill,(double)(1));
waserrors = waserrors||ae_fp_neq(tailr,(double)(1));
studentttest2(&x, n, &y, n-1, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(tailb,(double)(1));
waserrors = waserrors||ae_fp_neq(taill,(double)(1));
waserrors = waserrors||ae_fp_neq(tailr,(double)(1));
studentttest2(&x, n, &y, 1, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(tailb,(double)(1));
waserrors = waserrors||ae_fp_neq(taill,(double)(1));
waserrors = waserrors||ae_fp_neq(tailr,(double)(1));
studentttest2(&x, n-1, &y, n, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(tailb,(double)(1));
waserrors = waserrors||ae_fp_neq(taill,(double)(1));
waserrors = waserrors||ae_fp_neq(tailr,(double)(1));
studentttest2(&x, 1, &y, n, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(tailb,(double)(1));
waserrors = waserrors||ae_fp_neq(taill,(double)(1));
waserrors = waserrors||ae_fp_neq(tailr,(double)(1));
studentttest2(&x, 1, &y, 1, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(tailb,(double)(1));
waserrors = waserrors||ae_fp_neq(taill,(double)(1));
waserrors = waserrors||ae_fp_neq(tailr,(double)(1));
/*
* 2-sample unpooled (unequal variance) test:
* * test on two non-constant samples
* * tests on different combinations of non-constant and constant samples
*/
n = 8;
ae_vector_set_length(&xa, 8, _state);
ae_vector_set_length(&ya, 8, _state);
ae_vector_set_length(&xb, 8, _state);
ae_vector_set_length(&yb, 8, _state);
xa.ptr.p_double[0] = -3.0;
xa.ptr.p_double[1] = -1.5;
xa.ptr.p_double[2] = -1.0;
xa.ptr.p_double[3] = -0.5;
xa.ptr.p_double[4] = 0.5;
xa.ptr.p_double[5] = 1.0;
xa.ptr.p_double[6] = 1.5;
xa.ptr.p_double[7] = 3.0;
ya.ptr.p_double[0] = -1.0;
ya.ptr.p_double[1] = -0.5;
ya.ptr.p_double[2] = 0.0;
ya.ptr.p_double[3] = 0.5;
ya.ptr.p_double[4] = 1.5;
ya.ptr.p_double[5] = 2.0;
ya.ptr.p_double[6] = 2.5;
ya.ptr.p_double[7] = 3.0;
xb.ptr.p_double[0] = -1.1;
xb.ptr.p_double[1] = -1.1;
xb.ptr.p_double[2] = -1.1;
xb.ptr.p_double[3] = -1.1;
xb.ptr.p_double[4] = -1.1;
xb.ptr.p_double[5] = -1.1;
xb.ptr.p_double[6] = -1.1;
xb.ptr.p_double[7] = -1.1;
yb.ptr.p_double[0] = 1.1;
yb.ptr.p_double[1] = 1.1;
yb.ptr.p_double[2] = 1.1;
yb.ptr.p_double[3] = 1.1;
yb.ptr.p_double[4] = 1.1;
yb.ptr.p_double[5] = 1.1;
yb.ptr.p_double[6] = 1.1;
yb.ptr.p_double[7] = 1.1;
unequalvariancettest(&xa, n, &ya, n, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-0.25791, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(taill-0.12896, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-0.87105, _state),eps);
unequalvariancettest(&xa, n, &yb, n, &tailb, &taill, &tailr, _state);
studentttest1(&xa, n, 1.1, &tailb1, &taill1, &tailr1, _state);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-tailb1, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(taill-taill1, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-tailr1, _state),eps);
unequalvariancettest(&xa, n, &yb, 1, &tailb, &taill, &tailr, _state);
studentttest1(&xa, n, 1.1, &tailb1, &taill1, &tailr1, _state);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-tailb1, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(taill-taill1, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-tailr1, _state),eps);
unequalvariancettest(&xb, n, &ya, n, &tailb, &taill, &tailr, _state);
studentttest1(&ya, n, -1.1, &tailb1, &taill1, &tailr1, _state);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-tailb1, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(taill-tailr1, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-taill1, _state),eps);
unequalvariancettest(&xb, 1, &ya, n, &tailb, &taill, &tailr, _state);
studentttest1(&ya, n, -1.1, &tailb1, &taill1, &tailr1, _state);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailb-tailb1, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(taill-tailr1, _state),eps);
waserrors = waserrors||ae_fp_greater(ae_fabs(tailr-taill1, _state),eps);
unequalvariancettest(&xb, 1, &yb, 1, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(tailb,(double)(0));
waserrors = waserrors||ae_fp_neq(taill,(double)(0));
waserrors = waserrors||ae_fp_neq(tailr,(double)(1));
unequalvariancettest(&yb, 1, &xb, 1, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(tailb,(double)(0));
waserrors = waserrors||ae_fp_neq(taill,(double)(1));
waserrors = waserrors||ae_fp_neq(tailr,(double)(0));
unequalvariancettest(&xb, 1, &xb, 1, &tailb, &taill, &tailr, _state);
waserrors = waserrors||ae_fp_neq(tailb,(double)(1));
waserrors = waserrors||ae_fp_neq(taill,(double)(1));
waserrors = waserrors||ae_fp_neq(tailr,(double)(1));
/*
* Test for integer overflow in the function: if one crucial
* calculation step is performed in 32-bit integer arithmetics,
* it will return incorrect results.
*
* We use special handcrafted N, such that in 32-bit integer
* arithmetics int32(N*N)<0. Such negative N leads to domain
* error in the incomplete beta function.
*/
n = 50000;
ae_vector_set_length(&xa, n, _state);
ae_vector_set_length(&ya, n, _state);
for(i=0; i<=n-1; i++)
{
xa.ptr.p_double[i] = ae_randomreal(_state);
ya.ptr.p_double[i] = ae_randomreal(_state);
}
unequalvariancettest(&xa, n, &ya, n, &tailb, &taill, &tailr, _state);
/*
*
*/
if( !silent )
{
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
ae_bool testmannwhitneyu(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_bool waserrors;
ae_vector x;
ae_vector y;
ae_int_t testmin;
ae_int_t testmax;
ae_int_t testcnt;
ae_int_t pass;
ae_int_t n;
ae_int_t m;
ae_int_t i;
ae_int_t k;
double taill;
double tailr;
double tailb;
double taill1;
double tailr1;
double tailb1;
double taillprev;
double tailrprev;
double ebase;
double eshift;
ae_int_t ecnt;
double worsterr;
double v;
hqrndstate rs;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&y, 0, sizeof(y));
memset(&rs, 0, sizeof(rs));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&y, 0, DT_REAL, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
waserrors = ae_false;
hqrndrandomize(&rs, _state);
/*
* Test monotonicity of tail values for monotinically moving distributions.
*/
for(n=5; n<=20; n++)
{
for(m=5; m<=20; m++)
{
/*
* Generate uniform and sorted X/Y spanning [0,1]
*/
ae_vector_set_length(&x, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = (double)i/(double)(n-1)+100*ae_machineepsilon*hqrndnormal(&rs, _state);
}
ae_vector_set_length(&y, m, _state);
for(i=0; i<=m-1; i++)
{
y.ptr.p_double[i] = (double)i/(double)(m-1)+100*ae_machineepsilon*hqrndnormal(&rs, _state);
}
/*
* Test 100 values of E
*/
ecnt = 100;
ebase = -1.1;
eshift = -2*ebase/(ecnt-1);
tailrprev = (double)(0);
taillprev = (double)(1);
for(i=0; i<=m-1; i++)
{
y.ptr.p_double[i] = y.ptr.p_double[i]+ebase;
}
for(k=0; k<=ecnt-1; k++)
{
mannwhitneyutest(&x, n, &y, m, &tailb, &taill, &tailr, _state);
ae_set_error_flag(&waserrors, ae_fp_neq(tailb,2*ae_minreal(taill, tailr, _state)), __FILE__, __LINE__, "testmannwhitneyuunit.ap:57");
ae_set_error_flag(&waserrors, ae_fp_greater(tailrprev,tailr), __FILE__, __LINE__, "testmannwhitneyuunit.ap:58");
ae_set_error_flag(&waserrors, ae_fp_less(taillprev,taill), __FILE__, __LINE__, "testmannwhitneyuunit.ap:59");
tailrprev = tailr;
taillprev = taill;
for(i=0; i<=m-1; i++)
{
y.ptr.p_double[i] = y.ptr.p_double[i]+eshift;
}
}
}
}
/*
* Test frequency of p-value 0.05
*/
testmin = 5;
testmax = 50;
testcnt = 10000;
worsterr = 0.0;
for(n=testmin; n<=testmax; n++)
{
m = n+hqrnduniformi(&rs, testmax-n+1, _state);
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, m, _state);
/*
* Generate two uniformly distributed values, calculate p-value for both-tails, repeat
*/
k = 0;
for(pass=0; pass<=testcnt-1; pass++)
{
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = hqrnduniformr(&rs, _state);
}
for(i=0; i<=m-1; i++)
{
y.ptr.p_double[i] = hqrnduniformr(&rs, _state);
}
mannwhitneyutest(&x, n, &y, m, &tailb, &taill, &tailr, _state);
if( ae_fp_less(tailb,0.05) )
{
k = k+1;
}
}
v = ae_fabs((double)k/(double)testcnt-0.05, _state);
worsterr = ae_maxreal(worsterr, v, _state);
/*
* Test error in quantile; for different N's we have different tolerances
*/
if( n<10 )
{
ae_set_error_flag(&waserrors, ae_fp_greater(v,0.030), __FILE__, __LINE__, "testmannwhitneyuunit.ap:101");
}
else
{
if( n<15 )
{
ae_set_error_flag(&waserrors, ae_fp_greater(v,0.020), __FILE__, __LINE__, "testmannwhitneyuunit.ap:103");
}
else
{
if( n<30 )
{
ae_set_error_flag(&waserrors, ae_fp_greater(v,0.015), __FILE__, __LINE__, "testmannwhitneyuunit.ap:105");
}
else
{
ae_set_error_flag(&waserrors, ae_fp_greater(v,0.010), __FILE__, __LINE__, "testmannwhitneyuunit.ap:107");
}
}
}
}
/*
* Test symmetry properties
*/
for(n=5; n<=50; n++)
{
for(m=5; m<=50; m++)
{
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, m, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = hqrnduniformr(&rs, _state);
}
for(i=0; i<=m-1; i++)
{
y.ptr.p_double[i] = hqrnduniformr(&rs, _state);
}
mannwhitneyutest(&x, n, &y, m, &tailb, &taill, &tailr, _state);
mannwhitneyutest(&y, m, &x, n, &tailb1, &taill1, &tailr1, _state);
ae_set_error_flag(&waserrors, ae_fp_greater(ae_fabs(tailb-tailb1, _state),1.0E-12), __FILE__, __LINE__, "testmannwhitneyuunit.ap:126");
ae_set_error_flag(&waserrors, ae_fp_greater(ae_fabs(taill-tailr1, _state),1.0E-12), __FILE__, __LINE__, "testmannwhitneyuunit.ap:127");
ae_set_error_flag(&waserrors, ae_fp_greater(ae_fabs(tailr-taill1, _state),1.0E-12), __FILE__, __LINE__, "testmannwhitneyuunit.ap:128");
}
}
/*
* Test for integer overflow in the function: if one crucial
* calculation step is performed in 32-bit integer arithmetics,
* it will return incorrect results.
*
* We use special handcrafted N, such that in 32-bit integer
* arithmetics int32(N*N)<0. Such negative N leads to domain
* error in the sqrt() function.
*/
n = 50000;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&y, n, _state);
for(i=0; i<=n-1; i++)
{
x.ptr.p_double[i] = ae_sin((double)(10*i), _state);
y.ptr.p_double[i] = ae_sin((double)(13*i), _state);
}
mannwhitneyutest(&x, n, &y, n, &tailb, &taill, &tailr, _state);
ae_set_error_flag(&waserrors, !ae_isfinite(tailb, _state), __FILE__, __LINE__, "testmannwhitneyuunit.ap:149");
ae_set_error_flag(&waserrors, !ae_isfinite(taill, _state), __FILE__, __LINE__, "testmannwhitneyuunit.ap:150");
ae_set_error_flag(&waserrors, !ae_isfinite(tailr, _state), __FILE__, __LINE__, "testmannwhitneyuunit.ap:151");
/*
*
*/
if( !silent )
{
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
static void testschurunit_testschurproblem(/* Real */ ae_matrix* a,
ae_int_t n,
double* materr,
double* orterr,
ae_bool* errstruct,
ae_bool* wfailed,
ae_state *_state);
/*************************************************************************
Testing Schur decomposition subroutine
*************************************************************************/
ae_bool testschur(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_matrix a;
ae_int_t n;
ae_int_t maxn;
ae_int_t i;
ae_int_t j;
ae_int_t pass;
ae_int_t passcount;
ae_bool waserrors;
ae_bool errstruct;
ae_bool wfailed;
double materr;
double orterr;
double threshold;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
materr = (double)(0);
orterr = (double)(0);
errstruct = ae_false;
wfailed = ae_false;
waserrors = ae_false;
maxn = 70;
passcount = 1;
threshold = 5*100*ae_machineepsilon;
ae_matrix_set_length(&a, maxn-1+1, maxn-1+1, _state);
/*
* zero matrix, several cases
*/
for(i=0; i<=maxn-1; i++)
{
for(j=0; j<=maxn-1; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
for(n=1; n<=maxn; n++)
{
if( n>30&&n%2==0 )
{
continue;
}
testschurunit_testschurproblem(&a, n, &materr, &orterr, &errstruct, &wfailed, _state);
}
/*
* Dense matrix
*/
for(pass=1; pass<=passcount; pass++)
{
for(n=1; n<=maxn; n++)
{
if( n>30&&n%2==0 )
{
continue;
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
}
}
testschurunit_testschurproblem(&a, n, &materr, &orterr, &errstruct, &wfailed, _state);
}
}
/*
* report
*/
waserrors = ((ae_fp_greater(materr,threshold)||ae_fp_greater(orterr,threshold))||errstruct)||wfailed;
if( !silent )
{
printf("TESTING SCHUR DECOMPOSITION\n");
printf("Schur decomposition error: %5.3e\n",
(double)(materr));
printf("Schur orthogonality error: %5.3e\n",
(double)(orterr));
printf("T matrix structure: ");
if( !errstruct )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("Always converged: ");
if( !wfailed )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("Threshold: %5.3e\n",
(double)(threshold));
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
static void testschurunit_testschurproblem(/* Real */ ae_matrix* a,
ae_int_t n,
double* materr,
double* orterr,
ae_bool* errstruct,
ae_bool* wfailed,
ae_state *_state)
{
ae_frame _frame_block;
ae_matrix s;
ae_matrix t;
ae_vector sr;
ae_vector astc;
ae_vector sastc;
ae_int_t i;
ae_int_t j;
ae_int_t k;
double v;
double locerr;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&t, 0, sizeof(t));
memset(&sr, 0, sizeof(sr));
memset(&astc, 0, sizeof(astc));
memset(&sastc, 0, sizeof(sastc));
ae_matrix_init(&s, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&t, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&sr, 0, DT_REAL, _state, ae_true);
ae_vector_init(&astc, 0, DT_REAL, _state, ae_true);
ae_vector_init(&sastc, 0, DT_REAL, _state, ae_true);
ae_vector_set_length(&sr, n-1+1, _state);
ae_vector_set_length(&astc, n-1+1, _state);
ae_vector_set_length(&sastc, n-1+1, _state);
/*
* Schur decomposition, convergence test
*/
ae_matrix_set_length(&t, n-1+1, n-1+1, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
t.ptr.pp_double[i][j] = a->ptr.pp_double[i][j];
}
}
if( !rmatrixschur(&t, n, &s, _state) )
{
*wfailed = ae_true;
ae_frame_leave(_state);
return;
}
/*
* decomposition error
*/
locerr = (double)(0);
for(j=0; j<=n-1; j++)
{
ae_v_move(&sr.ptr.p_double[0], 1, &s.ptr.pp_double[j][0], 1, ae_v_len(0,n-1));
for(k=0; k<=n-1; k++)
{
v = ae_v_dotproduct(&t.ptr.pp_double[k][0], 1, &sr.ptr.p_double[0], 1, ae_v_len(0,n-1));
astc.ptr.p_double[k] = v;
}
for(k=0; k<=n-1; k++)
{
v = ae_v_dotproduct(&s.ptr.pp_double[k][0], 1, &astc.ptr.p_double[0], 1, ae_v_len(0,n-1));
sastc.ptr.p_double[k] = v;
}
for(k=0; k<=n-1; k++)
{
locerr = ae_maxreal(locerr, ae_fabs(sastc.ptr.p_double[k]-a->ptr.pp_double[k][j], _state), _state);
}
}
*materr = ae_maxreal(*materr, locerr, _state);
/*
* orthogonality error
*/
locerr = (double)(0);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
v = ae_v_dotproduct(&s.ptr.pp_double[0][i], s.stride, &s.ptr.pp_double[0][j], s.stride, ae_v_len(0,n-1));
if( i!=j )
{
locerr = ae_maxreal(locerr, ae_fabs(v, _state), _state);
}
else
{
locerr = ae_maxreal(locerr, ae_fabs(v-1, _state), _state);
}
}
}
*orterr = ae_maxreal(*orterr, locerr, _state);
/*
* T matrix structure
*/
for(j=0; j<=n-1; j++)
{
for(i=j+2; i<=n-1; i++)
{
if( ae_fp_neq(t.ptr.pp_double[i][j],(double)(0)) )
{
*errstruct = ae_true;
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Testing bidiagonal SVD decomposition subroutine
*************************************************************************/
ae_bool testspdgevd(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_int_t pass;
ae_int_t n;
ae_int_t passcount;
ae_int_t maxn;
ae_int_t atask;
ae_int_t btask;
ae_vector d;
ae_vector t1;
ae_matrix a;
ae_matrix b;
ae_matrix afull;
ae_matrix bfull;
ae_matrix l;
ae_matrix z;
ae_bool isuppera;
ae_bool isupperb;
ae_int_t i;
ae_int_t j;
ae_int_t minij;
double v;
double v1;
double v2;
double err;
double valerr;
double threshold;
ae_bool waserrors;
ae_bool wfailed;
ae_bool wnsorted;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&d, 0, sizeof(d));
memset(&t1, 0, sizeof(t1));
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
memset(&afull, 0, sizeof(afull));
memset(&bfull, 0, sizeof(bfull));
memset(&l, 0, sizeof(l));
memset(&z, 0, sizeof(z));
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&t1, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&b, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&afull, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&bfull, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&l, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&z, 0, 0, DT_REAL, _state, ae_true);
threshold = 10000*ae_machineepsilon;
valerr = (double)(0);
wfailed = ae_false;
wnsorted = ae_false;
maxn = 20;
passcount = 5;
/*
* Main cycle
*/
for(n=1; n<=maxn; n++)
{
for(pass=1; pass<=passcount; pass++)
{
for(atask=0; atask<=1; atask++)
{
for(btask=0; btask<=1; btask++)
{
isuppera = atask==0;
isupperb = btask==0;
/*
* Initialize A, B, AFull, BFull
*/
ae_vector_set_length(&t1, n-1+1, _state);
ae_matrix_set_length(&a, n-1+1, n-1+1, _state);
ae_matrix_set_length(&b, n-1+1, n-1+1, _state);
ae_matrix_set_length(&afull, n-1+1, n-1+1, _state);
ae_matrix_set_length(&bfull, n-1+1, n-1+1, _state);
ae_matrix_set_length(&l, n-1+1, n-1+1, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = 2*ae_randomreal(_state)-1;
a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j];
afull.ptr.pp_double[i][j] = a.ptr.pp_double[i][j];
afull.ptr.pp_double[j][i] = a.ptr.pp_double[i][j];
}
}
for(i=0; i<=n-1; i++)
{
for(j=i+1; j<=n-1; j++)
{
l.ptr.pp_double[i][j] = ae_randomreal(_state);
l.ptr.pp_double[j][i] = l.ptr.pp_double[i][j];
}
l.ptr.pp_double[i][i] = 1.5+ae_randomreal(_state);
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
minij = ae_minint(i, j, _state);
v = ae_v_dotproduct(&l.ptr.pp_double[i][0], 1, &l.ptr.pp_double[0][j], l.stride, ae_v_len(0,minij));
b.ptr.pp_double[i][j] = v;
b.ptr.pp_double[j][i] = v;
bfull.ptr.pp_double[i][j] = v;
bfull.ptr.pp_double[j][i] = v;
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( isuppera )
{
if( jptr.pp_double[i][j] = a->ptr.pp_double[i][j];
}
}
}
/*************************************************************************
LU decomposition
*************************************************************************/
static void testinverseupdateunit_matlu(/* Real */ ae_matrix* a,
ae_int_t m,
ae_int_t n,
/* Integer */ ae_vector* pivots,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
ae_int_t j;
ae_int_t jp;
ae_vector t1;
double s;
ae_frame_make(_state, &_frame_block);
memset(&t1, 0, sizeof(t1));
ae_vector_clear(pivots);
ae_vector_init(&t1, 0, DT_REAL, _state, ae_true);
ae_vector_set_length(pivots, ae_minint(m-1, n-1, _state)+1, _state);
ae_vector_set_length(&t1, ae_maxint(m-1, n-1, _state)+1, _state);
ae_assert(m>=0&&n>=0, "Error in LUDecomposition: incorrect function arguments", _state);
/*
* Quick return if possible
*/
if( m==0||n==0 )
{
ae_frame_leave(_state);
return;
}
for(j=0; j<=ae_minint(m-1, n-1, _state); j++)
{
/*
* Find pivot and test for singularity.
*/
jp = j;
for(i=j+1; i<=m-1; i++)
{
if( ae_fp_greater(ae_fabs(a->ptr.pp_double[i][j], _state),ae_fabs(a->ptr.pp_double[jp][j], _state)) )
{
jp = i;
}
}
pivots->ptr.p_int[j] = jp;
if( ae_fp_neq(a->ptr.pp_double[jp][j],(double)(0)) )
{
/*
*Apply the interchange to rows
*/
if( jp!=j )
{
ae_v_move(&t1.ptr.p_double[0], 1, &a->ptr.pp_double[j][0], 1, ae_v_len(0,n-1));
ae_v_move(&a->ptr.pp_double[j][0], 1, &a->ptr.pp_double[jp][0], 1, ae_v_len(0,n-1));
ae_v_move(&a->ptr.pp_double[jp][0], 1, &t1.ptr.p_double[0], 1, ae_v_len(0,n-1));
}
/*
*Compute elements J+1:M of J-th column.
*/
if( j+1ptr.pp_double[j][j];
ae_v_muld(&a->ptr.pp_double[jp][j], a->stride, ae_v_len(jp,m-1), s);
}
}
if( jptr.pp_double[i][j];
ae_v_subd(&a->ptr.pp_double[i][jp], 1, &a->ptr.pp_double[j][jp], 1, ae_v_len(jp,n-1), s);
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
Generate matrix with given condition number C (2-norm)
*************************************************************************/
static void testinverseupdateunit_generaterandomorthogonalmatrix(/* Real */ ae_matrix* a0,
ae_int_t n,
ae_state *_state)
{
ae_frame _frame_block;
double t;
double lambdav;
ae_int_t s;
ae_int_t i;
ae_int_t j;
double u1;
double u2;
ae_vector w;
ae_vector v;
ae_matrix a;
double sm;
ae_frame_make(_state, &_frame_block);
memset(&w, 0, sizeof(w));
memset(&v, 0, sizeof(v));
memset(&a, 0, sizeof(a));
ae_vector_init(&w, 0, DT_REAL, _state, ae_true);
ae_vector_init(&v, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
if( n<=0 )
{
ae_frame_leave(_state);
return;
}
ae_vector_set_length(&w, n+1, _state);
ae_vector_set_length(&v, n+1, _state);
ae_matrix_set_length(&a, n+1, n+1, _state);
ae_matrix_set_length(a0, n-1+1, n-1+1, _state);
/*
* Prepare A
*/
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
if( i==j )
{
a.ptr.pp_double[i][j] = (double)(1);
}
else
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
}
/*
* Calculate A using Stewart algorithm
*/
for(s=2; s<=n; s++)
{
/*
* Prepare v and Lambda = v'*v
*/
do
{
i = 1;
while(i<=s)
{
u1 = 2*ae_randomreal(_state)-1;
u2 = 2*ae_randomreal(_state)-1;
sm = u1*u1+u2*u2;
if( ae_fp_eq(sm,(double)(0))||ae_fp_greater(sm,(double)(1)) )
{
continue;
}
sm = ae_sqrt(-2*ae_log(sm, _state)/sm, _state);
v.ptr.p_double[i] = u1*sm;
if( i+1<=s )
{
v.ptr.p_double[i+1] = u2*sm;
}
i = i+2;
}
lambdav = ae_v_dotproduct(&v.ptr.p_double[1], 1, &v.ptr.p_double[1], 1, ae_v_len(1,s));
}
while(ae_fp_eq(lambdav,(double)(0)));
lambdav = 2/lambdav;
/*
* A * (I - 2 vv'/v'v ) =
* = A - (2/v'v) * A * v * v' =
* = A - (2/v'v) * w * v'
* where w = Av
*/
for(i=1; i<=s; i++)
{
t = ae_v_dotproduct(&a.ptr.pp_double[i][1], 1, &v.ptr.p_double[1], 1, ae_v_len(1,s));
w.ptr.p_double[i] = t;
}
for(i=1; i<=s; i++)
{
t = w.ptr.p_double[i]*lambdav;
ae_v_subd(&a.ptr.pp_double[i][1], 1, &v.ptr.p_double[1], 1, ae_v_len(1,s), t);
}
}
/*
*
*/
for(i=1; i<=n; i++)
{
for(j=1; j<=n; j++)
{
a0->ptr.pp_double[i-1][j-1] = a.ptr.pp_double[i][j];
}
}
ae_frame_leave(_state);
}
static void testinverseupdateunit_generaterandommatrixcond(/* Real */ ae_matrix* a0,
ae_int_t n,
double c,
ae_state *_state)
{
ae_frame _frame_block;
double l1;
double l2;
ae_matrix q1;
ae_matrix q2;
ae_vector cc;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_frame_make(_state, &_frame_block);
memset(&q1, 0, sizeof(q1));
memset(&q2, 0, sizeof(q2));
memset(&cc, 0, sizeof(cc));
ae_matrix_init(&q1, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&q2, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&cc, 0, DT_REAL, _state, ae_true);
testinverseupdateunit_generaterandomorthogonalmatrix(&q1, n, _state);
testinverseupdateunit_generaterandomorthogonalmatrix(&q2, n, _state);
ae_vector_set_length(&cc, n-1+1, _state);
l1 = (double)(0);
l2 = ae_log(1/c, _state);
cc.ptr.p_double[0] = ae_exp(l1, _state);
for(i=1; i<=n-2; i++)
{
cc.ptr.p_double[i] = ae_exp(ae_randomreal(_state)*(l2-l1)+l1, _state);
}
cc.ptr.p_double[n-1] = ae_exp(l2, _state);
ae_matrix_set_length(a0, n-1+1, n-1+1, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a0->ptr.pp_double[i][j] = (double)(0);
for(k=0; k<=n-1; k++)
{
a0->ptr.pp_double[i][j] = a0->ptr.pp_double[i][j]+q1.ptr.pp_double[i][k]*cc.ptr.p_double[k]*q2.ptr.pp_double[j][k];
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
triangular inverse
*************************************************************************/
static ae_bool testinverseupdateunit_invmattr(/* Real */ ae_matrix* a,
ae_int_t n,
ae_bool isupper,
ae_bool isunittriangular,
ae_state *_state)
{
ae_frame _frame_block;
ae_bool nounit;
ae_int_t i;
ae_int_t j;
double v;
double ajj;
ae_vector t;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&t, 0, sizeof(t));
ae_vector_init(&t, 0, DT_REAL, _state, ae_true);
result = ae_true;
ae_vector_set_length(&t, n-1+1, _state);
/*
* Test the input parameters.
*/
nounit = !isunittriangular;
if( isupper )
{
/*
* Compute inverse of upper triangular matrix.
*/
for(j=0; j<=n-1; j++)
{
if( nounit )
{
if( ae_fp_eq(a->ptr.pp_double[j][j],(double)(0)) )
{
result = ae_false;
ae_frame_leave(_state);
return result;
}
a->ptr.pp_double[j][j] = 1/a->ptr.pp_double[j][j];
ajj = -a->ptr.pp_double[j][j];
}
else
{
ajj = (double)(-1);
}
/*
* Compute elements 1:j-1 of j-th column.
*/
if( j>0 )
{
ae_v_move(&t.ptr.p_double[0], 1, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,j-1));
for(i=0; i<=j-1; i++)
{
if( iptr.pp_double[i][i+1], 1, &t.ptr.p_double[i+1], 1, ae_v_len(i+1,j-1));
}
else
{
v = (double)(0);
}
if( nounit )
{
a->ptr.pp_double[i][j] = v+a->ptr.pp_double[i][i]*t.ptr.p_double[i];
}
else
{
a->ptr.pp_double[i][j] = v+t.ptr.p_double[i];
}
}
ae_v_muld(&a->ptr.pp_double[0][j], a->stride, ae_v_len(0,j-1), ajj);
}
}
}
else
{
/*
* Compute inverse of lower triangular matrix.
*/
for(j=n-1; j>=0; j--)
{
if( nounit )
{
if( ae_fp_eq(a->ptr.pp_double[j][j],(double)(0)) )
{
result = ae_false;
ae_frame_leave(_state);
return result;
}
a->ptr.pp_double[j][j] = 1/a->ptr.pp_double[j][j];
ajj = -a->ptr.pp_double[j][j];
}
else
{
ajj = (double)(-1);
}
if( jptr.pp_double[j+1][j], a->stride, ae_v_len(j+1,n-1));
for(i=j+1; i<=n-1; i++)
{
if( i>j+1 )
{
v = ae_v_dotproduct(&a->ptr.pp_double[i][j+1], 1, &t.ptr.p_double[j+1], 1, ae_v_len(j+1,i-1));
}
else
{
v = (double)(0);
}
if( nounit )
{
a->ptr.pp_double[i][j] = v+a->ptr.pp_double[i][i]*t.ptr.p_double[i];
}
else
{
a->ptr.pp_double[i][j] = v+t.ptr.p_double[i];
}
}
ae_v_muld(&a->ptr.pp_double[j+1][j], a->stride, ae_v_len(j+1,n-1), ajj);
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
LU inverse
*************************************************************************/
static ae_bool testinverseupdateunit_invmatlu(/* Real */ ae_matrix* a,
/* Integer */ ae_vector* pivots,
ae_int_t n,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector work;
ae_int_t i;
ae_int_t j;
ae_int_t jp;
double v;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&work, 0, sizeof(work));
ae_vector_init(&work, 0, DT_REAL, _state, ae_true);
result = ae_true;
/*
* Quick return if possible
*/
if( n==0 )
{
ae_frame_leave(_state);
return result;
}
ae_vector_set_length(&work, n-1+1, _state);
/*
* Form inv(U)
*/
if( !testinverseupdateunit_invmattr(a, n, ae_true, ae_false, _state) )
{
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*
* Solve the equation inv(A)*L = inv(U) for inv(A).
*/
for(j=n-1; j>=0; j--)
{
/*
* Copy current column of L to WORK and replace with zeros.
*/
for(i=j+1; i<=n-1; i++)
{
work.ptr.p_double[i] = a->ptr.pp_double[i][j];
a->ptr.pp_double[i][j] = (double)(0);
}
/*
* Compute current column of inv(A).
*/
if( jptr.pp_double[i][j+1], 1, &work.ptr.p_double[j+1], 1, ae_v_len(j+1,n-1));
a->ptr.pp_double[i][j] = a->ptr.pp_double[i][j]-v;
}
}
}
/*
* Apply column interchanges.
*/
for(j=n-2; j>=0; j--)
{
jp = pivots->ptr.p_int[j];
if( jp!=j )
{
ae_v_move(&work.ptr.p_double[0], 1, &a->ptr.pp_double[0][j], a->stride, ae_v_len(0,n-1));
ae_v_move(&a->ptr.pp_double[0][j], a->stride, &a->ptr.pp_double[0][jp], a->stride, ae_v_len(0,n-1));
ae_v_move(&a->ptr.pp_double[0][jp], a->stride, &work.ptr.p_double[0], 1, ae_v_len(0,n-1));
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Matrix inverse
*************************************************************************/
static ae_bool testinverseupdateunit_invmat(/* Real */ ae_matrix* a,
ae_int_t n,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector pivots;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&pivots, 0, sizeof(pivots));
ae_vector_init(&pivots, 0, DT_INT, _state, ae_true);
testinverseupdateunit_matlu(a, n, n, &pivots, _state);
result = testinverseupdateunit_invmatlu(a, &pivots, n, _state);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Diff
*************************************************************************/
static double testinverseupdateunit_matrixdiff(/* Real */ ae_matrix* a,
/* Real */ ae_matrix* b,
ae_int_t m,
ae_int_t n,
ae_state *_state)
{
ae_int_t i;
ae_int_t j;
double result;
result = (double)(0);
for(i=0; i<=m-1; i++)
{
for(j=0; j<=n-1; j++)
{
result = ae_maxreal(result, ae_fabs(b->ptr.pp_double[i][j]-a->ptr.pp_double[i][j], _state), _state);
}
}
return result;
}
/*************************************************************************
Update and inverse
*************************************************************************/
static ae_bool testinverseupdateunit_updandinv(/* Real */ ae_matrix* a,
/* Real */ ae_vector* u,
/* Real */ ae_vector* v,
ae_int_t n,
ae_state *_state)
{
ae_frame _frame_block;
ae_vector pivots;
ae_int_t i;
double r;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&pivots, 0, sizeof(pivots));
ae_vector_init(&pivots, 0, DT_INT, _state, ae_true);
for(i=0; i<=n-1; i++)
{
r = u->ptr.p_double[i];
ae_v_addd(&a->ptr.pp_double[i][0], 1, &v->ptr.p_double[0], 1, ae_v_len(0,n-1), r);
}
testinverseupdateunit_matlu(a, n, n, &pivots, _state);
result = testinverseupdateunit_invmatlu(a, &pivots, n, _state);
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Test
*************************************************************************/
ae_bool testpolynomialsolver(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_bool wereerrors;
ae_vector a;
ae_vector x;
double eps;
ae_int_t n;
polynomialsolverreport rep;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&x, 0, sizeof(x));
memset(&rep, 0, sizeof(rep));
ae_vector_init(&a, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x, 0, DT_COMPLEX, _state, ae_true);
_polynomialsolverreport_init(&rep, _state, ae_true);
wereerrors = ae_false;
/*
* Basic tests
*/
eps = 1.0E-6;
n = 1;
ae_vector_set_length(&a, n+1, _state);
a.ptr.p_double[0] = (double)(2);
a.ptr.p_double[1] = (double)(3);
polynomialsolve(&a, n, &x, &rep, _state);
ae_set_error_flag(&wereerrors, ae_fp_greater(ae_fabs(x.ptr.p_complex[0].x+(double)2/(double)3, _state),eps), __FILE__, __LINE__, "testpolynomialsolverunit.ap:33");
ae_set_error_flag(&wereerrors, ae_fp_neq(x.ptr.p_complex[0].y,(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:34");
ae_set_error_flag(&wereerrors, ae_fp_greater(rep.maxerr,100*ae_machineepsilon), __FILE__, __LINE__, "testpolynomialsolverunit.ap:35");
n = 2;
ae_vector_set_length(&a, n+1, _state);
a.ptr.p_double[0] = (double)(1);
a.ptr.p_double[1] = (double)(-2);
a.ptr.p_double[2] = (double)(1);
polynomialsolve(&a, n, &x, &rep, _state);
ae_set_error_flag(&wereerrors, ae_fp_greater(ae_c_abs(ae_c_sub_d(x.ptr.p_complex[0],1), _state),eps), __FILE__, __LINE__, "testpolynomialsolverunit.ap:43");
ae_set_error_flag(&wereerrors, ae_fp_greater(ae_c_abs(ae_c_sub_d(x.ptr.p_complex[1],1), _state),eps), __FILE__, __LINE__, "testpolynomialsolverunit.ap:44");
ae_set_error_flag(&wereerrors, ae_fp_greater(rep.maxerr,100*ae_machineepsilon), __FILE__, __LINE__, "testpolynomialsolverunit.ap:45");
n = 2;
ae_vector_set_length(&a, n+1, _state);
a.ptr.p_double[0] = (double)(2);
a.ptr.p_double[1] = (double)(-3);
a.ptr.p_double[2] = (double)(1);
polynomialsolve(&a, n, &x, &rep, _state);
if( ae_fp_less(x.ptr.p_complex[0].x,x.ptr.p_complex[1].x) )
{
ae_set_error_flag(&wereerrors, ae_fp_greater(ae_fabs(x.ptr.p_complex[0].x-1, _state),eps), __FILE__, __LINE__, "testpolynomialsolverunit.ap:55");
ae_set_error_flag(&wereerrors, ae_fp_greater(ae_fabs(x.ptr.p_complex[1].x-2, _state),eps), __FILE__, __LINE__, "testpolynomialsolverunit.ap:56");
}
else
{
ae_set_error_flag(&wereerrors, ae_fp_greater(ae_fabs(x.ptr.p_complex[0].x-2, _state),eps), __FILE__, __LINE__, "testpolynomialsolverunit.ap:60");
ae_set_error_flag(&wereerrors, ae_fp_greater(ae_fabs(x.ptr.p_complex[1].x-1, _state),eps), __FILE__, __LINE__, "testpolynomialsolverunit.ap:61");
}
ae_set_error_flag(&wereerrors, ae_fp_neq(x.ptr.p_complex[0].y,(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:63");
ae_set_error_flag(&wereerrors, ae_fp_neq(x.ptr.p_complex[1].y,(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:64");
ae_set_error_flag(&wereerrors, ae_fp_greater(rep.maxerr,100*ae_machineepsilon), __FILE__, __LINE__, "testpolynomialsolverunit.ap:65");
n = 2;
ae_vector_set_length(&a, n+1, _state);
a.ptr.p_double[0] = (double)(1);
a.ptr.p_double[1] = (double)(0);
a.ptr.p_double[2] = (double)(1);
polynomialsolve(&a, n, &x, &rep, _state);
ae_set_error_flag(&wereerrors, ae_fp_greater(ae_c_abs(ae_c_add_d(ae_c_mul(x.ptr.p_complex[0],x.ptr.p_complex[0]),(double)(1)), _state),eps), __FILE__, __LINE__, "testpolynomialsolverunit.ap:73");
ae_set_error_flag(&wereerrors, ae_fp_greater(rep.maxerr,100*ae_machineepsilon), __FILE__, __LINE__, "testpolynomialsolverunit.ap:74");
n = 4;
ae_vector_set_length(&a, n+1, _state);
a.ptr.p_double[0] = (double)(0);
a.ptr.p_double[1] = (double)(0);
a.ptr.p_double[2] = (double)(0);
a.ptr.p_double[3] = (double)(0);
a.ptr.p_double[4] = (double)(1);
polynomialsolve(&a, n, &x, &rep, _state);
ae_set_error_flag(&wereerrors, ae_c_neq_d(x.ptr.p_complex[0],(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:84");
ae_set_error_flag(&wereerrors, ae_c_neq_d(x.ptr.p_complex[1],(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:85");
ae_set_error_flag(&wereerrors, ae_c_neq_d(x.ptr.p_complex[2],(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:86");
ae_set_error_flag(&wereerrors, ae_c_neq_d(x.ptr.p_complex[3],(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:87");
ae_set_error_flag(&wereerrors, ae_fp_greater(rep.maxerr,100*ae_machineepsilon), __FILE__, __LINE__, "testpolynomialsolverunit.ap:88");
n = 2;
ae_vector_set_length(&a, n+1, _state);
a.ptr.p_double[0] = (double)(0);
a.ptr.p_double[1] = (double)(3);
a.ptr.p_double[2] = (double)(2);
polynomialsolve(&a, n, &x, &rep, _state);
if( ae_fp_greater(x.ptr.p_complex[0].x,x.ptr.p_complex[1].x) )
{
ae_set_error_flag(&wereerrors, ae_c_neq_d(x.ptr.p_complex[0],(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:98");
ae_set_error_flag(&wereerrors, ae_fp_greater(ae_fabs(x.ptr.p_complex[1].x+(double)3/(double)2, _state),eps), __FILE__, __LINE__, "testpolynomialsolverunit.ap:99");
ae_set_error_flag(&wereerrors, ae_fp_neq(x.ptr.p_complex[1].y,(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:100");
}
else
{
ae_set_error_flag(&wereerrors, ae_c_neq_d(x.ptr.p_complex[1],(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:104");
ae_set_error_flag(&wereerrors, ae_fp_greater(ae_fabs(x.ptr.p_complex[0].x+(double)3/(double)2, _state),eps), __FILE__, __LINE__, "testpolynomialsolverunit.ap:105");
ae_set_error_flag(&wereerrors, ae_fp_neq(x.ptr.p_complex[0].y,(double)(0)), __FILE__, __LINE__, "testpolynomialsolverunit.ap:106");
}
ae_set_error_flag(&wereerrors, ae_fp_greater(rep.maxerr,100*ae_machineepsilon), __FILE__, __LINE__, "testpolynomialsolverunit.ap:108");
if( !silent )
{
printf("TESTING POLYNOMIAL SOLVER\n");
if( wereerrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
}
result = !wereerrors;
ae_frame_leave(_state);
return result;
}
static void testnlequnit_testfunchbm(nleqstate* state, ae_state *_state);
static void testnlequnit_testfunchb1(nleqstate* state, ae_state *_state);
static void testnlequnit_testfuncshbm(nleqstate* state, ae_state *_state);
ae_bool testnleq(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
ae_bool waserrors;
ae_bool basicserrors;
ae_bool converror;
ae_bool othererrors;
ae_int_t n;
ae_vector x;
ae_int_t i;
ae_int_t k;
double v;
double flast;
ae_vector xlast;
ae_bool firstrep;
ae_int_t nfunc;
ae_int_t njac;
ae_int_t itcnt;
nleqstate state;
nleqreport rep;
ae_int_t pass;
ae_int_t passcount;
double epsf;
double stpmax;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&x, 0, sizeof(x));
memset(&xlast, 0, sizeof(xlast));
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
ae_vector_init(&x, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xlast, 0, DT_REAL, _state, ae_true);
_nleqstate_init(&state, _state, ae_true);
_nleqreport_init(&rep, _state, ae_true);
waserrors = ae_false;
basicserrors = ae_false;
converror = ae_false;
othererrors = ae_false;
/*
* Basic tests
*
* Test with Himmelblau's function (M):
* * ability to find correct result
* * ability to work after soft restart (restart after finish)
* * ability to work after hard restart (restart in the middle of optimization)
*/
passcount = 100;
for(pass=0; pass<=passcount-1; pass++)
{
/*
* Ability to find correct result
*/
ae_vector_set_length(&x, 2, _state);
x.ptr.p_double[0] = 20*ae_randomreal(_state)-10;
x.ptr.p_double[1] = 20*ae_randomreal(_state)-10;
nleqcreatelm(2, 2, &x, &state, _state);
epsf = 1.0E-9;
nleqsetcond(&state, epsf, 0, _state);
while(nleqiteration(&state, _state))
{
testnlequnit_testfunchbm(&state, _state);
}
nleqresults(&state, &x, &rep, _state);
if( rep.terminationtype>0 )
{
basicserrors = basicserrors||ae_fp_greater(ae_sqr(x.ptr.p_double[0]*x.ptr.p_double[0]+x.ptr.p_double[1]-11, _state)+ae_sqr(x.ptr.p_double[0]+x.ptr.p_double[1]*x.ptr.p_double[1]-7, _state),ae_sqr(epsf, _state));
}
else
{
basicserrors = ae_true;
}
/*
* Ability to work after soft restart
*/
ae_vector_set_length(&x, 2, _state);
x.ptr.p_double[0] = 20*ae_randomreal(_state)-10;
x.ptr.p_double[1] = 20*ae_randomreal(_state)-10;
nleqcreatelm(2, 2, &x, &state, _state);
epsf = 1.0E-9;
nleqsetcond(&state, epsf, 0, _state);
while(nleqiteration(&state, _state))
{
testnlequnit_testfunchbm(&state, _state);
}
nleqresults(&state, &x, &rep, _state);
ae_vector_set_length(&x, 2, _state);
x.ptr.p_double[0] = 20*ae_randomreal(_state)-10;
x.ptr.p_double[1] = 20*ae_randomreal(_state)-10;
nleqrestartfrom(&state, &x, _state);
while(nleqiteration(&state, _state))
{
testnlequnit_testfunchbm(&state, _state);
}
nleqresults(&state, &x, &rep, _state);
if( rep.terminationtype>0 )
{
basicserrors = basicserrors||ae_fp_greater(ae_sqr(x.ptr.p_double[0]*x.ptr.p_double[0]+x.ptr.p_double[1]-11, _state)+ae_sqr(x.ptr.p_double[0]+x.ptr.p_double[1]*x.ptr.p_double[1]-7, _state),ae_sqr(epsf, _state));
}
else
{
basicserrors = ae_true;
}
/*
* Ability to work after hard restart:
* * stopping condition: small F
* * StpMax is so small that we need about 10000 iterations to
* find solution (steps are small)
* * choose random K significantly less that 9999
* * iterate for some time, then break, restart optimization
*/
ae_vector_set_length(&x, 2, _state);
x.ptr.p_double[0] = (double)(100);
x.ptr.p_double[1] = (double)(100);
nleqcreatelm(2, 2, &x, &state, _state);
epsf = 1.0E-9;
nleqsetcond(&state, epsf, 0, _state);
nleqsetstpmax(&state, 0.01, _state);
k = 1+ae_randominteger(100, _state);
for(i=0; i<=k-1; i++)
{
if( !nleqiteration(&state, _state) )
{
break;
}
testnlequnit_testfunchbm(&state, _state);
}
ae_vector_set_length(&x, 2, _state);
x.ptr.p_double[0] = 20*ae_randomreal(_state)-10;
x.ptr.p_double[1] = 20*ae_randomreal(_state)-10;
nleqrestartfrom(&state, &x, _state);
while(nleqiteration(&state, _state))
{
testnlequnit_testfunchbm(&state, _state);
}
nleqresults(&state, &x, &rep, _state);
if( rep.terminationtype>0 )
{
basicserrors = basicserrors||ae_fp_greater(ae_sqr(x.ptr.p_double[0]*x.ptr.p_double[0]+x.ptr.p_double[1]-11, _state)+ae_sqr(x.ptr.p_double[0]+x.ptr.p_double[1]*x.ptr.p_double[1]-7, _state),ae_sqr(epsf, _state));
}
else
{
basicserrors = ae_true;
}
}
/*
* Basic tests
*
* Test with Himmelblau's function (1):
* * ability to find correct result
*/
passcount = 100;
for(pass=0; pass<=passcount-1; pass++)
{
/*
* Ability to find correct result
*/
ae_vector_set_length(&x, 2, _state);
x.ptr.p_double[0] = 20*ae_randomreal(_state)-10;
x.ptr.p_double[1] = 20*ae_randomreal(_state)-10;
nleqcreatelm(2, 1, &x, &state, _state);
epsf = 1.0E-9;
nleqsetcond(&state, epsf, 0, _state);
while(nleqiteration(&state, _state))
{
testnlequnit_testfunchb1(&state, _state);
}
nleqresults(&state, &x, &rep, _state);
if( rep.terminationtype>0 )
{
basicserrors = basicserrors||ae_fp_greater(ae_sqr(x.ptr.p_double[0]*x.ptr.p_double[0]+x.ptr.p_double[1]-11, _state)+ae_sqr(x.ptr.p_double[0]+x.ptr.p_double[1]*x.ptr.p_double[1]-7, _state),epsf);
}
else
{
basicserrors = ae_true;
}
}
/*
* Basic tests
*
* Ability to detect situation when we can't find minimum
*/
passcount = 100;
for(pass=0; pass<=passcount-1; pass++)
{
ae_vector_set_length(&x, 2, _state);
x.ptr.p_double[0] = 20*ae_randomreal(_state)-10;
x.ptr.p_double[1] = 20*ae_randomreal(_state)-10;
nleqcreatelm(2, 3, &x, &state, _state);
epsf = 1.0E-9;
nleqsetcond(&state, epsf, 0, _state);
while(nleqiteration(&state, _state))
{
testnlequnit_testfuncshbm(&state, _state);
}
nleqresults(&state, &x, &rep, _state);
basicserrors = basicserrors||rep.terminationtype!=-4;
}
/*
* Test correctness of intermediate reports and final report:
* * first report is starting point
* * function value decreases on subsequent reports
* * function value is correctly reported
* * last report is final point
* * NFunc and NJac are compared with values counted directly
* * IterationsCount is compared with value counter directly
*/
n = 2;
ae_vector_set_length(&x, n, _state);
ae_vector_set_length(&xlast, n, _state);
x.ptr.p_double[0] = 20*ae_randomreal(_state)-10;
x.ptr.p_double[1] = 20*ae_randomreal(_state)-10;
xlast.ptr.p_double[0] = ae_maxrealnumber;
xlast.ptr.p_double[1] = ae_maxrealnumber;
nleqcreatelm(n, 2, &x, &state, _state);
nleqsetcond(&state, 1.0E-6, 0, _state);
nleqsetxrep(&state, ae_true, _state);
firstrep = ae_true;
flast = ae_maxrealnumber;
nfunc = 0;
njac = 0;
itcnt = 0;
while(nleqiteration(&state, _state))
{
if( state.xupdated )
{
/*
* first report must be starting point
*/
if( firstrep )
{
for(i=0; i<=n-1; i++)
{
othererrors = othererrors||ae_fp_neq(state.x.ptr.p_double[i],x.ptr.p_double[i]);
}
firstrep = ae_false;
}
/*
* function value must decrease
*/
othererrors = othererrors||ae_fp_greater(state.f,flast);
/*
* check correctness of function value
*/
v = ae_sqr(state.x.ptr.p_double[0]*state.x.ptr.p_double[0]+state.x.ptr.p_double[1]-11, _state)+ae_sqr(state.x.ptr.p_double[0]+state.x.ptr.p_double[1]*state.x.ptr.p_double[1]-7, _state);
othererrors = othererrors||ae_fp_greater(ae_fabs(v-state.f, _state)/ae_maxreal(v, (double)(1), _state),100*ae_machineepsilon);
/*
* update info and continue
*/
ae_v_move(&xlast.ptr.p_double[0], 1, &state.x.ptr.p_double[0], 1, ae_v_len(0,n-1));
flast = state.f;
itcnt = itcnt+1;
continue;
}
if( state.needf )
{
nfunc = nfunc+1;
}
if( state.needfij )
{
nfunc = nfunc+1;
njac = njac+1;
}
testnlequnit_testfunchbm(&state, _state);
}
nleqresults(&state, &x, &rep, _state);
if( rep.terminationtype>0 )
{
othererrors = (othererrors||ae_fp_neq(xlast.ptr.p_double[0],x.ptr.p_double[0]))||ae_fp_neq(xlast.ptr.p_double[1],x.ptr.p_double[1]);
v = ae_sqr(x.ptr.p_double[0]*x.ptr.p_double[0]+x.ptr.p_double[1]-11, _state)+ae_sqr(x.ptr.p_double[0]+x.ptr.p_double[1]*x.ptr.p_double[1]-7, _state);
othererrors = othererrors||ae_fp_greater(ae_fabs(flast-v, _state)/ae_maxreal(v, (double)(1), _state),100*ae_machineepsilon);
}
else
{
converror = ae_true;
}
othererrors = othererrors||rep.nfunc!=nfunc;
othererrors = othererrors||rep.njac!=njac;
othererrors = othererrors||rep.iterationscount!=itcnt-1;
/*
* Test ability to set limit on algorithm steps
*/
ae_vector_set_length(&x, 2, _state);
ae_vector_set_length(&xlast, 2, _state);
x.ptr.p_double[0] = 20*ae_randomreal(_state)+20;
x.ptr.p_double[1] = 20*ae_randomreal(_state)+20;
xlast.ptr.p_double[0] = x.ptr.p_double[0];
xlast.ptr.p_double[1] = x.ptr.p_double[1];
stpmax = 0.1+0.1*ae_randomreal(_state);
epsf = 1.0E-9;
nleqcreatelm(2, 2, &x, &state, _state);
nleqsetstpmax(&state, stpmax, _state);
nleqsetcond(&state, epsf, 0, _state);
nleqsetxrep(&state, ae_true, _state);
while(nleqiteration(&state, _state))
{
if( state.needf||state.needfij )
{
testnlequnit_testfunchbm(&state, _state);
}
if( (state.needf||state.needfij)||state.xupdated )
{
othererrors = othererrors||ae_fp_greater(ae_sqrt(ae_sqr(state.x.ptr.p_double[0]-xlast.ptr.p_double[0], _state)+ae_sqr(state.x.ptr.p_double[1]-xlast.ptr.p_double[1], _state), _state),1.00001*stpmax);
}
if( state.xupdated )
{
xlast.ptr.p_double[0] = state.x.ptr.p_double[0];
xlast.ptr.p_double[1] = state.x.ptr.p_double[1];
}
}
/*
* end
*/
waserrors = (basicserrors||converror)||othererrors;
if( !silent )
{
printf("TESTING NLEQ SOLVER\n");
printf("BASIC FUNCTIONALITY: ");
if( basicserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("CONVERGENCE: ");
if( converror )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("OTHER PROPERTIES: ");
if( othererrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Himmelblau's function
F = (x^2+y-11)^2 + (x+y^2-7)^2
posed as system of M functions:
f0 = x^2+y-11
f1 = x+y^2-7
*************************************************************************/
static void testnlequnit_testfunchbm(nleqstate* state, ae_state *_state)
{
double x;
double y;
ae_assert(state->needf||state->needfij, "TestNLEQUnit: internal error!", _state);
x = state->x.ptr.p_double[0];
y = state->x.ptr.p_double[1];
if( state->needf )
{
state->f = ae_sqr(x*x+y-11, _state)+ae_sqr(x+y*y-7, _state);
return;
}
if( state->needfij )
{
state->fi.ptr.p_double[0] = x*x+y-11;
state->fi.ptr.p_double[1] = x+y*y-7;
state->j.ptr.pp_double[0][0] = 2*x;
state->j.ptr.pp_double[0][1] = (double)(1);
state->j.ptr.pp_double[1][0] = (double)(1);
state->j.ptr.pp_double[1][1] = 2*y;
return;
}
}
/*************************************************************************
Himmelblau's function
F = (x^2+y-11)^2 + (x+y^2-7)^2
posed as system of 1 function
*************************************************************************/
static void testnlequnit_testfunchb1(nleqstate* state, ae_state *_state)
{
double x;
double y;
ae_assert(state->needf||state->needfij, "TestNLEQUnit: internal error!", _state);
x = state->x.ptr.p_double[0];
y = state->x.ptr.p_double[1];
if( state->needf )
{
state->f = ae_sqr(ae_sqr(x*x+y-11, _state)+ae_sqr(x+y*y-7, _state), _state);
return;
}
if( state->needfij )
{
state->fi.ptr.p_double[0] = ae_sqr(x*x+y-11, _state)+ae_sqr(x+y*y-7, _state);
state->j.ptr.pp_double[0][0] = 2*(x*x+y-11)*2*x+2*(x+y*y-7);
state->j.ptr.pp_double[0][1] = 2*(x*x+y-11)+2*(x+y*y-7)*2*y;
return;
}
}
/*************************************************************************
Shifted Himmelblau's function
F = (x^2+y-11)^2 + (x+y^2-7)^2 + 1
posed as system of M functions:
f0 = x^2+y-11
f1 = x+y^2-7
f2 = 1
This function is used to test algorithm on problem which has no solution.
*************************************************************************/
static void testnlequnit_testfuncshbm(nleqstate* state, ae_state *_state)
{
double x;
double y;
ae_assert(state->needf||state->needfij, "TestNLEQUnit: internal error!", _state);
x = state->x.ptr.p_double[0];
y = state->x.ptr.p_double[1];
if( state->needf )
{
state->f = ae_sqr(x*x+y-11, _state)+ae_sqr(x+y*y-7, _state)+1;
return;
}
if( state->needfij )
{
state->fi.ptr.p_double[0] = x*x+y-11;
state->fi.ptr.p_double[1] = x+y*y-7;
state->fi.ptr.p_double[2] = (double)(1);
state->j.ptr.pp_double[0][0] = 2*x;
state->j.ptr.pp_double[0][1] = (double)(1);
state->j.ptr.pp_double[1][0] = (double)(1);
state->j.ptr.pp_double[1][1] = 2*y;
state->j.ptr.pp_double[2][0] = (double)(0);
state->j.ptr.pp_double[2][1] = (double)(0);
return;
}
}
static void testdirectsparsesolversunit_testsks(ae_bool* errorflag,
ae_state *_state);
static void testdirectsparsesolversunit_testgen(ae_bool* errorflag,
ae_state *_state);
/*************************************************************************
Test
*************************************************************************/
ae_bool testdirectsparsesolvers(ae_bool silent, ae_state *_state)
{
ae_bool rskserrors;
ae_bool rgenerrors;
ae_bool wereerrors;
ae_bool result;
rskserrors = ae_false;
rgenerrors = ae_false;
testdirectsparsesolversunit_testsks(&rskserrors, _state);
testdirectsparsesolversunit_testgen(&rgenerrors, _state);
wereerrors = rskserrors||rgenerrors;
if( !silent )
{
printf("TESTING DIRECT SPARSE SOLVERS:\n");
printf("* SKS (real) ");
if( rskserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("* GENERAL (real) ");
if( rgenerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
if( wereerrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
}
result = !wereerrors;
return result;
}
/*************************************************************************
SPD SKS test
*************************************************************************/
static void testdirectsparsesolversunit_testsks(ae_bool* errorflag,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t pass;
ae_int_t passcount;
ae_int_t maxn;
double threshold;
ae_int_t bw;
ae_bool isupper;
ae_int_t n;
ae_int_t i;
ae_int_t j;
ae_matrix a;
ae_vector xe;
ae_vector b;
ae_vector xs;
sparsematrix sa;
sparsematrix sa2;
sparsesolverreport rep;
hqrndstate rs;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&xe, 0, sizeof(xe));
memset(&b, 0, sizeof(b));
memset(&xs, 0, sizeof(xs));
memset(&sa, 0, sizeof(sa));
memset(&sa2, 0, sizeof(sa2));
memset(&rep, 0, sizeof(rep));
memset(&rs, 0, sizeof(rs));
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xe, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xs, 0, DT_REAL, _state, ae_true);
_sparsematrix_init(&sa, _state, ae_true);
_sparsematrix_init(&sa2, _state, ae_true);
_sparsesolverreport_init(&rep, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
passcount = 10;
maxn = 30;
threshold = 1.0E-6;
hqrndrandomize(&rs, _state);
/*
* Well conditioned SPD problems solved with SKS solver
*/
for(n=1; n<=maxn; n++)
{
for(pass=1; pass<=passcount; pass++)
{
/*
* 1. generate random well conditioned matrix A.
* 2. generate random solution vector xe
* 3. generate right part b=A*xe
*/
isupper = ae_fp_greater(hqrndnormal(&rs, _state),0.5);
bw = hqrnduniformi(&rs, n+1, _state);
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
sparsecreate(n, n, 0, &sa, _state);
for(i=0; i<=n-1; i++)
{
a.ptr.pp_double[i][i] = 1+hqrnduniformr(&rs, _state);
sparseset(&sa, i, i, a.ptr.pp_double[i][i], _state);
for(j=i+1; j<=ae_minint(i+bw, n-1, _state); j++)
{
a.ptr.pp_double[i][j] = (hqrnduniformr(&rs, _state)-0.5)/n;
a.ptr.pp_double[j][i] = a.ptr.pp_double[i][j];
if( isupper )
{
sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state);
}
else
{
sparseset(&sa, j, i, a.ptr.pp_double[i][j], _state);
}
}
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( (ji&&!isupper) )
{
if( ae_fp_less(hqrnduniformr(&rs, _state),0.25) )
{
sparseset(&sa, i, j, hqrndnormal(&rs, _state), _state);
}
}
}
}
sparseconvertto(&sa, hqrnduniformi(&rs, 3, _state), _state);
ae_vector_set_length(&xe, n, _state);
for(i=0; i<=n-1; i++)
{
xe.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&b, n, _state);
rmatrixgemv(n, n, 1.0, &a, 0, 0, 0, &xe, 0, 0.0, &b, 0, _state);
/*
* Test solver #1
*/
ae_vector_set_length(&xs, 0, _state);
sparsesolvesks(&sa, n, isupper, &b, &rep, &xs, _state);
ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testdirectsparsesolversunit.ap:98");
ae_set_error_flag(errorflag, xs.cnt!=n, __FILE__, __LINE__, "testdirectsparsesolversunit.ap:99");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-xs.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testdirectsparsesolversunit.ap:103");
}
/*
* Test solver #2
*/
sparsecopytosks(&sa, &sa2, _state);
if( !sparsecholeskyskyline(&sa2, n, isupper, _state) )
{
ae_set_error_flag(errorflag, ae_true, __FILE__, __LINE__, "testdirectsparsesolversunit.ap:112");
ae_frame_leave(_state);
return;
}
ae_vector_set_length(&xs, 0, _state);
sparsecholeskysolvesks(&sa2, n, isupper, &b, &rep, &xs, _state);
ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testdirectsparsesolversunit.ap:117");
ae_set_error_flag(errorflag, xs.cnt!=n, __FILE__, __LINE__, "testdirectsparsesolversunit.ap:118");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-xs.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testdirectsparsesolversunit.ap:122");
}
}
}
ae_frame_leave(_state);
}
/*************************************************************************
General linear test
*************************************************************************/
static void testdirectsparsesolversunit_testgen(ae_bool* errorflag,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t pass;
ae_int_t passcount;
ae_int_t maxn;
double threshold;
ae_int_t n;
ae_int_t noffdiag;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_matrix a;
ae_vector xe;
ae_vector b;
ae_vector xs;
ae_vector xs2;
ae_vector pivp;
ae_vector pivq;
sparsematrix sa;
sparsematrix sa2;
sparsesolverreport rep;
hqrndstate rs;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&xe, 0, sizeof(xe));
memset(&b, 0, sizeof(b));
memset(&xs, 0, sizeof(xs));
memset(&xs2, 0, sizeof(xs2));
memset(&pivp, 0, sizeof(pivp));
memset(&pivq, 0, sizeof(pivq));
memset(&sa, 0, sizeof(sa));
memset(&sa2, 0, sizeof(sa2));
memset(&rep, 0, sizeof(rep));
memset(&rs, 0, sizeof(rs));
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xe, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xs, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xs2, 0, DT_REAL, _state, ae_true);
ae_vector_init(&pivp, 0, DT_INT, _state, ae_true);
ae_vector_init(&pivq, 0, DT_INT, _state, ae_true);
_sparsematrix_init(&sa, _state, ae_true);
_sparsematrix_init(&sa2, _state, ae_true);
_sparsesolverreport_init(&rep, _state, ae_true);
_hqrndstate_init(&rs, _state, ae_true);
passcount = 10;
maxn = 30;
threshold = 1.0E-6;
hqrndrandomize(&rs, _state);
/*
* Well conditioned general linear problems solved with LU solver
*/
for(n=1; n<=maxn; n++)
{
for(pass=1; pass<=passcount; pass++)
{
/*
* Select number of off-diagonal entries, we want to try matrices
* from dense to sparse
*/
noffdiag = n*(n-1);
for(;;)
{
/*
* 1. generate random well conditioned matrix A.
* 2. apply row/col permutation
* 3. generate random solution vector xe
* 4. generate right part b=A*xe
*/
ae_matrix_set_length(&a, n, n, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = (double)(0);
}
}
for(k=0; k<=noffdiag-1; k++)
{
i = hqrnduniformi(&rs, n, _state);
j = hqrnduniformi(&rs, n, _state);
a.ptr.pp_double[i][j] = 0.01*hqrndnormal(&rs, _state)/n;
}
for(i=0; i<=n-1; i++)
{
a.ptr.pp_double[i][i] = 1.0+ae_pow((double)(2), hqrndnormal(&rs, _state), _state);
}
for(i=0; i<=n-1; i++)
{
swaprows(&a, i, i+hqrnduniformi(&rs, n-i, _state), n, _state);
}
for(i=0; i<=n-1; i++)
{
swapcols(&a, i, i+hqrnduniformi(&rs, n-i, _state), n, _state);
}
sparsecreate(n, n, 0, &sa, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state);
}
}
sparseconvertto(&sa, hqrnduniformi(&rs, 3, _state), _state);
ae_vector_set_length(&xe, n, _state);
for(i=0; i<=n-1; i++)
{
xe.ptr.p_double[i] = hqrndnormal(&rs, _state);
}
ae_vector_set_length(&b, n, _state);
rmatrixgemv(n, n, 1.0, &a, 0, 0, 0, &xe, 0, 0.0, &b, 0, _state);
/*
* Test solver #1
*/
ae_vector_set_length(&xs, 0, _state);
sparsesolve(&sa, n, &b, &xs, &rep, _state);
ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testdirectsparsesolversunit.ap:206");
ae_set_error_flag(errorflag, xs.cnt!=n, __FILE__, __LINE__, "testdirectsparsesolversunit.ap:207");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-xs.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testdirectsparsesolversunit.ap:211");
}
/*
* Test solver #2
*/
ae_vector_set_length(&xs, 0, _state);
sparsecopytocrs(&sa, &sa2, _state);
sparselu(&sa2, 0, &pivp, &pivq, _state);
sparselusolve(&sa2, &pivp, &pivq, n, &b, &xs2, &rep, _state);
ae_set_error_flag(errorflag, rep.terminationtype<=0, __FILE__, __LINE__, "testdirectsparsesolversunit.ap:221");
ae_set_error_flag(errorflag, xs2.cnt!=n, __FILE__, __LINE__, "testdirectsparsesolversunit.ap:222");
if( *errorflag )
{
ae_frame_leave(_state);
return;
}
for(i=0; i<=n-1; i++)
{
ae_set_error_flag(errorflag, ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-xs2.ptr.p_double[i], _state),threshold), __FILE__, __LINE__, "testdirectsparsesolversunit.ap:226");
}
/*
* Update fill factor
*/
if( noffdiag==0 )
{
break;
}
noffdiag = noffdiag/2;
}
}
}
ae_frame_leave(_state);
}
static double testlincgunit_e0 = 1.0E-6;
static double testlincgunit_maxcond = 30;
static ae_bool testlincgunit_complextest(ae_bool silent, ae_state *_state);
static ae_bool testlincgunit_complexres(ae_bool silent, ae_state *_state);
static ae_bool testlincgunit_basictestx(ae_bool silent, ae_state *_state);
static ae_bool testlincgunit_testrcorrectness(ae_bool silent,
ae_state *_state);
static ae_bool testlincgunit_basictestiters(ae_bool silent,
ae_state *_state);
static ae_bool testlincgunit_krylovsubspacetest(ae_bool silent,
ae_state *_state);
static ae_bool testlincgunit_sparsetest(ae_bool silent, ae_state *_state);
static ae_bool testlincgunit_precondtest(ae_bool silent, ae_state *_state);
static void testlincgunit_gramshmidtortnorm(/* Real */ ae_matrix* a,
ae_int_t n,
ae_int_t k,
double eps,
/* Real */ ae_matrix* b,
ae_int_t* k2,
ae_state *_state);
static ae_bool testlincgunit_frombasis(/* Real */ ae_vector* x,
/* Real */ ae_matrix* basis,
ae_int_t n,
ae_int_t k,
double eps,
ae_state *_state);
ae_bool testlincg(ae_bool silent, ae_state *_state)
{
ae_bool basictestxerrors;
ae_bool basictestiterserr;
ae_bool complexreserrors;
ae_bool complexerrors;
ae_bool rcorrectness;
ae_bool krylovsubspaceerr;
ae_bool sparseerrors;
ae_bool preconderrors;
ae_bool waserrors;
ae_bool result;
basictestxerrors = testlincgunit_basictestx(ae_true, _state);
basictestiterserr = testlincgunit_basictestiters(ae_true, _state);
complexreserrors = testlincgunit_complexres(ae_true, _state);
complexerrors = testlincgunit_complextest(ae_true, _state);
rcorrectness = testlincgunit_testrcorrectness(ae_true, _state);
krylovsubspaceerr = testlincgunit_krylovsubspacetest(ae_true, _state);
sparseerrors = testlincgunit_sparsetest(ae_true, _state);
preconderrors = testlincgunit_precondtest(ae_true, _state);
/*
* report
*/
waserrors = ((((((basictestxerrors||complexreserrors)||complexerrors)||rcorrectness)||basictestiterserr)||krylovsubspaceerr)||sparseerrors)||preconderrors;
if( !silent )
{
printf("TESTING LinCG\n");
printf("BasicTestX: ");
if( basictestxerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("BasicTestIters: ");
if( basictestiterserr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("ComplexResTest: ");
if( complexreserrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("ComplexTest: ");
if( complexerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("R2 correctness: ");
if( rcorrectness )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("KrylovSubSpaceTest: ");
if( krylovsubspaceerr )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("SparseTest: ");
if( sparseerrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
printf("PrecondTest: ");
if( preconderrors )
{
printf("FAILED\n");
}
else
{
printf("OK\n");
}
/*
*was errors?
*/
if( waserrors )
{
printf("TEST FAILED\n");
}
else
{
printf("TEST PASSED\n");
}
printf("\n\n");
}
result = !waserrors;
return result;
}
/*************************************************************************
Function for testing LinCGIteration function(custom option), which to solve
Ax=b(here A is random positive definite matrix NxN, b is random vector). It
uses the default stopping criterion(RNormk;
2. (rk,rm)=0 for any m<>k;
3. (rk,pm)=0 for any m<>k;
INPUT:
Silent - if true then function output report
-- ALGLIB --
Copyright 14.11.2011 by Bochkanov Sergey
*************************************************************************/
static ae_bool testlincgunit_complextest(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
lincgstate state;
lincgreport rep;
ae_matrix a;
ae_vector b;
ae_int_t n;
double c;
ae_vector x0;
ae_vector residual;
double normofresidual;
double sclr;
double na;
double nv0;
double nv1;
ae_int_t sz;
double mx;
ae_int_t i;
ae_int_t j;
ae_int_t k;
ae_int_t l;
double tmp;
ae_matrix mtx;
ae_matrix mtp;
ae_matrix mtr;
double getrnorm;
ae_int_t numofit;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&state, 0, sizeof(state));
memset(&rep, 0, sizeof(rep));
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
memset(&x0, 0, sizeof(x0));
memset(&residual, 0, sizeof(residual));
memset(&mtx, 0, sizeof(mtx));
memset(&mtp, 0, sizeof(mtp));
memset(&mtr, 0, sizeof(mtr));
_lincgstate_init(&state, _state, ae_true);
_lincgreport_init(&rep, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&residual, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&mtx, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&mtp, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&mtr, 0, 0, DT_REAL, _state, ae_true);
mx = (double)(100);
n = 5;
for(sz=1; sz<=n; sz++)
{
/*
* Generate:
* * random A with norm NA (equal to 1.0),
* * random right part B whose elements are uniformly distributed in [-MX,+MX]
* * random starting point X0 whose elements are uniformly distributed in [-MX,+MX]
*/
c = 15+15*ae_randomreal(_state);
spdmatrixrndcond(sz, c, &a, _state);
na = (double)(1);
ae_vector_set_length(&b, sz, _state);
for(i=0; i<=sz-1; i++)
{
b.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1);
}
ae_vector_set_length(&x0, sz, _state);
for(i=0; i<=sz-1; i++)
{
x0.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1);
}
ae_matrix_set_length(&mtx, sz+1, sz, _state);
/*
* Start optimization, record its progress for further analysis
* NOTE: we set update frequency of R to 2 in order to test that R is updated correctly
*/
lincgcreate(sz, &state, _state);
lincgsetxrep(&state, ae_true, _state);
lincgsetb(&state, &b, _state);
lincgsetstartingpoint(&state, &x0, _state);
lincgsetcond(&state, (double)(0), sz, _state);
lincgsetrupdatefreq(&state, 2, _state);
numofit = 0;
getrnorm = ae_maxrealnumber;
while(lincgiteration(&state, _state))
{
if( state.needmv )
{
for(i=0; i<=sz-1; i++)
{
state.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=sz-1; j++)
{
state.mv.ptr.p_double[i] = state.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
}
}
if( state.needvmv )
{
state.vmv = (double)(0);
for(i=0; i<=sz-1; i++)
{
state.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=sz-1; j++)
{
state.mv.ptr.p_double[i] = state.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*state.x.ptr.p_double[j];
}
state.vmv = state.vmv+state.mv.ptr.p_double[i]*state.x.ptr.p_double[i];
}
}
if( state.needprec )
{
for(i=0; i<=sz-1; i++)
{
state.pv.ptr.p_double[i] = state.x.ptr.p_double[i];
}
}
if( state.xupdated )
{
/*
* Save current point to MtX, it will be used later for additional tests
*/
if( numofit>=mtx.rows )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=sz-1; i++)
{
mtx.ptr.pp_double[numofit][i] = state.x.ptr.p_double[i];
}
getrnorm = state.r2;
numofit = numofit+1;
}
}
lincgresults(&state, &x0, &rep, _state);
if( ae_fp_neq(getrnorm,rep.r2) )
{
if( !silent )
{
printf("IterationsCount=%0d;\nNMV=%0d;\nTerminationType=%0d;\n",
(int)(rep.iterationscount),
(int)(rep.nmv),
(int)(rep.terminationtype));
printf("Size=%0d;\nCond=%0.5f;\nComplexTest::Fail::GetRNorm<>Rep.R2!(%0.2e<>%0.2e)\n",
(int)(sz),
(double)(c),
(double)(getrnorm),
(double)(rep.r2));
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
/*
* Calculate residual, check result
*/
ae_vector_set_length(&residual, sz, _state);
for(i=0; i<=sz-1; i++)
{
tmp = (double)(0);
for(j=0; j<=sz-1; j++)
{
tmp = tmp+a.ptr.pp_double[i][j]*x0.ptr.p_double[j];
}
residual.ptr.p_double[i] = b.ptr.p_double[i]-tmp;
}
normofresidual = (double)(0);
for(i=0; i<=sz-1; i++)
{
if( ae_fp_greater(ae_fabs(residual.ptr.p_double[i], _state),testlincgunit_e0) )
{
if( !silent )
{
printf("IterationsCount=%0d;\nNMV=%0d;\nTerminationType=%0d;\n",
(int)(rep.iterationscount),
(int)(rep.nmv),
(int)(rep.terminationtype));
printf("Size=%0d;\nCond=%0.5f;\nComplexTest::Fail::Discripancy[%0d]>E0!(%0.2e>%0.2e)\n",
(int)(sz),
(double)(c),
(int)(i),
(double)(residual.ptr.p_double[i]),
(double)(testlincgunit_e0));
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
normofresidual = normofresidual+residual.ptr.p_double[i]*residual.ptr.p_double[i];
}
if( ae_fp_greater(ae_fabs(normofresidual-rep.r2, _state),testlincgunit_e0) )
{
if( !silent )
{
printf("IterationsCount=%0d;\nNMV=%0d;\nTerminationType=%0d;\n",
(int)(rep.iterationscount),
(int)(rep.nmv),
(int)(rep.terminationtype));
printf("Size=%0d;\nCond=%0.5f;\nComplexTest::Fail::||NormOfResidual-Rep.R2||>E0!(%0.2e>%0.2e)\n",
(int)(sz),
(double)(c),
(double)(ae_fabs(normofresidual-rep.r2, _state)),
(double)(testlincgunit_e0));
printf("NormOfResidual=%0.2e; Rep.R2=%0.2e\n",
(double)(normofresidual),
(double)(rep.r2));
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
/*
* Check algorithm properties (conjugacy/orthogonality).
* Here we use MtX which was filled during algorithm progress towards solution.
*
* NOTE: this test is skipped when algorithm converged in less than SZ iterations.
*/
if( sz>1&&rep.iterationscount==sz )
{
ae_matrix_set_length(&mtp, sz, sz, _state);
ae_matrix_set_length(&mtr, sz, sz, _state);
for(i=0; i<=sz-1; i++)
{
for(j=0; j<=sz-1; j++)
{
mtp.ptr.pp_double[i][j] = mtx.ptr.pp_double[i+1][j]-mtx.ptr.pp_double[i][j];
tmp = (double)(0);
for(k=0; k<=sz-1; k++)
{
tmp = tmp+a.ptr.pp_double[j][k]*mtx.ptr.pp_double[i][k];
}
mtr.ptr.pp_double[i][j] = b.ptr.p_double[j]-tmp;
}
}
/*
*(Api,pj)=0?
*/
sclr = (double)(0);
nv0 = (double)(0);
nv1 = (double)(0);
for(i=0; i<=sz-1; i++)
{
for(j=0; j<=sz-1; j++)
{
if( i==j )
{
continue;
}
for(k=0; k<=sz-1; k++)
{
tmp = (double)(0);
for(l=0; l<=sz-1; l++)
{
tmp = tmp+a.ptr.pp_double[k][l]*mtp.ptr.pp_double[i][l];
}
sclr = sclr+tmp*mtp.ptr.pp_double[j][k];
nv0 = nv0+mtp.ptr.pp_double[i][k]*mtp.ptr.pp_double[i][k];
nv1 = nv1+mtp.ptr.pp_double[j][k]*mtp.ptr.pp_double[j][k];
}
nv0 = ae_sqrt(nv0, _state);
nv1 = ae_sqrt(nv1, _state);
if( ae_fp_greater(ae_fabs(sclr, _state),testlincgunit_e0*na*nv0*nv1) )
{
if( !silent )
{
printf("IterationsCount=%0d;\nNMV=%0d;\nTerminationType=%0d;\n",
(int)(rep.iterationscount),
(int)(rep.nmv),
(int)(rep.terminationtype));
printf("Size=%0d;\nCond=%0.5f;\nComplexTest::Fail::(Ap%0d,p%0d)!=0\n{Sclr=%0.15f; NA=%0.15f NV0=%0.15f NV1=%0.15f;}\n",
(int)(sz),
(double)(c),
(int)(i),
(int)(j),
(double)(sclr),
(double)(na),
(double)(nv0),
(double)(nv1));
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
/*
*(ri,pj)=0?
*/
for(i=1; i<=sz-1; i++)
{
for(j=0; j<=i-1; j++)
{
sclr = (double)(0);
nv0 = (double)(0);
nv1 = (double)(0);
for(k=0; k<=sz-1; k++)
{
sclr = sclr+mtr.ptr.pp_double[i][k]*mtp.ptr.pp_double[j][k];
nv0 = nv0+mtr.ptr.pp_double[i][k]*mtr.ptr.pp_double[i][k];
nv1 = nv1+mtp.ptr.pp_double[j][k]*mtp.ptr.pp_double[j][k];
}
nv0 = ae_sqrt(nv0, _state);
nv1 = ae_sqrt(nv1, _state);
if( ae_fp_greater(ae_fabs(sclr, _state),testlincgunit_e0*nv0*nv1) )
{
if( !silent )
{
printf("IterationsCount=%0d;\nNMV=%0d;\nTerminationType=%0d;\n",
(int)(rep.iterationscount),
(int)(rep.nmv),
(int)(rep.terminationtype));
printf("Size=%0d;\nCond=%0.5f;\nComplexTest::Fail::(r%0d,p%0d)!=0\n{Sclr=%0.15f; NV0=%0.15f NV1=%0.15f;}\n",
(int)(sz),
(double)(c),
(int)(i),
(int)(j),
(double)(sclr),
(double)(nv0),
(double)(nv1));
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
/*
*(ri,rj)=0?
*/
for(i=0; i<=sz-1; i++)
{
for(j=i+1; j<=sz-1; j++)
{
sclr = (double)(0);
nv0 = (double)(0);
nv1 = (double)(0);
for(k=0; k<=sz-1; k++)
{
sclr = sclr+mtr.ptr.pp_double[i][k]*mtr.ptr.pp_double[j][k];
nv0 = nv0+mtr.ptr.pp_double[i][k]*mtr.ptr.pp_double[i][k];
nv1 = nv1+mtr.ptr.pp_double[j][k]*mtr.ptr.pp_double[j][k];
}
nv0 = ae_sqrt(nv0, _state);
nv1 = ae_sqrt(nv1, _state);
if( ae_fp_greater(ae_fabs(sclr, _state),testlincgunit_e0*nv0*nv1) )
{
if( !silent )
{
printf("IterationsCount=%0d;\nNMV=%0d;\nTerminationType=%0d;\n",
(int)(rep.iterationscount),
(int)(rep.nmv),
(int)(rep.terminationtype));
printf("Size=%0d;\nCond=%0.5f;\nComplexTest::Fail::(rm,rk)!=0\n{Sclr=%0.15f; NV0=%0.15f NV1=%0.15f;}\n",
(int)(sz),
(double)(c),
(double)(sclr),
(double)(nv0),
(double)(nv1));
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
}
if( !silent )
{
printf("ComplexTest::Ok\n");
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function prepare problem with a known solution 'Xs'(A*Xs-b=0). There
b is A*Xs. After, function check algorithm result and 'Xs'.
There used two stopping criterions:
1. achieved the required precision(StCrit=0);
2. execution of the required number of iterations(StCrit=1).
-- ALGLIB --
Copyright 14.11.2011 by Bochkanov Sergey
*************************************************************************/
static ae_bool testlincgunit_complexres(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
lincgstate s;
lincgreport rep;
ae_matrix a;
ae_vector b;
ae_vector xs;
ae_vector x0;
double err;
ae_int_t n;
ae_int_t sz;
double c;
ae_int_t i;
ae_int_t j;
ae_int_t stcrit;
double mx;
double tmp;
double eps;
ae_int_t xp;
ae_int_t nxp;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
memset(&xs, 0, sizeof(xs));
memset(&x0, 0, sizeof(x0));
_lincgstate_init(&s, _state, ae_true);
_lincgreport_init(&rep, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xs, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
sz = 5;
mx = (double)(100);
nxp = 100;
for(xp=0; xp<=nxp-1; xp++)
{
for(n=1; n<=sz; n++)
{
for(stcrit=0; stcrit<=1; stcrit++)
{
/*
* Generate:
* * random A with norm NA (equal to 1.0),
* * random solution XS whose elements are uniformly distributed in [-MX,+MX]
* * random starting point X0 whose elements are uniformly distributed in [-MX,+MX]
* * B = A*Xs
*/
c = (testlincgunit_maxcond-1)*ae_randomreal(_state)+1;
spdmatrixrndcond(n, c, &a, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&xs, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1);
xs.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1);
}
eps = (double)(0);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
b.ptr.p_double[i] = b.ptr.p_double[i]+a.ptr.pp_double[i][j]*xs.ptr.p_double[j];
}
eps = eps+b.ptr.p_double[i]*b.ptr.p_double[i];
}
eps = 1.0E-6*ae_sqrt(eps, _state);
/*
* Solve with different stopping criteria
*/
lincgcreate(n, &s, _state);
lincgsetb(&s, &b, _state);
lincgsetstartingpoint(&s, &x0, _state);
lincgsetxrep(&s, ae_true, _state);
if( stcrit==0 )
{
lincgsetcond(&s, 1.0E-6, 0, _state);
}
else
{
lincgsetcond(&s, (double)(0), n, _state);
}
while(lincgiteration(&s, _state))
{
if( s.needmv )
{
for(i=0; i<=n-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
}
}
if( s.needvmv )
{
s.vmv = (double)(0);
for(i=0; i<=n-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
s.vmv = s.vmv+s.mv.ptr.p_double[i]*s.x.ptr.p_double[i];
}
}
if( s.needprec )
{
for(i=0; i<=n-1; i++)
{
s.pv.ptr.p_double[i] = s.x.ptr.p_double[i];
}
}
}
lincgresults(&s, &x0, &rep, _state);
/*
* Check result
*/
err = 0.0;
for(i=0; i<=n-1; i++)
{
tmp = (double)(0);
for(j=0; j<=n-1; j++)
{
tmp = tmp+a.ptr.pp_double[i][j]*x0.ptr.p_double[j];
}
err = err+ae_sqr(b.ptr.p_double[i]-tmp, _state);
}
err = ae_sqrt(err, _state);
if( ae_fp_greater(err,eps) )
{
if( !silent )
{
printf("ComplexRes::fail\n");
printf("IterationsCount=%0d\n",
(int)(rep.iterationscount));
printf("NMV=%0d\n",
(int)(rep.nmv));
printf("TerminationType=%0d\n",
(int)(rep.terminationtype));
printf("X and Xs...\n");
for(j=0; j<=n-1; j++)
{
printf("x[%0d]=%0.10f; xs[%0d]=%0.10f\n",
(int)(j),
(double)(x0.ptr.p_double[j]),
(int)(j),
(double)(xs.ptr.p_double[j]));
}
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
/*
*test has been passed
*/
if( !silent )
{
printf("ComplexRes::Ok\n");
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function check, that XUpdated return State.X=X0 at zero iteration and
State.X=X(algorithm result) at last.
-- ALGLIB --
Copyright 14.11.2011 by Bochkanov Sergey
*************************************************************************/
static ae_bool testlincgunit_basictestx(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
lincgstate s;
lincgreport rep;
ae_matrix a;
ae_vector b;
ae_vector x0;
ae_vector x00;
ae_vector x01;
ae_int_t n;
ae_int_t sz;
double c;
ae_int_t i;
ae_int_t j;
double mx;
ae_int_t iters;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
memset(&x0, 0, sizeof(x0));
memset(&x00, 0, sizeof(x00));
memset(&x01, 0, sizeof(x01));
_lincgstate_init(&s, _state, ae_true);
_lincgreport_init(&rep, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x00, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x01, 0, DT_REAL, _state, ae_true);
sz = 5;
mx = (double)(100);
for(n=1; n<=sz; n++)
{
/*
* Generate:
* * random A with norm NA (equal to 1.0),
* * random right part B whose elements are uniformly distributed in [-MX,+MX]
* * random starting point X0 whose elements are uniformly distributed in [-MX,+MX]
*/
c = (testlincgunit_maxcond-1)*ae_randomreal(_state)+1;
spdmatrixrndcond(n, c, &a, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&x00, n, _state);
ae_vector_set_length(&x01, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1);
b.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1);
}
/*
* Solve, save first and last reported points to x00 and x01
*/
lincgcreate(n, &s, _state);
lincgsetb(&s, &b, _state);
lincgsetstartingpoint(&s, &x0, _state);
lincgsetxrep(&s, ae_true, _state);
lincgsetcond(&s, (double)(0), n, _state);
iters = 0;
while(lincgiteration(&s, _state))
{
if( s.needmv )
{
for(i=0; i<=n-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
}
}
if( s.needvmv )
{
s.vmv = (double)(0);
for(i=0; i<=n-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
s.vmv = s.vmv+s.mv.ptr.p_double[i]*s.x.ptr.p_double[i];
}
}
if( s.needprec )
{
for(i=0; i<=n-1; i++)
{
s.pv.ptr.p_double[i] = s.x.ptr.p_double[i];
}
}
if( s.xupdated )
{
if( iters==0 )
{
for(i=0; i<=n-1; i++)
{
x00.ptr.p_double[i] = s.x.ptr.p_double[i];
}
}
if( iters==n )
{
for(i=0; i<=n-1; i++)
{
x01.ptr.p_double[i] = s.x.ptr.p_double[i];
}
}
iters = iters+1;
}
}
/*
* Check first and last points
*/
for(i=0; i<=n-1; i++)
{
if( ae_fp_neq(x00.ptr.p_double[i],x0.ptr.p_double[i]) )
{
if( !silent )
{
printf("BasicTestX::fail\n");
printf("IterationsCount=%0d\n",
(int)(rep.iterationscount));
printf("NMV=%0d\n",
(int)(rep.nmv));
printf("TerminationType=%0d\n",
(int)(rep.terminationtype));
for(j=0; j<=n-1; j++)
{
printf("x0=%0.5f; x00=%0.5f;\n",
(double)(x0.ptr.p_double[j]),
(double)(x00.ptr.p_double[j]));
}
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
lincgresults(&s, &x0, &rep, _state);
for(i=0; i<=n-1; i++)
{
if( ae_fp_neq(x01.ptr.p_double[i],x0.ptr.p_double[i]) )
{
if( !silent )
{
printf("BasicTestX::fail\n");
printf("IterationsCount=%0d\n",
(int)(rep.iterationscount));
printf("NMV=%0d\n",
(int)(rep.nmv));
printf("TerminationType=%0d\n",
(int)(rep.terminationtype));
for(j=0; j<=n-1; j++)
{
printf("x0=%0.5f; x01=%0.5f;\n",
(double)(x0.ptr.p_double[j]),
(double)(x01.ptr.p_double[j]));
}
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
/*
*test has been passed
*/
if( !silent )
{
printf("BasicTestIters::Ok\n");
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function checks that XUpdated returns correct State.R2. It creates
large badly conditioned problem (N=50), which should be large enough and
ill-conditioned enough to cause periodic recalculation of R.
-- ALGLIB --
Copyright 14.11.2011 by Bochkanov Sergey
*************************************************************************/
static ae_bool testlincgunit_testrcorrectness(ae_bool silent,
ae_state *_state)
{
ae_frame _frame_block;
lincgstate s;
lincgreport rep;
ae_matrix a;
ae_vector b;
ae_int_t n;
double c;
ae_int_t i;
ae_int_t j;
double r2;
double v;
double rtol;
ae_int_t maxits;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
_lincgstate_init(&s, _state, ae_true);
_lincgreport_init(&rep, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
rtol = 1.0E6*ae_machineepsilon;
n = 50;
maxits = n/2;
c = (double)(10000);
spdmatrixrndcond(n, c, &a, _state);
ae_vector_set_length(&b, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
lincgcreate(n, &s, _state);
lincgsetb(&s, &b, _state);
lincgsetxrep(&s, ae_true, _state);
lincgsetcond(&s, (double)(0), maxits, _state);
while(lincgiteration(&s, _state))
{
if( s.needmv )
{
for(i=0; i<=n-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
}
}
if( s.needvmv )
{
s.vmv = (double)(0);
for(i=0; i<=n-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
s.vmv = s.vmv+s.mv.ptr.p_double[i]*s.x.ptr.p_double[i];
}
}
if( s.needprec )
{
for(i=0; i<=n-1; i++)
{
s.pv.ptr.p_double[i] = s.x.ptr.p_double[i];
}
}
if( s.xupdated )
{
/*
* calculate R2, compare with value returned in state.R2
*/
r2 = (double)(0);
for(i=0; i<=n-1; i++)
{
v = (double)(0);
for(j=0; j<=n-1; j++)
{
v = v+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
r2 = r2+ae_sqr(v-b.ptr.p_double[i], _state);
}
if( ae_fp_greater(ae_fabs(r2-s.r2, _state),rtol) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
lincgresults(&s, &b, &rep, _state);
if( rep.iterationscount!=maxits )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function check, that number of iterations are't more than MaxIts.
-- ALGLIB --
Copyright 14.11.2011 by Bochkanov Sergey
*************************************************************************/
static ae_bool testlincgunit_basictestiters(ae_bool silent,
ae_state *_state)
{
ae_frame _frame_block;
lincgstate s;
lincgreport rep;
ae_matrix a;
ae_vector b;
ae_vector x0;
ae_int_t n;
ae_int_t sz;
double c;
ae_int_t i;
ae_int_t j;
double mx;
ae_int_t iters;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
memset(&x0, 0, sizeof(x0));
_lincgstate_init(&s, _state, ae_true);
_lincgreport_init(&rep, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
sz = 5;
mx = (double)(100);
for(n=1; n<=sz; n++)
{
/*
* Generate:
* * random A with norm NA (equal to 1.0),
* * random right part B whose elements are uniformly distributed in [-MX,+MX]
* * random starting point X0 whose elements are uniformly distributed in [-MX,+MX]
*/
c = (testlincgunit_maxcond-1)*ae_randomreal(_state)+1;
spdmatrixrndcond(n, c, &a, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x0, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1);
b.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1);
}
/*
* Solve
*/
lincgcreate(n, &s, _state);
lincgsetb(&s, &b, _state);
lincgsetstartingpoint(&s, &x0, _state);
lincgsetxrep(&s, ae_true, _state);
lincgsetcond(&s, (double)(0), n, _state);
iters = 0;
while(lincgiteration(&s, _state))
{
if( s.needmv )
{
for(i=0; i<=n-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
}
}
if( s.needvmv )
{
s.vmv = (double)(0);
for(i=0; i<=n-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
s.vmv = s.vmv+s.mv.ptr.p_double[i]*s.x.ptr.p_double[i];
}
}
if( s.needprec )
{
for(i=0; i<=n-1; i++)
{
s.pv.ptr.p_double[i] = s.x.ptr.p_double[i];
}
}
if( s.xupdated )
{
iters = iters+1;
}
}
lincgresults(&s, &x0, &rep, _state);
/*
* Check
*/
if( iters!=rep.iterationscount+1||iters>n+1 )
{
if( !silent )
{
printf("BasicTestIters::fail\n");
printf("IterationsCount=%0d\n",
(int)(rep.iterationscount));
printf("NMV=%0d\n",
(int)(rep.nmv));
printf("TerminationType=%0d\n",
(int)(rep.terminationtype));
printf("Iters=%0d\n",
(int)(iters));
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
/*
* Restart problem
*/
c = (testlincgunit_maxcond-1)*ae_randomreal(_state)+1;
spdmatrixrndcond(n, c, &a, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1);
b.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1);
}
lincgsetstartingpoint(&s, &x0, _state);
lincgrestart(&s, _state);
lincgsetb(&s, &b, _state);
iters = 0;
while(lincgiteration(&s, _state))
{
if( s.needmv )
{
for(i=0; i<=n-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
}
}
if( s.needvmv )
{
s.vmv = (double)(0);
for(i=0; i<=n-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
s.vmv = s.vmv+s.mv.ptr.p_double[i]*s.x.ptr.p_double[i];
}
}
if( s.needprec )
{
for(i=0; i<=n-1; i++)
{
s.pv.ptr.p_double[i] = s.x.ptr.p_double[i];
}
}
if( s.xupdated )
{
iters = iters+1;
}
}
lincgresults(&s, &x0, &rep, _state);
/*
*check
*/
if( iters!=rep.iterationscount+1||iters>n+1 )
{
if( !silent )
{
printf("BasicTestIters::fail\n");
printf("IterationsCount=%0d\n",
(int)(rep.iterationscount));
printf("NMV=%0d\n",
(int)(rep.nmv));
printf("TerminationType=%0d\n",
(int)(rep.terminationtype));
printf("Iters=%0d\n",
(int)(iters));
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
/*
*test has been passed
*/
if( !silent )
{
printf("BasicTestIters::Ok\n");
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
This function check, that programmed method is Krylov subspace methed.
-- ALGLIB --
Copyright 14.11.2011 by Bochkanov Sergey
*************************************************************************/
static ae_bool testlincgunit_krylovsubspacetest(ae_bool silent,
ae_state *_state)
{
ae_frame _frame_block;
lincgstate s;
lincgreport rep;
ae_matrix a;
ae_vector b;
ae_vector x0;
ae_matrix ksr;
ae_vector r0;
ae_vector tarray;
ae_matrix mtx;
ae_int_t n;
ae_int_t sz;
double c;
ae_int_t i;
ae_int_t j;
ae_int_t l;
ae_int_t m;
double mx;
double tmp;
double normr0;
ae_int_t numofit;
ae_int_t maxits;
ae_int_t k2;
double eps;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
memset(&x0, 0, sizeof(x0));
memset(&ksr, 0, sizeof(ksr));
memset(&r0, 0, sizeof(r0));
memset(&tarray, 0, sizeof(tarray));
memset(&mtx, 0, sizeof(mtx));
_lincgstate_init(&s, _state, ae_true);
_lincgreport_init(&rep, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ksr, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&r0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tarray, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&mtx, 0, 0, DT_REAL, _state, ae_true);
eps = 1.0E-6;
maxits = 3;
sz = 5;
mx = (double)(100);
for(n=1; n<=sz; n++)
{
/*
* Generate:
* * random A with unit norm
* * cond(A) in [0.5*MaxCond, 1.0*MaxCond]
* * random x0 and b such that |A*x0-b| is large enough for algorithm to make at least one iteration.
*
* IMPORTANT: it is very important to have cond(A) both (1) not very large and
* (2) not very small. Large cond(A) will make our problem ill-conditioned,
* thus analytic properties won't hold. Small cond(A), from the other side,
* will give us rapid convergence of the algorithm - in fact, too rapid.
* Krylov basis will be dominated by numerical noise and test may fail.
*/
c = testlincgunit_maxcond*(0.5*ae_randomreal(_state)+0.5);
spdmatrixrndcond(n, c, &a, _state);
ae_matrix_set_length(&mtx, n+1, n, _state);
ae_matrix_set_length(&ksr, n, n, _state);
ae_vector_set_length(&r0, n, _state);
ae_vector_set_length(&tarray, n, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&x0, n, _state);
do
{
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1);
b.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1);
}
normr0 = (double)(0);
for(i=0; i<=n-1; i++)
{
tmp = (double)(0);
for(j=0; j<=n-1; j++)
{
tmp = tmp+a.ptr.pp_double[i][j]*x0.ptr.p_double[j];
}
r0.ptr.p_double[i] = b.ptr.p_double[i]-tmp;
normr0 = normr0+r0.ptr.p_double[i]*r0.ptr.p_double[i];
}
}
while(ae_fp_less_eq(ae_sqrt(normr0, _state),eps));
/*
* Fill KSR by {r0, A*r0, A^2*r0, ... }
*/
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
ksr.ptr.pp_double[i][j] = r0.ptr.p_double[j];
}
for(j=0; j<=i-1; j++)
{
for(l=0; l<=n-1; l++)
{
tarray.ptr.p_double[l] = (double)(0);
for(m=0; m<=n-1; m++)
{
tarray.ptr.p_double[l] = tarray.ptr.p_double[l]+a.ptr.pp_double[l][m]*ksr.ptr.pp_double[i][m];
}
}
for(l=0; l<=n-1; l++)
{
ksr.ptr.pp_double[i][l] = tarray.ptr.p_double[l];
}
}
}
/*
* Solve system, record intermediate points for futher analysis.
* NOTE: we set update frequency of R to 2 in order to test that R is updated correctly
*/
lincgcreate(n, &s, _state);
lincgsetb(&s, &b, _state);
lincgsetstartingpoint(&s, &x0, _state);
lincgsetxrep(&s, ae_true, _state);
lincgsetcond(&s, (double)(0), n, _state);
lincgsetrupdatefreq(&s, 2, _state);
numofit = 0;
while(lincgiteration(&s, _state))
{
if( s.needmv )
{
for(i=0; i<=n-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
}
}
if( s.needvmv )
{
s.vmv = (double)(0);
for(i=0; i<=n-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
s.vmv = s.vmv+s.mv.ptr.p_double[i]*s.x.ptr.p_double[i];
}
}
if( s.needprec )
{
for(i=0; i<=n-1; i++)
{
s.pv.ptr.p_double[i] = s.x.ptr.p_double[i];
}
}
if( s.xupdated )
{
for(i=0; i<=n-1; i++)
{
mtx.ptr.pp_double[numofit][i] = s.x.ptr.p_double[i];
}
numofit = numofit+1;
}
}
/*
* Check that I-th step S_i=X[I+1]-X[i] belongs to I-th Krylov subspace.
* Checks are done for first K2 steps, with K2 small enough to avoid
* numerical errors.
*/
if( n<=maxits )
{
k2 = n;
}
else
{
k2 = maxits;
}
for(i=0; i<=k2-1; i++)
{
for(j=0; j<=n-1; j++)
{
tarray.ptr.p_double[j] = mtx.ptr.pp_double[i+1][j]-mtx.ptr.pp_double[i][j];
}
if( !testlincgunit_frombasis(&tarray, &ksr, n, i+1, testlincgunit_e0, _state) )
{
if( !silent )
{
printf("KrylovSubspaceTest::FAIL\n");
printf("Size=%0d; Iters=%0d;\n",
(int)(n),
(int)(i));
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
if( !silent )
{
printf("KrylovSubspaceTest::OK\n");
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Function for testing LinCgSolveSparse. This function prepare problem with
a known solution 'Xs'(A*Xs-b=0). There b is A*Xs. After, function calculate
result by LinCGSolveSparse and compares it with 'Xs'.
-- ALGLIB --
Copyright 14.11.2011 by Bochkanov Sergey
*************************************************************************/
static ae_bool testlincgunit_sparsetest(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
lincgstate s;
lincgreport rep;
ae_matrix a;
ae_vector b;
ae_vector xs;
ae_vector x0;
ae_vector x1;
sparsematrix uppera;
sparsematrix lowera;
double err;
ae_int_t n;
ae_int_t sz;
double c;
ae_int_t i;
ae_int_t j;
double mx;
double eps;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&a, 0, sizeof(a));
memset(&b, 0, sizeof(b));
memset(&xs, 0, sizeof(xs));
memset(&x0, 0, sizeof(x0));
memset(&x1, 0, sizeof(x1));
memset(&uppera, 0, sizeof(uppera));
memset(&lowera, 0, sizeof(lowera));
_lincgstate_init(&s, _state, ae_true);
_lincgreport_init(&rep, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xs, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x1, 0, DT_REAL, _state, ae_true);
_sparsematrix_init(&uppera, _state, ae_true);
_sparsematrix_init(&lowera, _state, ae_true);
sz = 5;
mx = (double)(100);
for(n=1; n<=sz; n++)
{
/*
* Generate:
* * random A with unit norm
* * random X0 (starting point) and XS (known solution)
* Copy dense A to sparse SA
*/
c = (testlincgunit_maxcond-1)*ae_randomreal(_state)+1;
spdmatrixrndcond(n, c, &a, _state);
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&xs, n, _state);
for(i=0; i<=n-1; i++)
{
xs.ptr.p_double[i] = mx*(2*ae_randomreal(_state)-1);
}
eps = (double)(0);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
b.ptr.p_double[i] = b.ptr.p_double[i]+a.ptr.pp_double[i][j]*xs.ptr.p_double[j];
}
eps = eps+b.ptr.p_double[i]*b.ptr.p_double[i];
}
eps = 1.0E-6*ae_sqrt(eps, _state);
sparsecreate(n, n, 0, &uppera, _state);
sparsecreate(n, n, 0, &lowera, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( j>=i )
{
sparseset(&uppera, i, j, a.ptr.pp_double[i][j], _state);
}
if( j<=i )
{
sparseset(&lowera, i, j, a.ptr.pp_double[i][j], _state);
}
}
}
sparseconverttocrs(&uppera, _state);
sparseconverttocrs(&lowera, _state);
/*
* Test upper triangle
*/
lincgcreate(n, &s, _state);
lincgsetcond(&s, (double)(0), n, _state);
lincgsolvesparse(&s, &uppera, ae_true, &b, _state);
lincgresults(&s, &x0, &rep, _state);
err = (double)(0);
for(i=0; i<=n-1; i++)
{
err = err+ae_sqr(x0.ptr.p_double[i]-xs.ptr.p_double[i], _state);
}
err = ae_sqrt(err, _state);
if( ae_fp_greater(err,eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
/*
* Test lower triangle
*/
lincgcreate(n, &s, _state);
lincgsetcond(&s, (double)(0), n, _state);
lincgsolvesparse(&s, &lowera, ae_false, &b, _state);
lincgresults(&s, &x1, &rep, _state);
err = (double)(0);
for(i=0; i<=n-1; i++)
{
err = err+ae_sqr(x1.ptr.p_double[i]-xs.ptr.p_double[i], _state);
}
err = ae_sqrt(err, _state);
if( ae_fp_greater(err,eps) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Function for testing the preconditioned conjugate gradient method.
-- ALGLIB --
Copyright 14.11.2011 by Bochkanov Sergey
*************************************************************************/
static ae_bool testlincgunit_precondtest(ae_bool silent, ae_state *_state)
{
ae_frame _frame_block;
lincgstate s;
lincgreport rep;
ae_matrix a;
ae_matrix ta;
sparsematrix sa;
ae_vector m;
ae_matrix mtx;
ae_matrix mtprex;
ae_vector de;
ae_vector rde;
ae_vector b;
ae_vector tb;
ae_vector d;
ae_vector xe;
ae_vector x0;
ae_vector tx0;
ae_vector err;
ae_int_t n;
ae_int_t sz;
ae_int_t numofit;
double c;
ae_int_t i;
ae_int_t j;
ae_int_t k;
double eps;
ae_bool bflag;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&s, 0, sizeof(s));
memset(&rep, 0, sizeof(rep));
memset(&a, 0, sizeof(a));
memset(&ta, 0, sizeof(ta));
memset(&sa, 0, sizeof(sa));
memset(&m, 0, sizeof(m));
memset(&mtx, 0, sizeof(mtx));
memset(&mtprex, 0, sizeof(mtprex));
memset(&de, 0, sizeof(de));
memset(&rde, 0, sizeof(rde));
memset(&b, 0, sizeof(b));
memset(&tb, 0, sizeof(tb));
memset(&d, 0, sizeof(d));
memset(&xe, 0, sizeof(xe));
memset(&x0, 0, sizeof(x0));
memset(&tx0, 0, sizeof(tx0));
memset(&err, 0, sizeof(err));
_lincgstate_init(&s, _state, ae_true);
_lincgreport_init(&rep, _state, ae_true);
ae_matrix_init(&a, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&ta, 0, 0, DT_REAL, _state, ae_true);
_sparsematrix_init(&sa, _state, ae_true);
ae_vector_init(&m, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&mtx, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&mtprex, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&de, 0, DT_REAL, _state, ae_true);
ae_vector_init(&rde, 0, DT_REAL, _state, ae_true);
ae_vector_init(&b, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tb, 0, DT_REAL, _state, ae_true);
ae_vector_init(&d, 0, DT_REAL, _state, ae_true);
ae_vector_init(&xe, 0, DT_REAL, _state, ae_true);
ae_vector_init(&x0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&tx0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&err, 0, DT_REAL, _state, ae_true);
/*
* Test 1.
*
* Preconditioned CG for A*x=b with preconditioner M=E*E' is algebraically
* equivalent to non-preconditioned CG for (inv(E)*A*inv(E'))*z = inv(E)*b
* with z=E'*x.
*
* We test it by generating random preconditioner, running algorithm twice -
* one time for original problem with preconditioner , another one for
* modified problem without preconditioner.
*/
sz = 5;
for(n=1; n<=sz; n++)
{
/*
* Generate:
* * random A with unit norm
* * random positive definite diagonal preconditioner M
* * dE=sqrt(M)
* * rdE=dE^(-1)
* * tA = rdE*A*rdE
* * random x0 and b - for original preconditioned problem
* * tx0 and tb - for modified problem
*/
c = (testlincgunit_maxcond-1)*ae_randomreal(_state)+1;
spdmatrixrndcond(n, c, &a, _state);
ae_matrix_set_length(&ta, n, n, _state);
ae_matrix_set_length(&mtx, n+1, n, _state);
ae_matrix_set_length(&mtprex, n+1, n, _state);
ae_vector_set_length(&m, n, _state);
ae_vector_set_length(&de, n, _state);
ae_vector_set_length(&rde, n, _state);
for(i=0; i<=n-1; i++)
{
m.ptr.p_double[i] = ae_randomreal(_state)+0.5;
de.ptr.p_double[i] = ae_sqrt(m.ptr.p_double[i], _state);
rde.ptr.p_double[i] = 1/de.ptr.p_double[i];
}
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
ta.ptr.pp_double[i][j] = rde.ptr.p_double[i]*a.ptr.pp_double[i][j]*rde.ptr.p_double[j];
}
}
ae_vector_set_length(&b, n, _state);
ae_vector_set_length(&tb, n, _state);
ae_vector_set_length(&x0, n, _state);
ae_vector_set_length(&tx0, n, _state);
ae_vector_set_length(&err, n, _state);
for(i=0; i<=n-1; i++)
{
x0.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
b.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
eps = 1.0E-5;
for(i=0; i<=n-1; i++)
{
tx0.ptr.p_double[i] = de.ptr.p_double[i]*x0.ptr.p_double[i];
tb.ptr.p_double[i] = rde.ptr.p_double[i]*b.ptr.p_double[i];
}
/*
* Solve two problems, intermediate points are saved to MtX and MtPreX
*/
lincgcreate(n, &s, _state);
lincgsetb(&s, &b, _state);
lincgsetstartingpoint(&s, &x0, _state);
lincgsetxrep(&s, ae_true, _state);
lincgsetcond(&s, (double)(0), n, _state);
numofit = 0;
while(lincgiteration(&s, _state))
{
if( s.needmv )
{
for(i=0; i<=n-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
}
}
if( s.needvmv )
{
s.vmv = (double)(0);
for(i=0; i<=n-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+a.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
s.vmv = s.vmv+s.mv.ptr.p_double[i]*s.x.ptr.p_double[i];
}
}
if( s.needprec )
{
for(i=0; i<=n-1; i++)
{
s.pv.ptr.p_double[i] = s.x.ptr.p_double[i]/m.ptr.p_double[i];
}
}
if( s.xupdated )
{
if( numofit>=mtx.rows )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=n-1; i++)
{
mtx.ptr.pp_double[numofit][i] = s.x.ptr.p_double[i];
}
numofit = numofit+1;
}
}
lincgsetstartingpoint(&s, &tx0, _state);
lincgsetb(&s, &tb, _state);
lincgrestart(&s, _state);
numofit = 0;
while(lincgiteration(&s, _state))
{
if( s.needmv )
{
for(i=0; i<=n-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+ta.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
}
}
if( s.needvmv )
{
s.vmv = (double)(0);
for(i=0; i<=n-1; i++)
{
s.mv.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
s.mv.ptr.p_double[i] = s.mv.ptr.p_double[i]+ta.ptr.pp_double[i][j]*s.x.ptr.p_double[j];
}
s.vmv = s.vmv+s.mv.ptr.p_double[i]*s.x.ptr.p_double[i];
}
}
if( s.needprec )
{
for(i=0; i<=n-1; i++)
{
s.pv.ptr.p_double[i] = s.x.ptr.p_double[i];
}
}
if( s.xupdated )
{
if( numofit>=mtprex.rows )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=n-1; i++)
{
mtprex.ptr.pp_double[numofit][i] = s.x.ptr.p_double[i];
}
numofit = numofit+1;
}
}
/*
* Compare results - sequence of points generated when solving original problem with
* points generated by modified problem.
*/
for(i=0; i<=numofit-1; i++)
{
for(j=0; j<=n-1; j++)
{
if( ae_fp_greater(ae_fabs(mtx.ptr.pp_double[i][j]-rde.ptr.p_double[j]*mtprex.ptr.pp_double[i][j], _state),eps) )
{
if( !silent )
{
printf("PrecondTest::fail\n");
printf("Size=%0d\n",
(int)(n));
printf("IterationsCount=%0d\n",
(int)(rep.iterationscount));
printf("NMV=%0d\n",
(int)(rep.nmv));
printf("TerminationType=%0d\n",
(int)(rep.terminationtype));
printf("X and X^...\n");
for(k=0; k<=n-1; k++)
{
printf("I=%0d; mtx[%0d]=%0.10f; mtx^[%0d]=%0.10f\n",
(int)(i),
(int)(k),
(double)(mtx.ptr.pp_double[i][k]),
(int)(k),
(double)(mtprex.ptr.pp_double[i][k]));
}
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
}
}
/*
* Test 2.
*
* We test automatic diagonal preconditioning used by SolveSparse.
* In order to do so we:
* 1. generate 20*20 matrix A0 with condition number equal to 1.0E1
* 2. generate random "exact" solution xe and right part b=A0*xe
* 3. generate random ill-conditioned diagonal scaling matrix D with
* condition number equal to 1.0E50:
* 4. transform A*x=b into badly scaled problem:
* A0*x0=b0
* A0*D*(inv(D)*x0)=b0
* (D*A0*D)*(inv(D)*x0)=(D*b0)
* finally we got new problem A*x=b with A=D*A0*D, b=D*b0, x=inv(D)*x0
*
* Then we solve A*x=b:
* 1. with default preconditioner
* 2. with explicitly activayed diagonal preconditioning
* 3. with unit preconditioner.
* 1st and 2nd solutions must be close to xe, 3rd solution must be very
* far from the true one.
*/
n = 20;
spdmatrixrndcond(n, 1.0E1, &ta, _state);
ae_vector_set_length(&xe, n, _state);
for(i=0; i<=n-1; i++)
{
xe.ptr.p_double[i] = randomnormal(_state);
}
ae_vector_set_length(&b, n, _state);
for(i=0; i<=n-1; i++)
{
b.ptr.p_double[i] = (double)(0);
for(j=0; j<=n-1; j++)
{
b.ptr.p_double[i] = b.ptr.p_double[i]+ta.ptr.pp_double[i][j]*xe.ptr.p_double[j];
}
}
ae_vector_set_length(&d, n, _state);
for(i=0; i<=n-1; i++)
{
d.ptr.p_double[i] = ae_pow((double)(10), 100*ae_randomreal(_state)-50, _state);
}
ae_matrix_set_length(&a, n, n, _state);
sparsecreate(n, n, n*n, &sa, _state);
for(i=0; i<=n-1; i++)
{
for(j=0; j<=n-1; j++)
{
a.ptr.pp_double[i][j] = d.ptr.p_double[i]*ta.ptr.pp_double[i][j]*d.ptr.p_double[j];
sparseset(&sa, i, j, a.ptr.pp_double[i][j], _state);
}
b.ptr.p_double[i] = b.ptr.p_double[i]*d.ptr.p_double[i];
xe.ptr.p_double[i] = xe.ptr.p_double[i]/d.ptr.p_double[i];
}
sparseconverttocrs(&sa, _state);
lincgcreate(n, &s, _state);
lincgsetcond(&s, (double)(0), 2*n, _state);
lincgsolvesparse(&s, &sa, ae_true, &b, _state);
lincgresults(&s, &x0, &rep, _state);
if( rep.terminationtype<=0 )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=n-1; i++)
{
if( ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-x0.ptr.p_double[i], _state),5.0E-2/d.ptr.p_double[i]) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
lincgsetprecunit(&s, _state);
lincgsolvesparse(&s, &sa, ae_true, &b, _state);
lincgresults(&s, &x0, &rep, _state);
if( rep.terminationtype>0 )
{
bflag = ae_false;
for(i=0; i<=n-1; i++)
{
bflag = bflag||ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-x0.ptr.p_double[i], _state),5.0E-2/d.ptr.p_double[i]);
}
if( !bflag )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
lincgsetprecdiag(&s, _state);
lincgsolvesparse(&s, &sa, ae_true, &b, _state);
lincgresults(&s, &x0, &rep, _state);
if( rep.terminationtype<=0 )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
for(i=0; i<=n-1; i++)
{
if( ae_fp_greater(ae_fabs(xe.ptr.p_double[i]-x0.ptr.p_double[i], _state),5.0E-2/d.ptr.p_double[i]) )
{
result = ae_true;
ae_frame_leave(_state);
return result;
}
}
/*
*test has been passed
*/
if( !silent )
{
printf("PrecondTest::Ok\n");
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Orthogonalization by Gram-Shmidt method.
*************************************************************************/
static void testlincgunit_gramshmidtortnorm(/* Real */ ae_matrix* a,
ae_int_t n,
ae_int_t k,
double eps,
/* Real */ ae_matrix* b,
ae_int_t* k2,
ae_state *_state)
{
double scaling;
double tmp;
double e;
ae_int_t i;
ae_int_t j;
ae_int_t l;
ae_int_t m;
double sc;
ae_matrix_clear(b);
*k2 = 0;
*k2 = 0;
scaling = (double)(0);
ae_matrix_set_length(b, k, n, _state);
for(i=0; i<=k-1; i++)
{
tmp = (double)(0);
for(j=0; j<=n-1; j++)
{
tmp = tmp+a->ptr.pp_double[i][j]*a->ptr.pp_double[i][j];
}
if( ae_fp_greater(tmp,scaling) )
{
scaling = tmp;
}
}
scaling = ae_sqrt(scaling, _state);
e = eps*scaling;
for(i=0; i<=k-1; i++)
{
tmp = (double)(0);
for(j=0; j<=n-1; j++)
{
b->ptr.pp_double[*k2][j] = a->ptr.pp_double[i][j];
tmp = tmp+a->ptr.pp_double[i][j]*a->ptr.pp_double[i][j];
}
tmp = ae_sqrt(tmp, _state);
if( ae_fp_less_eq(tmp,e) )
{
continue;
}
for(j=0; j<=*k2-1; j++)
{
sc = (double)(0);
for(m=0; m<=n-1; m++)
{
sc = sc+b->ptr.pp_double[*k2][m]*b->ptr.pp_double[j][m];
}
for(l=0; l<=n-1; l++)
{
b->ptr.pp_double[*k2][l] = b->ptr.pp_double[*k2][l]-sc*b->ptr.pp_double[j][l];
}
}
tmp = (double)(0);
for(j=0; j<=n-1; j++)
{
tmp = tmp+b->ptr.pp_double[*k2][j]*b->ptr.pp_double[*k2][j];
}
tmp = ae_sqrt(tmp, _state);
if( ae_fp_less_eq(tmp,e) )
{
continue;
}
else
{
for(j=0; j<=n-1; j++)
{
b->ptr.pp_double[*k2][j] = b->ptr.pp_double[*k2][j]/tmp;
}
}
*k2 = *k2+1;
}
}
/*************************************************************************
Checks that a vector belongs to the basis.
*************************************************************************/
static ae_bool testlincgunit_frombasis(/* Real */ ae_vector* x,
/* Real */ ae_matrix* basis,
ae_int_t n,
ae_int_t k,
double eps,
ae_state *_state)
{
ae_frame _frame_block;
double normx;
ae_matrix ortnormbasis;
ae_int_t k2;
ae_int_t i;
ae_int_t j;
double alpha;
ae_vector alphas;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&ortnormbasis, 0, sizeof(ortnormbasis));
memset(&alphas, 0, sizeof(alphas));
ae_matrix_init(&ortnormbasis, 0, 0, DT_REAL, _state, ae_true);
ae_vector_init(&alphas, 0, DT_REAL, _state, ae_true);
ae_vector_set_length(&alphas, k, _state);
/*
*calculating NORM for X
*/
normx = (double)(0);
for(i=0; i<=n-1; i++)
{
normx = normx+x->ptr.p_double[i]*x->ptr.p_double[i];
}
normx = ae_sqrt(normx, _state);
/*
*Gram-Shmidt method
*/
testlincgunit_gramshmidtortnorm(basis, n, k, eps, &ortnormbasis, &k2, _state);
for(i=0; i<=k2-1; i++)
{
alpha = (double)(0);
for(j=0; j<=n-1; j++)
{
alpha = alpha+x->ptr.p_double[j]*ortnormbasis.ptr.pp_double[i][j];
}
alphas.ptr.p_double[i] = alpha;
}
/*
*check
*/
for(i=0; i<=n-1; i++)
{
alpha = (double)(0);
for(j=0; j<=k2-1; j++)
{
alpha = alpha+alphas.ptr.p_double[j]*ortnormbasis.ptr.pp_double[j][i];
}
if( ae_fp_greater(ae_fabs(x->ptr.p_double[i]-alpha, _state),normx*eps) )
{
result = ae_false;
ae_frame_leave(_state);
return result;
}
}
result = ae_true;
ae_frame_leave(_state);
return result;
}
static ae_bool testalglibbasicsunit_testcomplexarithmetics(ae_bool silent,
ae_state *_state);
static ae_bool testalglibbasicsunit_testieeespecial(ae_bool silent,
ae_state *_state);
static ae_bool testalglibbasicsunit_testswapfunctions(ae_bool silent,
ae_state *_state);
static ae_bool testalglibbasicsunit_teststandardfunctions(ae_bool silent,
ae_state *_state);
static ae_bool testalglibbasicsunit_testserializationfunctions(ae_bool silent,
ae_state *_state);
static void testalglibbasicsunit_createpoolandrecords(poolrec2* seedrec2,
poolrec2* seedrec2copy,
ae_shared_pool* pool,
ae_state *_state);
static ae_bool testalglibbasicsunit_sharedpoolerrors(ae_state *_state);
static ae_bool testalglibbasicsunit_testsharedpool(ae_bool silent,
ae_state *_state);
static void testalglibbasicsunit_testsort0func(/* Integer */ ae_vector* a,
/* Integer */ ae_vector* buf,
ae_int_t idx0,
ae_int_t idx2,
ae_state *_state);
ae_bool _trypexec_testalglibbasicsunit_testsort0func(/* Integer */ ae_vector* a,
/* Integer */ ae_vector* buf,
ae_int_t idx0,
ae_int_t idx2, ae_state *_state);
static ae_bool testalglibbasicsunit_performtestsort0(ae_state *_state);
static void testalglibbasicsunit_testsort1func(/* Integer */ ae_vector* a,
/* Integer */ ae_vector* buf,
ae_int_t idx0,
ae_int_t idx2,
ae_bool usesmp,
ae_state *_state);
ae_bool _trypexec_testalglibbasicsunit_testsort1func(/* Integer */ ae_vector* a,
/* Integer */ ae_vector* buf,
ae_int_t idx0,
ae_int_t idx2,
ae_bool usesmp, ae_state *_state);
static ae_bool testalglibbasicsunit_performtestsort1(ae_state *_state);
static void testalglibbasicsunit_testsort2func(/* Integer */ ae_vector* a,
/* Integer */ ae_vector* buf,
ae_int_t idx0,
ae_int_t idx2,
ae_state *_state);
ae_bool _trypexec_testalglibbasicsunit_testsort2func(/* Integer */ ae_vector* a,
/* Integer */ ae_vector* buf,
ae_int_t idx0,
ae_int_t idx2, ae_state *_state);
static ae_bool testalglibbasicsunit_performtestsort2(ae_state *_state);
static ae_bool testalglibbasicsunit_performtestpoolsum(ae_state *_state);
static void testalglibbasicsunit_parallelpoolsum(ae_shared_pool* sumpool,
ae_int_t ind0,
ae_int_t ind1,
ae_state *_state);
ae_bool _trypexec_testalglibbasicsunit_parallelpoolsum(ae_shared_pool* sumpool,
ae_int_t ind0,
ae_int_t ind1, ae_state *_state);
static void testalglibbasicsunit_mergesortedarrays(/* Integer */ ae_vector* a,
/* Integer */ ae_vector* buf,
ae_int_t idx0,
ae_int_t idx1,
ae_int_t idx2,
ae_state *_state);
ae_bool _trypexec_testalglibbasicsunit_mergesortedarrays(/* Integer */ ae_vector* a,
/* Integer */ ae_vector* buf,
ae_int_t idx0,
ae_int_t idx1,
ae_int_t idx2, ae_state *_state);
static ae_bool testalglibbasicsunit_testsmp(ae_bool silent,
ae_state *_state);
void rec4serializationalloc(ae_serializer* s,
rec4serialization* v,
ae_state *_state)
{
ae_int_t i;
/*
* boolean fields
*/
ae_serializer_alloc_entry(s);
for(i=0; i<=v->b.cnt-1; i++)
{
ae_serializer_alloc_entry(s);
}
/*
* integer fields
*/
ae_serializer_alloc_entry(s);
for(i=0; i<=v->i.cnt-1; i++)
{
ae_serializer_alloc_entry(s);
}
/*
* real fields
*/
ae_serializer_alloc_entry(s);
for(i=0; i<=v->r.cnt-1; i++)
{
ae_serializer_alloc_entry(s);
}
}
void rec4serializationserialize(ae_serializer* s,
rec4serialization* v,
ae_state *_state)
{
ae_int_t i;
/*
* boolean fields
*/
ae_serializer_serialize_int(s, v->b.cnt, _state);
for(i=0; i<=v->b.cnt-1; i++)
{
ae_serializer_serialize_bool(s, v->b.ptr.p_bool[i], _state);
}
/*
* integer fields
*/
ae_serializer_serialize_int(s, v->i.cnt, _state);
for(i=0; i<=v->i.cnt-1; i++)
{
ae_serializer_serialize_int(s, v->i.ptr.p_int[i], _state);
}
/*
* real fields
*/
ae_serializer_serialize_int(s, v->r.cnt, _state);
for(i=0; i<=v->r.cnt-1; i++)
{
ae_serializer_serialize_double(s, v->r.ptr.p_double[i], _state);
}
}
void rec4serializationunserialize(ae_serializer* s,
rec4serialization* v,
ae_state *_state)
{
ae_int_t i;
ae_int_t k;
ae_bool bv;
ae_int_t iv;
double rv;
_rec4serialization_clear(v);
/*
* boolean fields
*/
ae_serializer_unserialize_int(s, &k, _state);
if( k>0 )
{
ae_vector_set_length(&v->b, k, _state);
for(i=0; i<=k-1; i++)
{
ae_serializer_unserialize_bool(s, &bv, _state);
v->b.ptr.p_bool[i] = bv;
}
}
/*
* integer fields
*/
ae_serializer_unserialize_int(s, &k, _state);
if( k>0 )
{
ae_vector_set_length(&v->i, k, _state);
for(i=0; i<=k-1; i++)
{
ae_serializer_unserialize_int(s, &iv, _state);
v->i.ptr.p_int[i] = iv;
}
}
/*
* real fields
*/
ae_serializer_unserialize_int(s, &k, _state);
if( k>0 )
{
ae_vector_set_length(&v->r, k, _state);
for(i=0; i<=k-1; i++)
{
ae_serializer_unserialize_double(s, &rv, _state);
v->r.ptr.p_double[i] = rv;
}
}
}
ae_bool testalglibbasics(ae_bool silent, ae_state *_state)
{
ae_bool result;
result = ae_true;
result = result&&testalglibbasicsunit_testcomplexarithmetics(silent, _state);
result = result&&testalglibbasicsunit_testieeespecial(silent, _state);
result = result&&testalglibbasicsunit_testswapfunctions(silent, _state);
result = result&&testalglibbasicsunit_teststandardfunctions(silent, _state);
result = result&&testalglibbasicsunit_testserializationfunctions(silent, _state);
result = result&&testalglibbasicsunit_testsharedpool(silent, _state);
result = result&&testalglibbasicsunit_testsmp(silent, _state);
if( !silent )
{
printf("\n\n");
}
return result;
}
/*************************************************************************
Complex arithmetics test
*************************************************************************/
static ae_bool testalglibbasicsunit_testcomplexarithmetics(ae_bool silent,
ae_state *_state)
{
ae_bool absc;
ae_bool addcc;
ae_bool addcr;
ae_bool addrc;
ae_bool subcc;
ae_bool subcr;
ae_bool subrc;
ae_bool mulcc;
ae_bool mulcr;
ae_bool mulrc;
ae_bool divcc;
ae_bool divcr;
ae_bool divrc;
ae_complex ca;
ae_complex cb;
ae_complex res;
double ra;
double rb;
double threshold;
ae_int_t pass;
ae_int_t passcount;
ae_bool result;
threshold = 100*ae_machineepsilon;
passcount = 1000;
result = ae_true;
absc = ae_true;
addcc = ae_true;
addcr = ae_true;
addrc = ae_true;
subcc = ae_true;
subcr = ae_true;
subrc = ae_true;
mulcc = ae_true;
mulcr = ae_true;
mulrc = ae_true;
divcc = ae_true;
divcr = ae_true;
divrc = ae_true;
for(pass=1; pass<=passcount; pass++)
{
/*
* Test AbsC
*/
ca.x = 2*ae_randomreal(_state)-1;
ca.y = 2*ae_randomreal(_state)-1;
ra = ae_c_abs(ca, _state);
absc = absc&&ae_fp_less(ae_fabs(ra-ae_sqrt(ae_sqr(ca.x, _state)+ae_sqr(ca.y, _state), _state), _state),threshold);
/*
* test Add
*/
ca.x = 2*ae_randomreal(_state)-1;
ca.y = 2*ae_randomreal(_state)-1;
cb.x = 2*ae_randomreal(_state)-1;
cb.y = 2*ae_randomreal(_state)-1;
ra = 2*ae_randomreal(_state)-1;
rb = 2*ae_randomreal(_state)-1;
res = ae_c_add(ca,cb);
addcc = (addcc&&ae_fp_less(ae_fabs(res.x-ca.x-cb.x, _state),threshold))&&ae_fp_less(ae_fabs(res.y-ca.y-cb.y, _state),threshold);
res = ae_c_add_d(ca,rb);
addcr = (addcr&&ae_fp_less(ae_fabs(res.x-ca.x-rb, _state),threshold))&&ae_fp_less(ae_fabs(res.y-ca.y, _state),threshold);
res = ae_c_add_d(cb,ra);
addrc = (addrc&&ae_fp_less(ae_fabs(res.x-ra-cb.x, _state),threshold))&&ae_fp_less(ae_fabs(res.y-cb.y, _state),threshold);
/*
* test Sub
*/
ca.x = 2*ae_randomreal(_state)-1;
ca.y = 2*ae_randomreal(_state)-1;
cb.x = 2*ae_randomreal(_state)-1;
cb.y = 2*ae_randomreal(_state)-1;
ra = 2*ae_randomreal(_state)-1;
rb = 2*ae_randomreal(_state)-1;
res = ae_c_sub(ca,cb);
subcc = (subcc&&ae_fp_less(ae_fabs(res.x-(ca.x-cb.x), _state),threshold))&&ae_fp_less(ae_fabs(res.y-(ca.y-cb.y), _state),threshold);
res = ae_c_sub_d(ca,rb);
subcr = (subcr&&ae_fp_less(ae_fabs(res.x-(ca.x-rb), _state),threshold))&&ae_fp_less(ae_fabs(res.y-ca.y, _state),threshold);
res = ae_c_d_sub(ra,cb);
subrc = (subrc&&ae_fp_less(ae_fabs(res.x-(ra-cb.x), _state),threshold))&&ae_fp_less(ae_fabs(res.y+cb.y, _state),threshold);
/*
* test Mul
*/
ca.x = 2*ae_randomreal(_state)-1;
ca.y = 2*ae_randomreal(_state)-1;
cb.x = 2*ae_randomreal(_state)-1;
cb.y = 2*ae_randomreal(_state)-1;
ra = 2*ae_randomreal(_state)-1;
rb = 2*ae_randomreal(_state)-1;
res = ae_c_mul(ca,cb);
mulcc = (mulcc&&ae_fp_less(ae_fabs(res.x-(ca.x*cb.x-ca.y*cb.y), _state),threshold))&&ae_fp_less(ae_fabs(res.y-(ca.x*cb.y+ca.y*cb.x), _state),threshold);
res = ae_c_mul_d(ca,rb);
mulcr = (mulcr&&ae_fp_less(ae_fabs(res.x-ca.x*rb, _state),threshold))&&ae_fp_less(ae_fabs(res.y-ca.y*rb, _state),threshold);
res = ae_c_mul_d(cb,ra);
mulrc = (mulrc&&ae_fp_less(ae_fabs(res.x-ra*cb.x, _state),threshold))&&ae_fp_less(ae_fabs(res.y-ra*cb.y, _state),threshold);
/*
* test Div
*/
ca.x = 2*ae_randomreal(_state)-1;
ca.y = 2*ae_randomreal(_state)-1;
do
{
cb.x = 2*ae_randomreal(_state)-1;
cb.y = 2*ae_randomreal(_state)-1;
}
while(ae_fp_less_eq(ae_c_abs(cb, _state),0.5));
ra = 2*ae_randomreal(_state)-1;
do
{
rb = 2*ae_randomreal(_state)-1;
}
while(ae_fp_less_eq(ae_fabs(rb, _state),0.5));
res = ae_c_div(ca,cb);
divcc = (divcc&&ae_fp_less(ae_fabs(ae_c_mul(res,cb).x-ca.x, _state),threshold))&&ae_fp_less(ae_fabs(ae_c_mul(res,cb).y-ca.y, _state),threshold);
res = ae_c_div_d(ca,rb);
divcr = (divcr&&ae_fp_less(ae_fabs(res.x-ca.x/rb, _state),threshold))&&ae_fp_less(ae_fabs(res.y-ca.y/rb, _state),threshold);
res = ae_c_d_div(ra,cb);
divrc = (divrc&&ae_fp_less(ae_fabs(ae_c_mul(res,cb).x-ra, _state),threshold))&&ae_fp_less(ae_fabs(ae_c_mul(res,cb).y, _state),threshold);
}
/*
* summary
*/
result = result&&absc;
result = result&&addcc;
result = result&&addcr;
result = result&&addrc;
result = result&&subcc;
result = result&&subcr;
result = result&&subrc;
result = result&&mulcc;
result = result&&mulcr;
result = result&&mulrc;
result = result&&divcc;
result = result&&divcr;
result = result&&divrc;
if( !silent )
{
if( result )
{
printf("COMPLEX ARITHMETICS: OK\n");
}
else
{
printf("COMPLEX ARITHMETICS: FAILED\n");
printf("* AddCC - - - - - - - - - - - - - - - - ");
if( addcc )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* AddCR - - - - - - - - - - - - - - - - ");
if( addcr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* AddRC - - - - - - - - - - - - - - - - ");
if( addrc )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* SubCC - - - - - - - - - - - - - - - - ");
if( subcc )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* SubCR - - - - - - - - - - - - - - - - ");
if( subcr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* SubRC - - - - - - - - - - - - - - - - ");
if( subrc )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* MulCC - - - - - - - - - - - - - - - - ");
if( mulcc )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* MulCR - - - - - - - - - - - - - - - - ");
if( mulcr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* MulRC - - - - - - - - - - - - - - - - ");
if( mulrc )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* DivCC - - - - - - - - - - - - - - - - ");
if( divcc )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* DivCR - - - - - - - - - - - - - - - - ");
if( divcr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* DivRC - - - - - - - - - - - - - - - - ");
if( divrc )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
}
}
return result;
}
/*************************************************************************
Tests for IEEE special quantities
*************************************************************************/
static ae_bool testalglibbasicsunit_testieeespecial(ae_bool silent,
ae_state *_state)
{
ae_bool oknan;
ae_bool okinf;
ae_bool okother;
double v1;
double v2;
ae_bool result;
result = ae_true;
oknan = ae_true;
okinf = ae_true;
okother = ae_true;
/*
* Test classification functions
*/
okother = okother&&!ae_isinf(_state->v_nan, _state);
okother = okother&&ae_isinf(_state->v_posinf, _state);
okother = okother&&!ae_isinf(ae_maxrealnumber, _state);
okother = okother&&!ae_isinf(1.0, _state);
okother = okother&&!ae_isinf(ae_minrealnumber, _state);
okother = okother&&!ae_isinf(0.0, _state);
okother = okother&&!ae_isinf(-ae_minrealnumber, _state);
okother = okother&&!ae_isinf(-1.0, _state);
okother = okother&&!ae_isinf(-ae_maxrealnumber, _state);
okother = okother&&ae_isinf(_state->v_neginf, _state);
okother = okother&&!ae_isposinf(_state->v_nan, _state);
okother = okother&&ae_isposinf(_state->v_posinf, _state);
okother = okother&&!ae_isposinf(ae_maxrealnumber, _state);
okother = okother&&!ae_isposinf(1.0, _state);
okother = okother&&!ae_isposinf(ae_minrealnumber, _state);
okother = okother&&!ae_isposinf(0.0, _state);
okother = okother&&!ae_isposinf(-ae_minrealnumber, _state);
okother = okother&&!ae_isposinf(-1.0, _state);
okother = okother&&!ae_isposinf(-ae_maxrealnumber, _state);
okother = okother&&!ae_isposinf(_state->v_neginf, _state);
okother = okother&&!ae_isneginf(_state->v_nan, _state);
okother = okother&&!ae_isneginf(_state->v_posinf, _state);
okother = okother&&!ae_isneginf(ae_maxrealnumber, _state);
okother = okother&&!ae_isneginf(1.0, _state);
okother = okother&&!ae_isneginf(ae_minrealnumber, _state);
okother = okother&&!ae_isneginf(0.0, _state);
okother = okother&&!ae_isneginf(-ae_minrealnumber, _state);
okother = okother&&!ae_isneginf(-1.0, _state);
okother = okother&&!ae_isneginf(-ae_maxrealnumber, _state);
okother = okother&&ae_isneginf(_state->v_neginf, _state);
okother = okother&&ae_isnan(_state->v_nan, _state);
okother = okother&&!ae_isnan(_state->v_posinf, _state);
okother = okother&&!ae_isnan(ae_maxrealnumber, _state);
okother = okother&&!ae_isnan(1.0, _state);
okother = okother&&!ae_isnan(ae_minrealnumber, _state);
okother = okother&&!ae_isnan(0.0, _state);
okother = okother&&!ae_isnan(-ae_minrealnumber, _state);
okother = okother&&!ae_isnan(-1.0, _state);
okother = okother&&!ae_isnan(-ae_maxrealnumber, _state);
okother = okother&&!ae_isnan(_state->v_neginf, _state);
okother = okother&&!ae_isfinite(_state->v_nan, _state);
okother = okother&&!ae_isfinite(_state->v_posinf, _state);
okother = okother&&ae_isfinite(ae_maxrealnumber, _state);
okother = okother&&ae_isfinite(1.0, _state);
okother = okother&&ae_isfinite(ae_minrealnumber, _state);
okother = okother&&ae_isfinite(0.0, _state);
okother = okother&&ae_isfinite(-ae_minrealnumber, _state);
okother = okother&&ae_isfinite(-1.0, _state);
okother = okother&&ae_isfinite(-ae_maxrealnumber, _state);
okother = okother&&!ae_isfinite(_state->v_neginf, _state);
/*
* Test NAN
*/
v1 = _state->v_nan;
v2 = _state->v_nan;
oknan = oknan&&ae_isnan(v1, _state);
oknan = oknan&&ae_fp_neq(v1,v2);
oknan = oknan&&!ae_fp_eq(v1,v2);
/*
* Test INF:
* * basic properties
* * comparisons involving PosINF on one of the sides
* * comparisons involving NegINF on one of the sides
*/
v1 = _state->v_posinf;
v2 = _state->v_neginf;
okinf = okinf&&ae_isinf(_state->v_posinf, _state);
okinf = okinf&&ae_isinf(v1, _state);
okinf = okinf&&ae_isinf(_state->v_neginf, _state);
okinf = okinf&&ae_isinf(v2, _state);
okinf = okinf&&ae_isposinf(_state->v_posinf, _state);
okinf = okinf&&ae_isposinf(v1, _state);
okinf = okinf&&!ae_isposinf(_state->v_neginf, _state);
okinf = okinf&&!ae_isposinf(v2, _state);
okinf = okinf&&!ae_isneginf(_state->v_posinf, _state);
okinf = okinf&&!ae_isneginf(v1, _state);
okinf = okinf&&ae_isneginf(_state->v_neginf, _state);
okinf = okinf&&ae_isneginf(v2, _state);
okinf = okinf&&ae_fp_eq(_state->v_posinf,_state->v_posinf);
okinf = okinf&&ae_fp_eq(_state->v_posinf,v1);
okinf = okinf&&!ae_fp_eq(_state->v_posinf,_state->v_neginf);
okinf = okinf&&!ae_fp_eq(_state->v_posinf,v2);
okinf = okinf&&!ae_fp_eq(_state->v_posinf,(double)(0));
okinf = okinf&&!ae_fp_eq(_state->v_posinf,1.2);
okinf = okinf&&!ae_fp_eq(_state->v_posinf,-1.2);
okinf = okinf&&ae_fp_eq(v1,_state->v_posinf);
okinf = okinf&&!ae_fp_eq(_state->v_neginf,_state->v_posinf);
okinf = okinf&&!ae_fp_eq(v2,_state->v_posinf);
okinf = okinf&&!ae_fp_eq((double)(0),_state->v_posinf);
okinf = okinf&&!ae_fp_eq(1.2,_state->v_posinf);
okinf = okinf&&!ae_fp_eq(-1.2,_state->v_posinf);
okinf = okinf&&!ae_fp_neq(_state->v_posinf,_state->v_posinf);
okinf = okinf&&!ae_fp_neq(_state->v_posinf,v1);
okinf = okinf&&ae_fp_neq(_state->v_posinf,_state->v_neginf);
okinf = okinf&&ae_fp_neq(_state->v_posinf,v2);
okinf = okinf&&ae_fp_neq(_state->v_posinf,(double)(0));
okinf = okinf&&ae_fp_neq(_state->v_posinf,1.2);
okinf = okinf&&ae_fp_neq(_state->v_posinf,-1.2);
okinf = okinf&&!ae_fp_neq(v1,_state->v_posinf);
okinf = okinf&&ae_fp_neq(_state->v_neginf,_state->v_posinf);
okinf = okinf&&ae_fp_neq(v2,_state->v_posinf);
okinf = okinf&&ae_fp_neq((double)(0),_state->v_posinf);
okinf = okinf&&ae_fp_neq(1.2,_state->v_posinf);
okinf = okinf&&ae_fp_neq(-1.2,_state->v_posinf);
okinf = okinf&&!ae_fp_less(_state->v_posinf,_state->v_posinf);
okinf = okinf&&!ae_fp_less(_state->v_posinf,v1);
okinf = okinf&&!ae_fp_less(_state->v_posinf,_state->v_neginf);
okinf = okinf&&!ae_fp_less(_state->v_posinf,v2);
okinf = okinf&&!ae_fp_less(_state->v_posinf,(double)(0));
okinf = okinf&&!ae_fp_less(_state->v_posinf,1.2);
okinf = okinf&&!ae_fp_less(_state->v_posinf,-1.2);
okinf = okinf&&!ae_fp_less(v1,_state->v_posinf);
okinf = okinf&&ae_fp_less(_state->v_neginf,_state->v_posinf);
okinf = okinf&&ae_fp_less(v2,_state->v_posinf);
okinf = okinf&&ae_fp_less((double)(0),_state->v_posinf);
okinf = okinf&&ae_fp_less(1.2,_state->v_posinf);
okinf = okinf&&ae_fp_less(-1.2,_state->v_posinf);
okinf = okinf&&ae_fp_less_eq(_state->v_posinf,_state->v_posinf);
okinf = okinf&&ae_fp_less_eq(_state->v_posinf,v1);
okinf = okinf&&!ae_fp_less_eq(_state->v_posinf,_state->v_neginf);
okinf = okinf&&!ae_fp_less_eq(_state->v_posinf,v2);
okinf = okinf&&!ae_fp_less_eq(_state->v_posinf,(double)(0));
okinf = okinf&&!ae_fp_less_eq(_state->v_posinf,1.2);
okinf = okinf&&!ae_fp_less_eq(_state->v_posinf,-1.2);
okinf = okinf&&ae_fp_less_eq(v1,_state->v_posinf);
okinf = okinf&&ae_fp_less_eq(_state->v_neginf,_state->v_posinf);
okinf = okinf&&ae_fp_less_eq(v2,_state->v_posinf);
okinf = okinf&&ae_fp_less_eq((double)(0),_state->v_posinf);
okinf = okinf&&ae_fp_less_eq(1.2,_state->v_posinf);
okinf = okinf&&ae_fp_less_eq(-1.2,_state->v_posinf);
okinf = okinf&&!ae_fp_greater(_state->v_posinf,_state->v_posinf);
okinf = okinf&&!ae_fp_greater(_state->v_posinf,v1);
okinf = okinf&&ae_fp_greater(_state->v_posinf,_state->v_neginf);
okinf = okinf&&ae_fp_greater(_state->v_posinf,v2);
okinf = okinf&&ae_fp_greater(_state->v_posinf,(double)(0));
okinf = okinf&&ae_fp_greater(_state->v_posinf,1.2);
okinf = okinf&&ae_fp_greater(_state->v_posinf,-1.2);
okinf = okinf&&!ae_fp_greater(v1,_state->v_posinf);
okinf = okinf&&!ae_fp_greater(_state->v_neginf,_state->v_posinf);
okinf = okinf&&!ae_fp_greater(v2,_state->v_posinf);
okinf = okinf&&!ae_fp_greater((double)(0),_state->v_posinf);
okinf = okinf&&!ae_fp_greater(1.2,_state->v_posinf);
okinf = okinf&&!ae_fp_greater(-1.2,_state->v_posinf);
okinf = okinf&&ae_fp_greater_eq(_state->v_posinf,_state->v_posinf);
okinf = okinf&&ae_fp_greater_eq(_state->v_posinf,v1);
okinf = okinf&&ae_fp_greater_eq(_state->v_posinf,_state->v_neginf);
okinf = okinf&&ae_fp_greater_eq(_state->v_posinf,v2);
okinf = okinf&&ae_fp_greater_eq(_state->v_posinf,(double)(0));
okinf = okinf&&ae_fp_greater_eq(_state->v_posinf,1.2);
okinf = okinf&&ae_fp_greater_eq(_state->v_posinf,-1.2);
okinf = okinf&&ae_fp_greater_eq(v1,_state->v_posinf);
okinf = okinf&&!ae_fp_greater_eq(_state->v_neginf,_state->v_posinf);
okinf = okinf&&!ae_fp_greater_eq(v2,_state->v_posinf);
okinf = okinf&&!ae_fp_greater_eq((double)(0),_state->v_posinf);
okinf = okinf&&!ae_fp_greater_eq(1.2,_state->v_posinf);
okinf = okinf&&!ae_fp_greater_eq(-1.2,_state->v_posinf);
okinf = okinf&&!ae_fp_eq(_state->v_neginf,_state->v_posinf);
okinf = okinf&&!ae_fp_eq(_state->v_neginf,v1);
okinf = okinf&&ae_fp_eq(_state->v_neginf,_state->v_neginf);
okinf = okinf&&ae_fp_eq(_state->v_neginf,v2);
okinf = okinf&&!ae_fp_eq(_state->v_neginf,(double)(0));
okinf = okinf&&!ae_fp_eq(_state->v_neginf,1.2);
okinf = okinf&&!ae_fp_eq(_state->v_neginf,-1.2);
okinf = okinf&&!ae_fp_eq(v1,_state->v_neginf);
okinf = okinf&&ae_fp_eq(_state->v_neginf,_state->v_neginf);
okinf = okinf&&ae_fp_eq(v2,_state->v_neginf);
okinf = okinf&&!ae_fp_eq((double)(0),_state->v_neginf);
okinf = okinf&&!ae_fp_eq(1.2,_state->v_neginf);
okinf = okinf&&!ae_fp_eq(-1.2,_state->v_neginf);
okinf = okinf&&ae_fp_neq(_state->v_neginf,_state->v_posinf);
okinf = okinf&&ae_fp_neq(_state->v_neginf,v1);
okinf = okinf&&!ae_fp_neq(_state->v_neginf,_state->v_neginf);
okinf = okinf&&!ae_fp_neq(_state->v_neginf,v2);
okinf = okinf&&ae_fp_neq(_state->v_neginf,(double)(0));
okinf = okinf&&ae_fp_neq(_state->v_neginf,1.2);
okinf = okinf&&ae_fp_neq(_state->v_neginf,-1.2);
okinf = okinf&&ae_fp_neq(v1,_state->v_neginf);
okinf = okinf&&!ae_fp_neq(_state->v_neginf,_state->v_neginf);
okinf = okinf&&!ae_fp_neq(v2,_state->v_neginf);
okinf = okinf&&ae_fp_neq((double)(0),_state->v_neginf);
okinf = okinf&&ae_fp_neq(1.2,_state->v_neginf);
okinf = okinf&&ae_fp_neq(-1.2,_state->v_neginf);
okinf = okinf&&ae_fp_less(_state->v_neginf,_state->v_posinf);
okinf = okinf&&ae_fp_less(_state->v_neginf,v1);
okinf = okinf&&!ae_fp_less(_state->v_neginf,_state->v_neginf);
okinf = okinf&&!ae_fp_less(_state->v_neginf,v2);
okinf = okinf&&ae_fp_less(_state->v_neginf,(double)(0));
okinf = okinf&&ae_fp_less(_state->v_neginf,1.2);
okinf = okinf&&ae_fp_less(_state->v_neginf,-1.2);
okinf = okinf&&!ae_fp_less(v1,_state->v_neginf);
okinf = okinf&&!ae_fp_less(_state->v_neginf,_state->v_neginf);
okinf = okinf&&!ae_fp_less(v2,_state->v_neginf);
okinf = okinf&&!ae_fp_less((double)(0),_state->v_neginf);
okinf = okinf&&!ae_fp_less(1.2,_state->v_neginf);
okinf = okinf&&!ae_fp_less(-1.2,_state->v_neginf);
okinf = okinf&&ae_fp_less_eq(_state->v_neginf,_state->v_posinf);
okinf = okinf&&ae_fp_less_eq(_state->v_neginf,v1);
okinf = okinf&&ae_fp_less_eq(_state->v_neginf,_state->v_neginf);
okinf = okinf&&ae_fp_less_eq(_state->v_neginf,v2);
okinf = okinf&&ae_fp_less_eq(_state->v_neginf,(double)(0));
okinf = okinf&&ae_fp_less_eq(_state->v_neginf,1.2);
okinf = okinf&&ae_fp_less_eq(_state->v_neginf,-1.2);
okinf = okinf&&!ae_fp_less_eq(v1,_state->v_neginf);
okinf = okinf&&ae_fp_less_eq(_state->v_neginf,_state->v_neginf);
okinf = okinf&&ae_fp_less_eq(v2,_state->v_neginf);
okinf = okinf&&!ae_fp_less_eq((double)(0),_state->v_neginf);
okinf = okinf&&!ae_fp_less_eq(1.2,_state->v_neginf);
okinf = okinf&&!ae_fp_less_eq(-1.2,_state->v_neginf);
okinf = okinf&&!ae_fp_greater(_state->v_neginf,_state->v_posinf);
okinf = okinf&&!ae_fp_greater(_state->v_neginf,v1);
okinf = okinf&&!ae_fp_greater(_state->v_neginf,_state->v_neginf);
okinf = okinf&&!ae_fp_greater(_state->v_neginf,v2);
okinf = okinf&&!ae_fp_greater(_state->v_neginf,(double)(0));
okinf = okinf&&!ae_fp_greater(_state->v_neginf,1.2);
okinf = okinf&&!ae_fp_greater(_state->v_neginf,-1.2);
okinf = okinf&&ae_fp_greater(v1,_state->v_neginf);
okinf = okinf&&!ae_fp_greater(_state->v_neginf,_state->v_neginf);
okinf = okinf&&!ae_fp_greater(v2,_state->v_neginf);
okinf = okinf&&ae_fp_greater((double)(0),_state->v_neginf);
okinf = okinf&&ae_fp_greater(1.2,_state->v_neginf);
okinf = okinf&&ae_fp_greater(-1.2,_state->v_neginf);
okinf = okinf&&!ae_fp_greater_eq(_state->v_neginf,_state->v_posinf);
okinf = okinf&&!ae_fp_greater_eq(_state->v_neginf,v1);
okinf = okinf&&ae_fp_greater_eq(_state->v_neginf,_state->v_neginf);
okinf = okinf&&ae_fp_greater_eq(_state->v_neginf,v2);
okinf = okinf&&!ae_fp_greater_eq(_state->v_neginf,(double)(0));
okinf = okinf&&!ae_fp_greater_eq(_state->v_neginf,1.2);
okinf = okinf&&!ae_fp_greater_eq(_state->v_neginf,-1.2);
okinf = okinf&&ae_fp_greater_eq(v1,_state->v_neginf);
okinf = okinf&&ae_fp_greater_eq(_state->v_neginf,_state->v_neginf);
okinf = okinf&&ae_fp_greater_eq(v2,_state->v_neginf);
okinf = okinf&&ae_fp_greater_eq((double)(0),_state->v_neginf);
okinf = okinf&&ae_fp_greater_eq(1.2,_state->v_neginf);
okinf = okinf&&ae_fp_greater_eq(-1.2,_state->v_neginf);
/*
* summary
*/
result = result&&oknan;
result = result&&okinf;
result = result&&okother;
if( !silent )
{
if( result )
{
printf("IEEE SPECIAL VALUES: OK\n");
}
else
{
printf("IEEE SPECIAL VALUES: FAILED\n");
printf("* NAN - - - - - - - - - - - - - - - - - ");
if( oknan )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* INF - - - - - - - - - - - - - - - - - ");
if( okinf )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* FUNCTIONS - - - - - - - - - - - - - - ");
if( okother )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
}
}
return result;
}
/*************************************************************************
Tests for swapping functions
*************************************************************************/
static ae_bool testalglibbasicsunit_testswapfunctions(ae_bool silent,
ae_state *_state)
{
ae_frame _frame_block;
ae_bool okb1;
ae_bool okb2;
ae_bool oki1;
ae_bool oki2;
ae_bool okr1;
ae_bool okr2;
ae_bool okc1;
ae_bool okc2;
ae_vector b11;
ae_vector b12;
ae_vector i11;
ae_vector i12;
ae_vector r11;
ae_vector r12;
ae_vector c11;
ae_vector c12;
ae_matrix b21;
ae_matrix b22;
ae_matrix i21;
ae_matrix i22;
ae_matrix r21;
ae_matrix r22;
ae_matrix c21;
ae_matrix c22;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&b11, 0, sizeof(b11));
memset(&b12, 0, sizeof(b12));
memset(&i11, 0, sizeof(i11));
memset(&i12, 0, sizeof(i12));
memset(&r11, 0, sizeof(r11));
memset(&r12, 0, sizeof(r12));
memset(&c11, 0, sizeof(c11));
memset(&c12, 0, sizeof(c12));
memset(&b21, 0, sizeof(b21));
memset(&b22, 0, sizeof(b22));
memset(&i21, 0, sizeof(i21));
memset(&i22, 0, sizeof(i22));
memset(&r21, 0, sizeof(r21));
memset(&r22, 0, sizeof(r22));
memset(&c21, 0, sizeof(c21));
memset(&c22, 0, sizeof(c22));
ae_vector_init(&b11, 0, DT_BOOL, _state, ae_true);
ae_vector_init(&b12, 0, DT_BOOL, _state, ae_true);
ae_vector_init(&i11, 0, DT_INT, _state, ae_true);
ae_vector_init(&i12, 0, DT_INT, _state, ae_true);
ae_vector_init(&r11, 0, DT_REAL, _state, ae_true);
ae_vector_init(&r12, 0, DT_REAL, _state, ae_true);
ae_vector_init(&c11, 0, DT_COMPLEX, _state, ae_true);
ae_vector_init(&c12, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&b21, 0, 0, DT_BOOL, _state, ae_true);
ae_matrix_init(&b22, 0, 0, DT_BOOL, _state, ae_true);
ae_matrix_init(&i21, 0, 0, DT_INT, _state, ae_true);
ae_matrix_init(&i22, 0, 0, DT_INT, _state, ae_true);
ae_matrix_init(&r21, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&r22, 0, 0, DT_REAL, _state, ae_true);
ae_matrix_init(&c21, 0, 0, DT_COMPLEX, _state, ae_true);
ae_matrix_init(&c22, 0, 0, DT_COMPLEX, _state, ae_true);
result = ae_true;
okb1 = ae_true;
okb2 = ae_true;
oki1 = ae_true;
oki2 = ae_true;
okr1 = ae_true;
okr2 = ae_true;
okc1 = ae_true;
okc2 = ae_true;
/*
* Test B1 swaps
*/
ae_vector_set_length(&b11, 1, _state);
ae_vector_set_length(&b12, 2, _state);
b11.ptr.p_bool[0] = ae_true;
b12.ptr.p_bool[0] = ae_false;
b12.ptr.p_bool[1] = ae_true;
ae_swap_vectors(&b11, &b12);
if( b11.cnt==2&&b12.cnt==1 )
{
okb1 = okb1&&!b11.ptr.p_bool[0];
okb1 = okb1&&b11.ptr.p_bool[1];
okb1 = okb1&&b12.ptr.p_bool[0];
}
else
{
okb1 = ae_false;
}
/*
* Test I1 swaps
*/
ae_vector_set_length(&i11, 1, _state);
ae_vector_set_length(&i12, 2, _state);
i11.ptr.p_int[0] = 1;
i12.ptr.p_int[0] = 2;
i12.ptr.p_int[1] = 3;
ae_swap_vectors(&i11, &i12);
if( i11.cnt==2&&i12.cnt==1 )
{
oki1 = oki1&&i11.ptr.p_int[0]==2;
oki1 = oki1&&i11.ptr.p_int[1]==3;
oki1 = oki1&&i12.ptr.p_int[0]==1;
}
else
{
oki1 = ae_false;
}
/*
* Test R1 swaps
*/
ae_vector_set_length(&r11, 1, _state);
ae_vector_set_length(&r12, 2, _state);
r11.ptr.p_double[0] = 1.5;
r12.ptr.p_double[0] = 2.5;
r12.ptr.p_double[1] = 3.5;
ae_swap_vectors(&r11, &r12);
if( r11.cnt==2&&r12.cnt==1 )
{
okr1 = okr1&&ae_fp_eq(r11.ptr.p_double[0],2.5);
okr1 = okr1&&ae_fp_eq(r11.ptr.p_double[1],3.5);
okr1 = okr1&&ae_fp_eq(r12.ptr.p_double[0],1.5);
}
else
{
okr1 = ae_false;
}
/*
* Test C1 swaps
*/
ae_vector_set_length(&c11, 1, _state);
ae_vector_set_length(&c12, 2, _state);
c11.ptr.p_complex[0] = ae_complex_from_i(1);
c12.ptr.p_complex[0] = ae_complex_from_i(2);
c12.ptr.p_complex[1] = ae_complex_from_i(3);
ae_swap_vectors(&c11, &c12);
if( c11.cnt==2&&c12.cnt==1 )
{
okc1 = okc1&&ae_c_eq_d(c11.ptr.p_complex[0],(double)(2));
okc1 = okc1&&ae_c_eq_d(c11.ptr.p_complex[1],(double)(3));
okc1 = okc1&&ae_c_eq_d(c12.ptr.p_complex[0],(double)(1));
}
else
{
okc1 = ae_false;
}
/*
* Test B2 swaps
*/
ae_matrix_set_length(&b21, 1, 2, _state);
ae_matrix_set_length(&b22, 2, 1, _state);
b21.ptr.pp_bool[0][0] = ae_true;
b21.ptr.pp_bool[0][1] = ae_false;
b22.ptr.pp_bool[0][0] = ae_false;
b22.ptr.pp_bool[1][0] = ae_true;
ae_swap_matrices(&b21, &b22);
if( ((b21.rows==2&&b21.cols==1)&&b22.rows==1)&&b22.cols==2 )
{
okb2 = okb2&&!b21.ptr.pp_bool[0][0];
okb2 = okb2&&b21.ptr.pp_bool[1][0];
okb2 = okb2&&b22.ptr.pp_bool[0][0];
okb2 = okb2&&!b22.ptr.pp_bool[0][1];
}
else
{
okb2 = ae_false;
}
/*
* Test I2 swaps
*/
ae_matrix_set_length(&i21, 1, 2, _state);
ae_matrix_set_length(&i22, 2, 1, _state);
i21.ptr.pp_int[0][0] = 1;
i21.ptr.pp_int[0][1] = 2;
i22.ptr.pp_int[0][0] = 3;
i22.ptr.pp_int[1][0] = 4;
ae_swap_matrices(&i21, &i22);
if( ((i21.rows==2&&i21.cols==1)&&i22.rows==1)&&i22.cols==2 )
{
oki2 = oki2&&i21.ptr.pp_int[0][0]==3;
oki2 = oki2&&i21.ptr.pp_int[1][0]==4;
oki2 = oki2&&i22.ptr.pp_int[0][0]==1;
oki2 = oki2&&i22.ptr.pp_int[0][1]==2;
}
else
{
oki2 = ae_false;
}
/*
* Test R2 swaps
*/
ae_matrix_set_length(&r21, 1, 2, _state);
ae_matrix_set_length(&r22, 2, 1, _state);
r21.ptr.pp_double[0][0] = (double)(1);
r21.ptr.pp_double[0][1] = (double)(2);
r22.ptr.pp_double[0][0] = (double)(3);
r22.ptr.pp_double[1][0] = (double)(4);
ae_swap_matrices(&r21, &r22);
if( ((r21.rows==2&&r21.cols==1)&&r22.rows==1)&&r22.cols==2 )
{
okr2 = okr2&&ae_fp_eq(r21.ptr.pp_double[0][0],(double)(3));
okr2 = okr2&&ae_fp_eq(r21.ptr.pp_double[1][0],(double)(4));
okr2 = okr2&&ae_fp_eq(r22.ptr.pp_double[0][0],(double)(1));
okr2 = okr2&&ae_fp_eq(r22.ptr.pp_double[0][1],(double)(2));
}
else
{
okr2 = ae_false;
}
/*
* Test C2 swaps
*/
ae_matrix_set_length(&c21, 1, 2, _state);
ae_matrix_set_length(&c22, 2, 1, _state);
c21.ptr.pp_complex[0][0] = ae_complex_from_i(1);
c21.ptr.pp_complex[0][1] = ae_complex_from_i(2);
c22.ptr.pp_complex[0][0] = ae_complex_from_i(3);
c22.ptr.pp_complex[1][0] = ae_complex_from_i(4);
ae_swap_matrices(&c21, &c22);
if( ((c21.rows==2&&c21.cols==1)&&c22.rows==1)&&c22.cols==2 )
{
okc2 = okc2&&ae_c_eq_d(c21.ptr.pp_complex[0][0],(double)(3));
okc2 = okc2&&ae_c_eq_d(c21.ptr.pp_complex[1][0],(double)(4));
okc2 = okc2&&ae_c_eq_d(c22.ptr.pp_complex[0][0],(double)(1));
okc2 = okc2&&ae_c_eq_d(c22.ptr.pp_complex[0][1],(double)(2));
}
else
{
okc2 = ae_false;
}
/*
* summary
*/
result = result&&okb1;
result = result&&okb2;
result = result&&oki1;
result = result&&oki2;
result = result&&okr1;
result = result&&okr2;
result = result&&okc1;
result = result&&okc2;
if( !silent )
{
if( result )
{
printf("SWAPPING FUNCTIONS: OK\n");
}
else
{
printf("SWAPPING FUNCTIONS: FAILED\n");
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Tests for standard functions
*************************************************************************/
static ae_bool testalglibbasicsunit_teststandardfunctions(ae_bool silent,
ae_state *_state)
{
ae_bool result;
result = ae_true;
/*
* Test Sign()
*/
result = result&&ae_sign(1.2, _state)==1;
result = result&&ae_sign((double)(0), _state)==0;
result = result&&ae_sign(-1.2, _state)==-1;
/*
* summary
*/
if( !silent )
{
if( result )
{
printf("STANDARD FUNCTIONS: OK\n");
}
else
{
printf("STANDARD FUNCTIONS: FAILED\n");
}
}
return result;
}
/*************************************************************************
Tests for serualization functions
*************************************************************************/
static ae_bool testalglibbasicsunit_testserializationfunctions(ae_bool silent,
ae_state *_state)
{
ae_frame _frame_block;
ae_bool okb;
ae_bool oki;
ae_bool okr;
ae_int_t nb;
ae_int_t ni;
ae_int_t nr;
ae_int_t i;
rec4serialization r0;
rec4serialization r1;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&r0, 0, sizeof(r0));
memset(&r1, 0, sizeof(r1));
_rec4serialization_init(&r0, _state, ae_true);
_rec4serialization_init(&r1, _state, ae_true);
result = ae_true;
okb = ae_true;
oki = ae_true;
okr = ae_true;
for(nb=1; nb<=4; nb++)
{
for(ni=1; ni<=4; ni++)
{
for(nr=1; nr<=4; nr++)
{
ae_vector_set_length(&r0.b, nb, _state);
for(i=0; i<=nb-1; i++)
{
r0.b.ptr.p_bool[i] = ae_randominteger(2, _state)!=0;
}
ae_vector_set_length(&r0.i, ni, _state);
for(i=0; i<=ni-1; i++)
{
r0.i.ptr.p_int[i] = ae_randominteger(10, _state)-5;
}
ae_vector_set_length(&r0.r, nr, _state);
for(i=0; i<=nr-1; i++)
{
r0.r.ptr.p_double[i] = 2*ae_randomreal(_state)-1;
}
{
/*
* This code passes data structure through serializers
* (serializes it to string and loads back)
*/
ae_serializer _local_serializer;
ae_int_t _local_ssize;
ae_frame _local_frame_block;
ae_dyn_block _local_dynamic_block;
ae_frame_make(_state, &_local_frame_block);
ae_serializer_init(&_local_serializer);
ae_serializer_alloc_start(&_local_serializer);
rec4serializationalloc(&_local_serializer, &r0, _state);
_local_ssize = ae_serializer_get_alloc_size(&_local_serializer);
memset(&_local_dynamic_block, 0, sizeof(_local_dynamic_block));
ae_db_init(&_local_dynamic_block, _local_ssize+1, _state, ae_true);
ae_serializer_sstart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
rec4serializationserialize(&_local_serializer, &r0, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_serializer_init(&_local_serializer);
ae_serializer_ustart_str(&_local_serializer, (char*)_local_dynamic_block.ptr);
rec4serializationunserialize(&_local_serializer, &r1, _state);
ae_serializer_stop(&_local_serializer, _state);
ae_serializer_clear(&_local_serializer);
ae_frame_leave(_state);
}
if( (r0.b.cnt==r1.b.cnt&&r0.i.cnt==r1.i.cnt)&&r0.r.cnt==r1.r.cnt )
{
for(i=0; i<=nb-1; i++)
{
okb = okb&&((r0.b.ptr.p_bool[i]&&r1.b.ptr.p_bool[i])||(!r0.b.ptr.p_bool[i]&&!r1.b.ptr.p_bool[i]));
}
for(i=0; i<=ni-1; i++)
{
oki = oki&&r0.i.ptr.p_int[i]==r1.i.ptr.p_int[i];
}
for(i=0; i<=nr-1; i++)
{
okr = okr&&ae_fp_eq(r0.r.ptr.p_double[i],r1.r.ptr.p_double[i]);
}
}
else
{
oki = ae_false;
}
}
}
}
/*
* summary
*/
result = result&&okb;
result = result&&oki;
result = result&&okr;
if( !silent )
{
if( result )
{
printf("SERIALIZATION FUNCTIONS: OK\n");
}
else
{
printf("SERIALIZATION FUNCTIONS: FAILED\n");
printf("* BOOLEAN - - - - - - - - - - - - - - - ");
if( okb )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* INTEGER - - - - - - - - - - - - - - - ");
if( oki )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* REAL - - - - - - - - - - - - - - - - ");
if( okr )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
}
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Tests for pool functions
*************************************************************************/
static void testalglibbasicsunit_createpoolandrecords(poolrec2* seedrec2,
poolrec2* seedrec2copy,
ae_shared_pool* pool,
ae_state *_state)
{
_poolrec2_clear(seedrec2);
_poolrec2_clear(seedrec2copy);
ae_shared_pool_clear(pool);
seedrec2->bval = ae_fp_greater(ae_randomreal(_state),0.5);
seedrec2->recval.bval = ae_fp_greater(ae_randomreal(_state),0.5);
seedrec2->recval.ival = ae_randominteger(10, _state);
seedrec2->recval.rval = ae_randomreal(_state);
seedrec2->recval.cval.x = ae_randomreal(_state);
seedrec2->recval.cval.y = ae_randomreal(_state);
ae_vector_set_length(&seedrec2->recval.i1val, 3, _state);
seedrec2->recval.i1val.ptr.p_int[0] = ae_randominteger(10, _state);
seedrec2->recval.i1val.ptr.p_int[1] = ae_randominteger(10, _state);
seedrec2->recval.i1val.ptr.p_int[2] = ae_randominteger(10, _state);
seedrec2copy->bval = seedrec2->bval;
seedrec2copy->recval.bval = seedrec2->recval.bval;
seedrec2copy->recval.ival = seedrec2->recval.ival;
seedrec2copy->recval.rval = seedrec2->recval.rval;
seedrec2copy->recval.cval = seedrec2->recval.cval;
ae_vector_set_length(&seedrec2copy->recval.i1val, 3, _state);
seedrec2copy->recval.i1val.ptr.p_int[0] = seedrec2->recval.i1val.ptr.p_int[0];
seedrec2copy->recval.i1val.ptr.p_int[1] = seedrec2->recval.i1val.ptr.p_int[1];
seedrec2copy->recval.i1val.ptr.p_int[2] = seedrec2->recval.i1val.ptr.p_int[2];
ae_shared_pool_set_seed(pool, seedrec2, sizeof(*seedrec2), _poolrec2_init, _poolrec2_init_copy, _poolrec2_destroy, _state);
}
static ae_bool testalglibbasicsunit_sharedpoolerrors(ae_state *_state)
{
ae_frame _frame_block;
poolrec1 seedrec1;
poolrec2 seedrec2;
poolrec2 seedrec2copy;
ae_shared_pool pool;
ae_shared_pool pool2;
poolrec2 *prec2;
ae_smart_ptr _prec2;
poolrec2 *p0;
ae_smart_ptr _p0;
poolrec2 *p1;
ae_smart_ptr _p1;
poolrec2 *p2;
ae_smart_ptr _p2;
poolrec1 *q0;
ae_smart_ptr _q0;
poolrec1 *q1;
ae_smart_ptr _q1;
ae_shared_pool *ppool0;
ae_smart_ptr _ppool0;
ae_shared_pool *ppool1;
ae_smart_ptr _ppool1;
ae_int_t val100cnt;
ae_int_t val101cnt;
ae_int_t val102cnt;
ae_int_t tmpval;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&seedrec1, 0, sizeof(seedrec1));
memset(&seedrec2, 0, sizeof(seedrec2));
memset(&seedrec2copy, 0, sizeof(seedrec2copy));
memset(&pool, 0, sizeof(pool));
memset(&pool2, 0, sizeof(pool2));
memset(&_prec2, 0, sizeof(_prec2));
memset(&_p0, 0, sizeof(_p0));
memset(&_p1, 0, sizeof(_p1));
memset(&_p2, 0, sizeof(_p2));
memset(&_q0, 0, sizeof(_q0));
memset(&_q1, 0, sizeof(_q1));
memset(&_ppool0, 0, sizeof(_ppool0));
memset(&_ppool1, 0, sizeof(_ppool1));
_poolrec1_init(&seedrec1, _state, ae_true);
_poolrec2_init(&seedrec2, _state, ae_true);
_poolrec2_init(&seedrec2copy, _state, ae_true);
ae_shared_pool_init(&pool, _state, ae_true);
ae_shared_pool_init(&pool2, _state, ae_true);
ae_smart_ptr_init(&_prec2, (void**)&prec2, _state, ae_true);
ae_smart_ptr_init(&_p0, (void**)&p0, _state, ae_true);
ae_smart_ptr_init(&_p1, (void**)&p1, _state, ae_true);
ae_smart_ptr_init(&_p2, (void**)&p2, _state, ae_true);
ae_smart_ptr_init(&_q0, (void**)&q0, _state, ae_true);
ae_smart_ptr_init(&_q1, (void**)&q1, _state, ae_true);
ae_smart_ptr_init(&_ppool0, (void**)&ppool0, _state, ae_true);
ae_smart_ptr_init(&_ppool1, (void**)&ppool1, _state, ae_true);
result = ae_true;
/*
* Test 1: test that:
* a) smart pointer is null by default
* b) "conventional local" is valid by default
* b) unitinitialized shared pool is "not initialized"
*/
if( prec2!=NULL )
{
ae_frame_leave(_state);
return result;
}
if( !(&seedrec1!=NULL) )
{
ae_frame_leave(_state);
return result;
}
if( ae_shared_pool_is_initialized(&pool) )
{
ae_frame_leave(_state);
return result;
}
/*
* Test 2: basic copying of complex structures
* * check that pool is recognized as "initialized"
* * change original seed record,
* * retrieve value from pool,
* * check that it is valid
* * and it is unchanged.
*/
testalglibbasicsunit_createpoolandrecords(&seedrec2, &seedrec2copy, &pool, _state);
if( !ae_shared_pool_is_initialized(&pool) )
{
ae_frame_leave(_state);
return result;
}
seedrec2.bval = !seedrec2.bval;
seedrec2.recval.i1val.ptr.p_int[0] = seedrec2.recval.i1val.ptr.p_int[0]+1;
ae_shared_pool_retrieve(&pool, &_prec2, _state);
if( !(prec2!=NULL) )
{
ae_frame_leave(_state);
return result;
}
if( (seedrec2copy.bval&&!prec2->bval)||(prec2->bval&&!seedrec2copy.bval) )
{
ae_frame_leave(_state);
return result;
}
if( seedrec2copy.recval.i1val.ptr.p_int[0]!=prec2->recval.i1val.ptr.p_int[0] )
{
ae_frame_leave(_state);
return result;
}
/*
* Test 3: unrecycled values are lost
* * retrieve value from pool,
* * change it,
* * retrieve one more time,
* * check that it is unchanged.
*/
testalglibbasicsunit_createpoolandrecords(&seedrec2, &seedrec2copy, &pool, _state);
ae_shared_pool_retrieve(&pool, &_prec2, _state);
prec2->recval.ival = prec2->recval.ival+1;
ae_shared_pool_retrieve(&pool, &_prec2, _state);
if( prec2->recval.ival!=seedrec2copy.recval.ival )
{
ae_frame_leave(_state);
return result;
}
/*
* Test 4: recycled values are reused, PoolClearRecycled() removes recycled values
* * retrieve value from pool,
* * change it,
* * recycle,
* * check that recycled pointer is null
* * retrieve one more time,
* * check that modified value was returned,
* * recycle,
* * clear pool,
* * retrieve one more time,
* * check that unmodified value was returned,
*/
testalglibbasicsunit_createpoolandrecords(&seedrec2, &seedrec2copy, &pool, _state);
ae_shared_pool_retrieve(&pool, &_prec2, _state);
prec2->recval.ival = prec2->recval.ival+1;
ae_shared_pool_recycle(&pool, &_prec2, _state);
if( prec2!=NULL )
{
ae_frame_leave(_state);
return result;
}
ae_shared_pool_retrieve(&pool, &_prec2, _state);
if( !(prec2!=NULL) )
{
ae_frame_leave(_state);
return result;
}
if( prec2->recval.ival!=seedrec2copy.recval.ival+1 )
{
ae_frame_leave(_state);
return result;
}
ae_shared_pool_recycle(&pool, &_prec2, _state);
ae_shared_pool_clear_recycled(&pool, _state);
ae_shared_pool_retrieve(&pool, &_prec2, _state);
if( !(prec2!=NULL) )
{
ae_frame_leave(_state);
return result;
}
if( prec2->recval.ival!=seedrec2copy.recval.ival )
{
ae_frame_leave(_state);
return result;
}
/*
* Test 5: basic enumeration
* * retrieve 3 values from pool
* * fill RecVal.iVal by 100, 101, 102
* * recycle values
* * enumerate, check that each iVal occurs only once during enumeration
* * repeat enumeration to make sure that it can be repeated
*/
testalglibbasicsunit_createpoolandrecords(&seedrec2, &seedrec2copy, &pool, _state);
ae_shared_pool_retrieve(&pool, &_p0, _state);
ae_shared_pool_retrieve(&pool, &_p1, _state);
ae_shared_pool_retrieve(&pool, &_p2, _state);
p0->recval.ival = 100;
p1->recval.ival = 101;
p2->recval.ival = 102;
ae_shared_pool_recycle(&pool, &_p1, _state);
ae_shared_pool_recycle(&pool, &_p2, _state);
ae_shared_pool_recycle(&pool, &_p0, _state);
val100cnt = 0;
val101cnt = 0;
val102cnt = 0;
ae_shared_pool_first_recycled(&pool, &_prec2, _state);
while(prec2!=NULL)
{
if( prec2->recval.ival==100 )
{
val100cnt = val100cnt+1;
}
if( prec2->recval.ival==101 )
{
val101cnt = val101cnt+1;
}
if( prec2->recval.ival==102 )
{
val102cnt = val102cnt+1;
}
ae_shared_pool_next_recycled(&pool, &_prec2, _state);
}
if( (val100cnt!=1||val101cnt!=1)||val102cnt!=1 )
{
ae_frame_leave(_state);
return result;
}
val100cnt = 0;
val101cnt = 0;
val102cnt = 0;
ae_shared_pool_first_recycled(&pool, &_prec2, _state);
while(prec2!=NULL)
{
if( prec2->recval.ival==100 )
{
val100cnt = val100cnt+1;
}
if( prec2->recval.ival==101 )
{
val101cnt = val101cnt+1;
}
if( prec2->recval.ival==102 )
{
val102cnt = val102cnt+1;
}
ae_shared_pool_next_recycled(&pool, &_prec2, _state);
}
if( (val100cnt!=1||val101cnt!=1)||val102cnt!=1 )
{
ae_frame_leave(_state);
return result;
}
/*
* Test 6: pool itself can be pooled
* * pool can be seeded with another pool
* * smart pointers to pool are correctly handled
* * pool correctly returns different references on "retrieve":
* * we retrieve, modify and recycle back to PPool0
* * we retrieve from PPool1 - unmodified value is returned
* * we retrievefrom PPool0 - modified value is returned
*/
testalglibbasicsunit_createpoolandrecords(&seedrec2, &seedrec2copy, &pool, _state);
ae_shared_pool_set_seed(&pool2, &pool, sizeof(pool), ae_shared_pool_init, ae_shared_pool_init_copy, ae_shared_pool_destroy, _state);
if( ppool0!=NULL||ppool1!=NULL )
{
ae_frame_leave(_state);
return result;
}
ae_shared_pool_retrieve(&pool2, &_ppool0, _state);
ae_shared_pool_retrieve(&pool2, &_ppool1, _state);
if( !(ppool0!=NULL&&ppool1!=NULL) )
{
ae_frame_leave(_state);
return result;
}
ae_shared_pool_retrieve(ppool0, &_p0, _state);
p0->recval.ival = p0->recval.ival+1;
tmpval = p0->recval.ival;
ae_shared_pool_recycle(ppool0, &_p0, _state);
ae_shared_pool_retrieve(ppool1, &_p1, _state);
if( p1->recval.ival==tmpval )
{
ae_frame_leave(_state);
return result;
}
ae_shared_pool_recycle(ppool1, &_p1, _state);
ae_shared_pool_retrieve(ppool0, &_p0, _state);
if( p0->recval.ival!=tmpval )
{
ae_frame_leave(_state);
return result;
}
/*
* Test 7: pools which are fields of records are correctly handled
* * pool can be seeded with record which has initialized pool as its field
* * when record is retrieved from pool, its fields are correctly copied (including
* fields which are pools)
*/
testalglibbasicsunit_createpoolandrecords(&seedrec2, &seedrec2copy, &pool, _state);
tmpval = 99;
seedrec1.ival = tmpval;
ae_shared_pool_set_seed(&seedrec2.pool, &seedrec1, sizeof(seedrec1), _poolrec1_init, _poolrec1_init_copy, _poolrec1_destroy, _state);
ae_shared_pool_set_seed(&pool, &seedrec2, sizeof(seedrec2), _poolrec2_init, _poolrec2_init_copy, _poolrec2_destroy, _state);
ae_shared_pool_retrieve(&pool, &_p0, _state);
ae_shared_pool_retrieve(&p0->pool, &_q0, _state);
q0->ival = tmpval-1;
ae_shared_pool_recycle(&p0->pool, &_q0, _state);
ae_shared_pool_retrieve(&pool, &_p1, _state);
ae_shared_pool_retrieve(&p1->pool, &_q1, _state);
if( q1->ival!=tmpval )
{
ae_frame_leave(_state);
return result;
}
ae_shared_pool_recycle(&p1->pool, &_q1, _state);
ae_shared_pool_retrieve(&p0->pool, &_q0, _state);
if( q0->ival!=tmpval-1 )
{
ae_frame_leave(_state);
return result;
}
/*
* Test 8: after call to PoolReset(), call to PoolFirstRecycled() returns null references
*/
testalglibbasicsunit_createpoolandrecords(&seedrec2, &seedrec2copy, &pool, _state);
ae_shared_pool_retrieve(&pool, &_p0, _state);
ae_shared_pool_retrieve(&pool, &_p1, _state);
ae_shared_pool_retrieve(&pool, &_p2, _state);
ae_shared_pool_recycle(&pool, &_p1, _state);
ae_shared_pool_recycle(&pool, &_p2, _state);
ae_shared_pool_recycle(&pool, &_p0, _state);
ae_shared_pool_first_recycled(&pool, &_p0, _state);
if( !(p0!=NULL) )
{
ae_frame_leave(_state);
return result;
}
ae_shared_pool_next_recycled(&pool, &_p0, _state);
if( !(p0!=NULL) )
{
ae_frame_leave(_state);
return result;
}
ae_shared_pool_next_recycled(&pool, &_p0, _state);
if( !(p0!=NULL) )
{
ae_frame_leave(_state);
return result;
}
ae_shared_pool_next_recycled(&pool, &_p0, _state);
if( p0!=NULL )
{
ae_frame_leave(_state);
return result;
}
ae_shared_pool_reset(&pool, _state);
ae_shared_pool_first_recycled(&pool, &_p0, _state);
if( p0!=NULL )
{
ae_frame_leave(_state);
return result;
}
ae_shared_pool_next_recycled(&pool, &_p0, _state);
if( p0!=NULL )
{
ae_frame_leave(_state);
return result;
}
ae_shared_pool_next_recycled(&pool, &_p0, _state);
if( p0!=NULL )
{
ae_frame_leave(_state);
return result;
}
ae_shared_pool_next_recycled(&pool, &_p0, _state);
if( p0!=NULL )
{
ae_frame_leave(_state);
return result;
}
/*
* Test 9: invalid pointer is recognized as non-null (we do not reference it, just test)
*/
testalglibbasicsunit_createpoolandrecords(&seedrec2, &seedrec2copy, &pool, _state);
ae_shared_pool_retrieve(&pool, &_p0, _state);
ae_shared_pool_retrieve(&pool, &_p1, _state);
ae_shared_pool_retrieve(&pool, &_p2, _state);
ae_shared_pool_recycle(&pool, &_p1, _state);
ae_shared_pool_recycle(&pool, &_p2, _state);
ae_shared_pool_recycle(&pool, &_p0, _state);
ae_shared_pool_first_recycled(&pool, &_p0, _state);
if( !(p0!=NULL) )
{
ae_frame_leave(_state);
return result;
}
ae_shared_pool_clear_recycled(&pool, _state);
if( !(p0!=NULL) )
{
ae_frame_leave(_state);
return result;
}
/*
* Test 9: non-null pointer is nulled by calling SetNull()
*/
testalglibbasicsunit_createpoolandrecords(&seedrec2, &seedrec2copy, &pool, _state);
ae_shared_pool_retrieve(&pool, &_p0, _state);
if( !(p0!=NULL) )
{
ae_frame_leave(_state);
return result;
}
ae_smart_ptr_assign(&_p0, NULL, ae_false, ae_false, NULL);
if( p0!=NULL )
{
ae_frame_leave(_state);
return result;
}
result = ae_false;
ae_frame_leave(_state);
return result;
}
static ae_bool testalglibbasicsunit_testsharedpool(ae_bool silent,
ae_state *_state)
{
ae_bool result;
result = !testalglibbasicsunit_sharedpoolerrors(_state);
if( !silent )
{
if( result )
{
printf("SHARED POOL: OK\n");
}
else
{
printf("SHARED POOL: FAILED\n");
}
}
return result;
}
/*************************************************************************
Tests for SMP functions
testSort0: sort function
*************************************************************************/
static void testalglibbasicsunit_testsort0func(/* Integer */ ae_vector* a,
/* Integer */ ae_vector* buf,
ae_int_t idx0,
ae_int_t idx2,
ae_state *_state)
{
ae_int_t idx1;
if( idx2<=idx0+1 )
{
return;
}
idx1 = (idx0+idx2)/2;
testalglibbasicsunit_testsort0func(a, buf, idx0, idx1, _state);
testalglibbasicsunit_testsort0func(a, buf, idx1, idx2, _state);
testalglibbasicsunit_mergesortedarrays(a, buf, idx0, idx1, idx2, _state);
}
/*************************************************************************
Serial stub for GPL edition.
*************************************************************************/
ae_bool _trypexec_testalglibbasicsunit_testsort0func(/* Integer */ ae_vector* a,
/* Integer */ ae_vector* buf,
ae_int_t idx0,
ae_int_t idx2,
ae_state *_state)
{
return ae_false;
}
/*************************************************************************
testSort0: recursive sorting by splitting array into two subarrays.
Returns True on success, False on failure.
*************************************************************************/
static ae_bool testalglibbasicsunit_performtestsort0(ae_state *_state)
{
ae_frame _frame_block;
ae_vector a;
ae_vector buf;
ae_int_t i;
ae_int_t k;
ae_int_t t;
ae_int_t n;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&buf, 0, sizeof(buf));
ae_vector_init(&a, 0, DT_INT, _state, ae_true);
ae_vector_init(&buf, 0, DT_INT, _state, ae_true);
n = 100000;
ae_vector_set_length(&a, n, _state);
ae_vector_set_length(&buf, n, _state);
for(i=0; i<=n-1; i++)
{
a.ptr.p_int[i] = i;
}
for(i=0; i<=n-1; i++)
{
k = ae_randominteger(n, _state);
if( k!=i )
{
t = a.ptr.p_int[i];
a.ptr.p_int[i] = a.ptr.p_int[k];
a.ptr.p_int[k] = t;
}
}
testalglibbasicsunit_testsort0func(&a, &buf, 0, n, _state);
result = ae_true;
for(i=0; i<=n-1; i++)
{
result = result&&a.ptr.p_int[i]==i;
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
TestSort0: sort function
*************************************************************************/
static void testalglibbasicsunit_testsort1func(/* Integer */ ae_vector* a,
/* Integer */ ae_vector* buf,
ae_int_t idx0,
ae_int_t idx2,
ae_bool usesmp,
ae_state *_state)
{
ae_int_t idxa;
ae_int_t idxb;
ae_int_t idxc;
ae_int_t cnt4;
if( idx2<=idx0+1 )
{
return;
}
if( idx2==idx0+2 )
{
testalglibbasicsunit_mergesortedarrays(a, buf, idx0, idx0+1, idx0+2, _state);
return;
}
if( idx2==idx0+3 )
{
testalglibbasicsunit_mergesortedarrays(a, buf, idx0+0, idx0+1, idx0+2, _state);
testalglibbasicsunit_mergesortedarrays(a, buf, idx0+0, idx0+2, idx0+3, _state);
return;
}
if( idx2==idx0+4 )
{
testalglibbasicsunit_mergesortedarrays(a, buf, idx0+0, idx0+1, idx0+2, _state);
testalglibbasicsunit_mergesortedarrays(a, buf, idx0+2, idx0+3, idx0+4, _state);
testalglibbasicsunit_mergesortedarrays(a, buf, idx0+0, idx0+2, idx0+4, _state);
return;
}
cnt4 = (idx2-idx0)/4;
idxa = idx0+cnt4;
idxb = idx0+2*cnt4;
idxc = idx0+3*cnt4;
testalglibbasicsunit_testsort1func(a, buf, idx0, idxa, usesmp, _state);
testalglibbasicsunit_testsort1func(a, buf, idxa, idxb, usesmp, _state);
testalglibbasicsunit_testsort1func(a, buf, idxb, idxc, usesmp, _state);
testalglibbasicsunit_testsort1func(a, buf, idxc, idx2, usesmp, _state);
testalglibbasicsunit_mergesortedarrays(a, buf, idx0, idxa, idxb, _state);
testalglibbasicsunit_mergesortedarrays(a, buf, idxb, idxc, idx2, _state);
testalglibbasicsunit_mergesortedarrays(a, buf, idx0, idxb, idx2, _state);
}
/*************************************************************************
Serial stub for GPL edition.
*************************************************************************/
ae_bool _trypexec_testalglibbasicsunit_testsort1func(/* Integer */ ae_vector* a,
/* Integer */ ae_vector* buf,
ae_int_t idx0,
ae_int_t idx2,
ae_bool usesmp,
ae_state *_state)
{
return ae_false;
}
/*************************************************************************
TestSort0: recursive sorting by splitting array into 4 subarrays.
Sorting is performed in three rounds:
* parallel sorting of randomly permuted array
* result is randomly shuffled and sequentially sorted
* result is randomly shuffled (again) and sorted in parallel mode (again)
The idea of such "multitry sort" is that we test ability of SMP core to
interleave highly parallel parts of code with long sequential parts.
Returns True on success, False on failure.
*************************************************************************/
static ae_bool testalglibbasicsunit_performtestsort1(ae_state *_state)
{
ae_frame _frame_block;
ae_vector a;
ae_vector buf;
ae_int_t i;
ae_int_t k;
ae_int_t t;
ae_int_t n;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&buf, 0, sizeof(buf));
ae_vector_init(&a, 0, DT_INT, _state, ae_true);
ae_vector_init(&buf, 0, DT_INT, _state, ae_true);
/*
* Generate array
*/
n = 100000;
ae_vector_set_length(&a, n, _state);
ae_vector_set_length(&buf, n, _state);
for(i=0; i<=n-1; i++)
{
a.ptr.p_int[i] = i;
}
/*
* round 0: parallel sorting of randomly permuted array
*/
for(i=0; i<=n-1; i++)
{
k = ae_randominteger(n, _state);
if( k!=i )
{
t = a.ptr.p_int[i];
a.ptr.p_int[i] = a.ptr.p_int[k];
a.ptr.p_int[k] = t;
}
}
testalglibbasicsunit_testsort1func(&a, &buf, 0, n, ae_true, _state);
/*
* round 1: result is randomly shuffled and sequentially sorted
*/
for(i=0; i<=n-1; i++)
{
k = ae_randominteger(n, _state);
if( k!=i )
{
t = a.ptr.p_int[i];
a.ptr.p_int[i] = a.ptr.p_int[k];
a.ptr.p_int[k] = t;
}
}
testalglibbasicsunit_testsort1func(&a, &buf, 0, n, ae_false, _state);
/*
* round 2: result is randomly shuffled (again) and sorted in parallel mode (again)
*/
for(i=0; i<=n-1; i++)
{
k = ae_randominteger(n, _state);
if( k!=i )
{
t = a.ptr.p_int[i];
a.ptr.p_int[i] = a.ptr.p_int[k];
a.ptr.p_int[k] = t;
}
}
testalglibbasicsunit_testsort1func(&a, &buf, 0, n, ae_true, _state);
/*
* Test
*/
result = ae_true;
for(i=0; i<=n-1; i++)
{
result = result&&a.ptr.p_int[i]==i;
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Tests for SMP functions
testSort2: sort function
*************************************************************************/
static void testalglibbasicsunit_testsort2func(/* Integer */ ae_vector* a,
/* Integer */ ae_vector* buf,
ae_int_t idx0,
ae_int_t idx2,
ae_state *_state)
{
ae_int_t idx1;
if( idx2<=idx0+1 )
{
return;
}
idx1 = idx0+1+ae_randominteger(idx2-idx0-1, _state);
testalglibbasicsunit_testsort0func(a, buf, idx0, idx1, _state);
testalglibbasicsunit_testsort0func(a, buf, idx1, idx2, _state);
testalglibbasicsunit_mergesortedarrays(a, buf, idx0, idx1, idx2, _state);
}
/*************************************************************************
Serial stub for GPL edition.
*************************************************************************/
ae_bool _trypexec_testalglibbasicsunit_testsort2func(/* Integer */ ae_vector* a,
/* Integer */ ae_vector* buf,
ae_int_t idx0,
ae_int_t idx2,
ae_state *_state)
{
return ae_false;
}
/*************************************************************************
testSort2: recursive sorting by splitting array into two subarrays of
different length (main difference from testsort0).
Returns True on success, False on failure.
*************************************************************************/
static ae_bool testalglibbasicsunit_performtestsort2(ae_state *_state)
{
ae_frame _frame_block;
ae_vector a;
ae_vector buf;
ae_int_t i;
ae_int_t k;
ae_int_t t;
ae_int_t n;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&a, 0, sizeof(a));
memset(&buf, 0, sizeof(buf));
ae_vector_init(&a, 0, DT_INT, _state, ae_true);
ae_vector_init(&buf, 0, DT_INT, _state, ae_true);
n = 100000;
ae_vector_set_length(&a, n, _state);
ae_vector_set_length(&buf, n, _state);
for(i=0; i<=n-1; i++)
{
a.ptr.p_int[i] = i;
}
for(i=0; i<=n-1; i++)
{
k = ae_randominteger(n, _state);
if( k!=i )
{
t = a.ptr.p_int[i];
a.ptr.p_int[i] = a.ptr.p_int[k];
a.ptr.p_int[k] = t;
}
}
testalglibbasicsunit_testsort2func(&a, &buf, 0, n, _state);
result = ae_true;
for(i=0; i<=n-1; i++)
{
result = result&&a.ptr.p_int[i]==i;
}
ae_frame_leave(_state);
return result;
}
/*************************************************************************
TestPoolSum: summation with pool
We perform summation of 500000 numbers (each of them is equal to 1) in the
recurrent manner, by accumulation of result in the pool.
This test checks pool ability to handle continuous stream of operations.
Returns True on success, False on failure.
*************************************************************************/
static ae_bool testalglibbasicsunit_performtestpoolsum(ae_state *_state)
{
ae_frame _frame_block;
ae_shared_pool pool;
poolsummand *ptr;
ae_smart_ptr _ptr;
poolsummand seed;
ae_int_t n;
ae_int_t sum;
ae_bool result;
ae_frame_make(_state, &_frame_block);
memset(&pool, 0, sizeof(pool));
memset(&_ptr, 0, sizeof(_ptr));
memset(&seed, 0, sizeof(seed));
ae_shared_pool_init(&pool, _state, ae_true);
ae_smart_ptr_init(&_ptr, (void**)&ptr, _state, ae_true);
_poolsummand_init(&seed, _state, ae_true);
n = 500000;
seed.val = 0;
ae_shared_pool_set_seed(&pool, &seed, sizeof(seed), _poolsummand_init, _poolsummand_init_copy, _poolsummand_destroy, _state);
testalglibbasicsunit_parallelpoolsum(&pool, 0, n, _state);
sum = 0;
ae_shared_pool_first_recycled(&pool, &_ptr, _state);
while(ptr!=NULL)
{
sum = sum+ptr->val;
ae_shared_pool_next_recycled(&pool, &_ptr, _state);
}
result = sum==n;
ae_frame_leave(_state);
return result;
}
/*************************************************************************
Summation routune for parallel summation test.
*************************************************************************/
static void testalglibbasicsunit_parallelpoolsum(ae_shared_pool* sumpool,
ae_int_t ind0,
ae_int_t ind1,
ae_state *_state)
{
ae_frame _frame_block;
ae_int_t i;
poolsummand *ptr;
ae_smart_ptr _ptr;
ae_frame_make(_state, &_frame_block);
memset(&_ptr, 0, sizeof(_ptr));
ae_smart_ptr_init(&_ptr, (void**)&ptr, _state, ae_true);
if( ind1-ind0<=2 )
{
ae_shared_pool_retrieve(sumpool, &_ptr, _state);
ptr->val = ptr->val+ind1-ind0;
ae_shared_pool_recycle(sumpool, &_ptr, _state);
}
else
{
i = (ind0+ind1)/2;
testalglibbasicsunit_parallelpoolsum(sumpool, ind0, i, _state);
testalglibbasicsunit_parallelpoolsum(sumpool, i, ind1, _state);
}
ae_frame_leave(_state);
}
/*************************************************************************
Serial stub for GPL edition.
*************************************************************************/
ae_bool _trypexec_testalglibbasicsunit_parallelpoolsum(ae_shared_pool* sumpool,
ae_int_t ind0,
ae_int_t ind1,
ae_state *_state)
{
return ae_false;
}
/*************************************************************************
This function merges sorted A[Idx0,Idx1) and A[Idx1,Idx2) into sorted array
A[Idx0,Idx2) using corresponding elements of Buf.
*************************************************************************/
static void testalglibbasicsunit_mergesortedarrays(/* Integer */ ae_vector* a,
/* Integer */ ae_vector* buf,
ae_int_t idx0,
ae_int_t idx1,
ae_int_t idx2,
ae_state *_state)
{
ae_int_t srcleft;
ae_int_t srcright;
ae_int_t dst;
srcleft = idx0;
srcright = idx1;
dst = idx0;
for(;;)
{
if( srcleft==idx1&&srcright==idx2 )
{
break;
}
if( srcleft==idx1 )
{
buf->ptr.p_int[dst] = a->ptr.p_int[srcright];
srcright = srcright+1;
dst = dst+1;
continue;
}
if( srcright==idx2 )
{
buf->ptr.p_int[dst] = a->ptr.p_int[srcleft];
srcleft = srcleft+1;
dst = dst+1;
continue;
}
if( a->ptr.p_int[srcleft]ptr.p_int[srcright] )
{
buf->ptr.p_int[dst] = a->ptr.p_int[srcleft];
srcleft = srcleft+1;
dst = dst+1;
}
else
{
buf->ptr.p_int[dst] = a->ptr.p_int[srcright];
srcright = srcright+1;
dst = dst+1;
}
}
for(dst=idx0; dst<=idx2-1; dst++)
{
a->ptr.p_int[dst] = buf->ptr.p_int[dst];
}
}
/*************************************************************************
Serial stub for GPL edition.
*************************************************************************/
ae_bool _trypexec_testalglibbasicsunit_mergesortedarrays(/* Integer */ ae_vector* a,
/* Integer */ ae_vector* buf,
ae_int_t idx0,
ae_int_t idx1,
ae_int_t idx2,
ae_state *_state)
{
return ae_false;
}
static ae_bool testalglibbasicsunit_testsmp(ae_bool silent,
ae_state *_state)
{
ae_bool t0;
ae_bool t1;
ae_bool t2;
ae_bool ts;
ae_bool result;
t0 = testalglibbasicsunit_performtestsort0(_state);
t1 = testalglibbasicsunit_performtestsort1(_state);
t2 = testalglibbasicsunit_performtestsort2(_state);
ts = testalglibbasicsunit_performtestpoolsum(_state);
result = ((t0&&t1)&&t2)&&ts;
if( !silent )
{
if( result )
{
printf("SMP FUNCTIONS: OK\n");
}
else
{
printf("SMP FUNCTIONS: FAILED\n");
printf("* TEST SORT0 (sorting, split-2) ");
if( t0 )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* TEST SORT1 (sorting, split-4) ");
if( t1 )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* TEST SORT2 (sorting, split-2, unequal) ");
if( t2 )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
printf("* TEST POOLSUM (accumulation with pool) ");
if( ts )
{
printf("OK\n");
}
else
{
printf("FAILED\n");
}
}
}
return result;
}
void _rec1_init(void* _p, ae_state *_state, ae_bool make_automatic)
{
rec1 *p = (rec1*)_p;
ae_touch_ptr((void*)p);
ae_vector_init(&p->b1field, 0, DT_BOOL, _state, make_automatic);
ae_vector_init(&p->r1field, 0, DT_REAL, _state, make_automatic);
ae_vector_init(&p->i1field, 0, DT_INT, _state, make_automatic);
ae_vector_init(&p->c1field, 0, DT_COMPLEX, _state, make_automatic);
ae_matrix_init(&p->b2field, 0, 0, DT_BOOL, _state, make_automatic);
ae_matrix_init(&p->r2field, 0, 0, DT_REAL, _state, make_automatic);
ae_matrix_init(&p->i2field, 0, 0, DT_INT, _state, make_automatic);
ae_matrix_init(&p->c2field, 0, 0, DT_COMPLEX, _state, make_automatic);
}
void _rec1_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
{
rec1 *dst = (rec1*)_dst;
rec1 *src = (rec1*)_src;
dst->bfield = src->bfield;
dst->rfield = src->rfield;
dst->ifield = src->ifield;
dst->cfield = src->cfield;
ae_vector_init_copy(&dst->b1field, &src->b1field, _state, make_automatic);
ae_vector_init_copy(&dst->r1field, &src->r1field, _state, make_automatic);
ae_vector_init_copy(&dst->i1field, &src->i1field, _state, make_automatic);
ae_vector_init_copy(&dst->c1field, &src->c1field, _state, make_automatic);
ae_matrix_init_copy(&dst->b2field, &src->b2field, _state, make_automatic);
ae_matrix_init_copy(&dst->r2field, &src->r2field, _state, make_automatic);
ae_matrix_init_copy(&dst->i2field, &src->i2field, _state, make_automatic);
ae_matrix_init_copy(&dst->c2field, &src->c2field, _state, make_automatic);
}
void _rec1_clear(void* _p)
{
rec1 *p = (rec1*)_p;
ae_touch_ptr((void*)p);
ae_vector_clear(&p->b1field);
ae_vector_clear(&p->r1field);
ae_vector_clear(&p->i1field);
ae_vector_clear(&p->c1field);
ae_matrix_clear(&p->b2field);
ae_matrix_clear(&p->r2field);
ae_matrix_clear(&p->i2field);
ae_matrix_clear(&p->c2field);
}
void _rec1_destroy(void* _p)
{
rec1 *p = (rec1*)_p;
ae_touch_ptr((void*)p);
ae_vector_destroy(&p->b1field);
ae_vector_destroy(&p->r1field);
ae_vector_destroy(&p->i1field);
ae_vector_destroy(&p->c1field);
ae_matrix_destroy(&p->b2field);
ae_matrix_destroy(&p->r2field);
ae_matrix_destroy(&p->i2field);
ae_matrix_destroy(&p->c2field);
}
void _rec4serialization_init(void* _p, ae_state *_state, ae_bool make_automatic)
{
rec4serialization *p = (rec4serialization*)_p;
ae_touch_ptr((void*)p);
ae_vector_init(&p->b, 0, DT_BOOL, _state, make_automatic);
ae_vector_init(&p->i, 0, DT_INT, _state, make_automatic);
ae_vector_init(&p->r, 0, DT_REAL, _state, make_automatic);
}
void _rec4serialization_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
{
rec4serialization *dst = (rec4serialization*)_dst;
rec4serialization *src = (rec4serialization*)_src;
ae_vector_init_copy(&dst->b, &src->b, _state, make_automatic);
ae_vector_init_copy(&dst->i, &src->i, _state, make_automatic);
ae_vector_init_copy(&dst->r, &src->r, _state, make_automatic);
}
void _rec4serialization_clear(void* _p)
{
rec4serialization *p = (rec4serialization*)_p;
ae_touch_ptr((void*)p);
ae_vector_clear(&p->b);
ae_vector_clear(&p->i);
ae_vector_clear(&p->r);
}
void _rec4serialization_destroy(void* _p)
{
rec4serialization *p = (rec4serialization*)_p;
ae_touch_ptr((void*)p);
ae_vector_destroy(&p->b);
ae_vector_destroy(&p->i);
ae_vector_destroy(&p->r);
}
void _poolrec1_init(void* _p, ae_state *_state, ae_bool make_automatic)
{
poolrec1 *p = (poolrec1*)_p;
ae_touch_ptr((void*)p);
ae_vector_init(&p->i1val, 0, DT_INT, _state, make_automatic);
}
void _poolrec1_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
{
poolrec1 *dst = (poolrec1*)_dst;
poolrec1 *src = (poolrec1*)_src;
dst->cval = src->cval;
dst->rval = src->rval;
dst->ival = src->ival;
dst->bval = src->bval;
ae_vector_init_copy(&dst->i1val, &src->i1val, _state, make_automatic);
}
void _poolrec1_clear(void* _p)
{
poolrec1 *p = (poolrec1*)_p;
ae_touch_ptr((void*)p);
ae_vector_clear(&p->i1val);
}
void _poolrec1_destroy(void* _p)
{
poolrec1 *p = (poolrec1*)_p;
ae_touch_ptr((void*)p);
ae_vector_destroy(&p->i1val);
}
void _poolrec2_init(void* _p, ae_state *_state, ae_bool make_automatic)
{
poolrec2 *p = (poolrec2*)_p;
ae_touch_ptr((void*)p);
_poolrec1_init(&p->recval, _state, make_automatic);
ae_shared_pool_init(&p->pool, _state, make_automatic);
}
void _poolrec2_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
{
poolrec2 *dst = (poolrec2*)_dst;
poolrec2 *src = (poolrec2*)_src;
dst->bval = src->bval;
_poolrec1_init_copy(&dst->recval, &src->recval, _state, make_automatic);
ae_shared_pool_init_copy(&dst->pool, &src->pool, _state, make_automatic);
}
void _poolrec2_clear(void* _p)
{
poolrec2 *p = (poolrec2*)_p;
ae_touch_ptr((void*)p);
_poolrec1_clear(&p->recval);
ae_shared_pool_clear(&p->pool);
}
void _poolrec2_destroy(void* _p)
{
poolrec2 *p = (poolrec2*)_p;
ae_touch_ptr((void*)p);
_poolrec1_destroy(&p->recval);
ae_shared_pool_destroy(&p->pool);
}
void _poolsummand_init(void* _p, ae_state *_state, ae_bool make_automatic)
{
poolsummand *p = (poolsummand*)_p;
ae_touch_ptr((void*)p);
}
void _poolsummand_init_copy(void* _dst, void* _src, ae_state *_state, ae_bool make_automatic)
{
poolsummand *dst = (poolsummand*)_dst;
poolsummand *src = (poolsummand*)_src;
dst->val = src->val;
}
void _poolsummand_clear(void* _p)
{
poolsummand *p = (poolsummand*)_p;
ae_touch_ptr((void*)p);
}
void _poolsummand_destroy(void* _p)
{
poolsummand *p = (poolsummand*)_p;
ae_touch_ptr((void*)p);
}
#if (AE_OS==AE_WINDOWS) || defined(AE_DEBUG4WINDOWS)
#include
#endif
#if (AE_OS==AE_POSIX) || defined(AE_DEBUG4POSIX)
#include
#include
#endif
#define AE_SINGLECORE 1
#define AE_SEQUENTIAL_MULTICORE 2
#define AE_PARALLEL_SINGLECORE 3
#define AE_PARALLEL_MULTICORE 4
#define AE_SKIP_TEST 5
unsigned seed;
int global_failure_flag = 0;
ae_bool use_smp = ae_false;
#if (AE_OS==AE_WINDOWS) || defined(AE_DEBUG4WINDOWS)
CRITICAL_SECTION tests_lock;
CRITICAL_SECTION print_lock;
#elif (AE_OS==AE_POSIX) || defined(AE_DEBUG4POSIX)
pthread_mutex_t tests_lock;
pthread_mutex_t print_lock;
#else
void *tests_lock = NULL;
void *print_lock = NULL;
#endif
typedef struct
{
const char *name;
ae_bool (*testfunc)(ae_bool, ae_state*);
} _s_testrecord;
int unittests_processed = 0;
_s_testrecord unittests[] =
{
{"tsort",testtsort},
{"nearestneighbor",testnearestneighbor},
{"hqrnd",testhqrnd},
{"odesolver",testodesolver},
{"sparse",testsparse},
{"ablas",testablas},
{"creflections",testcreflections},
{"matgen",testmatgen},
{"trfac",testtrfac},
{"trlinsolve",testtrlinsolve},
{"safesolve",testsafesolve},
{"rcond",testrcond},
{"matinv",testmatinv},
{"hblas",testhblas},
{"sblas",testsblas},
{"ortfac",testortfac},
{"fbls",testfbls},
{"cqmodels",testcqmodels},
{"bdsvd",testbdsvd},
{"blas",testblas},
{"svd",testsvd},
{"optserv",testoptserv},
{"snnls",testsnnls},
{"sactivesets",testsactivesets},
{"xblas",testxblas},
{"directdensesolvers",testdirectdensesolvers},
{"linmin",testlinmin},
{"minlbfgs",testminlbfgs},
{"normestimator",testnormestimator},
{"linlsqr",testlinlsqr},
{"minbleic",testminbleic},
{"minqp",testminqp},
{"minlp",testminlp},
{"minnlc",testminnlc},
{"minbc",testminbc},
{"minns",testminns},
{"mincg",testmincg},
{"minlm",testminlm},
{"evd",testevd},
{"basestat",testbasestat},
{"pca",testpca},
{"bdss",testbdss},
{"mlpbase",testmlpbase},
{"lda",testlda},
{"ssa",testssa},
{"gammafunc",testgammafunc},
{"normaldistr",testnormaldistr},
{"linreg",testlinreg},
{"filters",testfilters},
{"mcpd",testmcpd},
{"mlpe",testmlpe},
{"mlptrain",testmlptrain},
{"clustering",testclustering},
{"dforest",testdforest},
{"knn",testknn},
{"gq",testgq},
{"gkq",testgkq},
{"autogk",testautogk},
{"fft",testfft},
{"fht",testfht},
{"conv",testconv},
{"corr",testcorr},
{"idw",testidw},
{"ratint",testratint},
{"fitsphere",testfitsphere},
{"spline1d",testspline1d},
{"parametric",testparametric},
{"spline3d",testspline3d},
{"polint",testpolint},
{"lsfit",testlsfit},
{"spline2d",testspline2d},
{"rbf",testrbf},
{"hermite",testhermite},
{"laguerre",testlaguerre},
{"legendre",testlegendre},
{"chebyshev",testchebyshev},
{"wsr",testwsr},
{"stest",teststest},
{"studentttests",teststudentttests},
{"mannwhitneyu",testmannwhitneyu},
{"schur",testschur},
{"spdgevd",testspdgevd},
{"inverseupdate",testinverseupdate},
{"polynomialsolver",testpolynomialsolver},
{"nleq",testnleq},
{"directsparsesolvers",testdirectsparsesolvers},
{"lincg",testlincg},
{"alglibbasics",testalglibbasics},
{NULL, NULL}
};
#if (AE_OS==AE_WINDOWS) || defined(AE_DEBUG4WINDOWS)
void acquire_lock(CRITICAL_SECTION *p_lock)
{
EnterCriticalSection(p_lock);
}
void release_lock(CRITICAL_SECTION *p_lock)
{
LeaveCriticalSection(p_lock);
}
#elif (AE_OS==AE_POSIX) || defined(AE_DEBUG4POSIX)
void acquire_lock(pthread_mutex_t *p_lock)
{
pthread_mutex_lock(p_lock);
}
void release_lock(pthread_mutex_t *p_lock)
{
pthread_mutex_unlock(p_lock);
}
#else
void acquire_lock(void **p_lock)
{
}
void release_lock(void **p_lock)
{
}
#endif
ae_bool call_unittest(
ae_bool(*testfunc)(ae_bool, ae_state*),
int *psticky)
{
#ifndef AE_USE_CPP_ERROR_HANDLING
ae_state _alglib_env_state;
ae_frame _frame_block;
jmp_buf _break_jump;
ae_bool result;
ae_state_init(&_alglib_env_state);
if( setjmp(_break_jump) )
{
*psticky = 1;
return ae_false;
}
ae_state_set_break_jump(&_alglib_env_state, &_break_jump);
if( use_smp )
ae_state_set_flags(&_alglib_env_state, _ALGLIB_FLG_THREADING_PARALLEL);
ae_frame_make(&_alglib_env_state, &_frame_block);
result = testfunc(ae_true, &_alglib_env_state);
ae_state_clear(&_alglib_env_state);
if( !result )
*psticky = 1;
return result;
#else
try
{
ae_state _alglib_env_state;
ae_frame _frame_block;
ae_bool result;
ae_state_init(&_alglib_env_state);
ae_frame_make(&_alglib_env_state, &_frame_block);
if( use_smp )
ae_state_set_flags(&_alglib_env_state, _ALGLIB_FLG_THREADING_PARALLEL);
result = testfunc(ae_true, &_alglib_env_state);
ae_state_clear(&_alglib_env_state);
if( !result )
*psticky = 1;
return result;
}
catch(...)
{
*psticky = 1;
return ae_false;
}
#endif
}
#if (AE_OS==AE_WINDOWS) || defined(AE_DEBUG4WINDOWS)
DWORD WINAPI tester_function(LPVOID T)
#elif AE_OS==AE_POSIX || defined(AE_DEBUG4POSIX)
void* tester_function(void *T)
#else
void tester_function(void *T)
#endif
{
int idx;
ae_bool status;
for(;;)
{
/*
* try to acquire test record
*/
acquire_lock(&tests_lock);
if( unittests[unittests_processed].name==NULL )
{
release_lock(&tests_lock);
break;
}
idx = unittests_processed;
unittests_processed++;
release_lock(&tests_lock);
/*
* Call unit test
*/
status = call_unittest(unittests[idx].testfunc, &global_failure_flag);
acquire_lock(&print_lock);
if( status )
printf("%-32s OK\n", unittests[idx].name);
else
printf("%-32s FAILED\n", unittests[idx].name);
fflush(stdout);
release_lock(&print_lock);
}
#if AE_OS==AE_WINDOWS || defined(AE_DEBUG4WINDOWS)
return 0;
#elif AE_OS==AE_POSIX || defined(AE_DEBUG4POSIX)
return NULL;
#else
#endif
}
int main(int argc, char **argv)
{
time_t time_0, time_1;
union
{
double a;
ae_int32_t p[2];
} u;
if( argc==2 )
seed = (unsigned)atoi(argv[1]);
else
{
time_t t;
seed = (unsigned)time(&t);
}
#if (AE_OS==AE_WINDOWS) || defined(AE_DEBUG4WINDOWS)
InitializeCriticalSection(&tests_lock);
InitializeCriticalSection(&print_lock);
#elif (AE_OS==AE_POSIX) || defined(AE_DEBUG4POSIX)
pthread_mutex_init(&tests_lock, NULL);
pthread_mutex_init(&print_lock, NULL);
#endif
/*
* SMP settings
*/
#if AE_TEST==AE_PARALLEL_MULTICORE || AE_TEST==AE_SEQUENTIAL_MULTICORE
use_smp = ae_true;
#else
use_smp = ae_false;
#endif
/*
* Seed
*/
printf("SEED: %u\n", (unsigned int)seed);
srand(seed);
/*
* Compiler
*/
#if AE_COMPILER==AE_GNUC
printf("COMPILER: GCC\n");
#elif AE_COMPILER==AE_SUNC
printf("COMPILER: SunStudio\n");
#elif AE_COMPILER==AE_MSVC
printf("COMPILER: MSVC\n");
#else
printf("COMPILER: unknown\n");
#endif
/*
* Architecture
*/
if( sizeof(void*)==4 )
printf("HARDWARE: 32-bit\n");
else if( sizeof(void*)==8 )
printf("HARDWARE: 64-bit\n");
else
printf("HARDWARE: strange (non-32, non-64)\n");
/*
* determine endianness of hardware.
* 1983 is a good number - non-periodic double representation allow us to
* easily distinguish between upper and lower halfs and to detect mixed endian hardware.
*/
u.a = 1.0/1983.0;
if( u.p[1]==0x3f408642 )
printf("HARDWARE: little-endian\n");
else if( u.p[0]==0x3f408642 )
printf("HARDWARE: big-endian\n");
else
printf("HARDWARE: mixed-endian\n");
/*
* CPU (as defined)
*/
#if AE_CPU==AE_INTEL
printf("CPU: Intel\n");
#elif AE_CPU==AE_SPARC
printf("CPU: SPARC\n");
#else
printf("CPU: unknown\n");
#endif
/*
* Cores count
*/
#ifdef _ALGLIB_HAS_WORKSTEALING
printf("CORES: %d\n", (int)ae_cores_count());
#else
printf("CORES: 1 (serial version)\n");
#endif
/*
* Support for vendor libraries
*/
#ifdef AE_MKL
printf("LIBS: MKL (Intel)\n");
#else
printf("LIBS: \n");
#endif
/*
* CPUID results
*/
printf("CPUID: %s\n", ae_cpuid()&CPU_SSE2 ? "sse2" : "");
/*
* OS
*/
#if AE_OS==AE_WINDOWS
printf("OS: Windows\n");
#elif AE_OS==AE_POSIX
printf("OS: POSIX\n");
#else
printf("OS: unknown\n");
#endif
/*
* Testing mode
*/
#if (AE_TEST==0) || (AE_TEST==AE_SINGLECORE)
printf("TESTING MODE: single core\n");
#elif AE_TEST==AE_PARALLEL_SINGLECORE
printf("TESTING MODE: single core, parallel\n");
#elif AE_TEST==AE_SEQUENTIAL_MULTICORE
printf("TESTING MODE: milti-core, sequential\n");
#elif AE_TEST==AE_PARALLEL_MULTICORE
printf("TESTING MODE: milti-core, parallel\n");
#elif AE_TEST==AE_SKIP_TEST
printf("TESTING MODE: just compiling\n");
printf("Done in 0 seconds\n");
return 0;
#else
#error Unknown AE_TEST being passed
#endif
/*
* now we are ready to test!
*/
time(&time_0);
#ifdef _ALGLIB_HAS_WORKSTEALING
if( ae_smpselftests() )
printf("%-32s OK\n", "SMP self tests");
else
{
printf("%-32s FAILED\n", "SMP self tests");
return 1;
}
#endif
fflush(stdout);
#if AE_TEST==0 || AE_TEST==AE_SINGLECORE || AE_TEST==AE_SEQUENTIAL_MULTICORE || AE_TEST==AE_SKIP_TEST
tester_function(NULL);
#elif AE_TEST==AE_PARALLEL_MULTICORE || AE_TEST==AE_PARALLEL_SINGLECORE
#ifdef _ALGLIB_HAS_WORKSTEALING
ae_set_cores_to_use(0);
#endif
#if AE_OS==AE_WINDOWS || defined(AE_DEBUG4WINDOWS)
{
SYSTEM_INFO sysInfo;
HANDLE *hThreads = NULL;
int idx;
GetSystemInfo(&sysInfo);
ae_assert(sysInfo.dwNumberOfProcessors>=1, "processors count is less than 1", NULL);
hThreads = (HANDLE*)malloc(sizeof(HANDLE)*sysInfo.dwNumberOfProcessors);
ae_assert(hThreads!=NULL, "malloc failure", NULL);
for(idx=0; idx=1, "processors count is less than 1", NULL);
threads = (pthread_t*)malloc(sizeof(pthread_t)*cpu_cnt);
ae_assert(threads!=NULL, "malloc failure", NULL);
for(idx=0; idx