From ce34633df7cd4b1df85955ba37969b358e5ba0f6 Mon Sep 17 00:00:00 2001 From: kalmarek Date: Thu, 28 Dec 2017 13:58:42 +0100 Subject: [PATCH 01/27] Replace kalmar by real name --- LICENSE.md | 226 ++++++++++++++++++++++++++--------------------------- 1 file changed, 113 insertions(+), 113 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 3b97910..433303d 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,29 +1,29 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0+: -> Copyright (c) 2017: kalmar. +> Copyright (c) 2017: Marek Kaluba. > 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. -> -> +> +> > 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 @@ -32,35 +32,35 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -71,49 +71,49 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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) @@ -122,18 +122,18 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -144,7 +144,7 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > (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 @@ -157,16 +157,16 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -174,7 +174,7 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -185,19 +185,19 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -205,9 +205,9 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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; @@ -215,24 +215,24 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -240,12 +240,12 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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, @@ -255,19 +255,19 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -279,13 +279,13 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -298,16 +298,16 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -320,7 +320,7 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -328,7 +328,7 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -339,7 +339,7 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -347,15 +347,15 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -364,41 +364,41 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -408,46 +408,46 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -456,14 +456,14 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -473,7 +473,7 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -481,13 +481,13 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > (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 @@ -497,19 +497,19 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -523,7 +523,7 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -531,7 +531,7 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -546,13 +546,13 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -562,9 +562,9 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -573,14 +573,14 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -589,19 +589,19 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -610,9 +610,9 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 @@ -622,15 +622,15 @@ The Property(T).jl package is licensed under the GNU Public License, Version 3.0 > 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 -> +> From fc54803b5888b270ccb86803a7eaf27603f43dec Mon Sep 17 00:00:00 2001 From: kalmarek Date: Mon, 1 Jan 2018 13:13:44 +0100 Subject: [PATCH 02/27] fix Memento deprecations; make clear when logger is global --- src/CheckSolution.jl | 10 +++--- src/Orbit-wise.jl | 44 ++++++++++++------------- src/PropertyT.jl | 76 ++++++++++++++++++++++++-------------------- src/SDPs.jl | 10 +++--- 4 files changed, 73 insertions(+), 67 deletions(-) diff --git a/src/CheckSolution.jl b/src/CheckSolution.jl index 0a7e32e..dc2aee7 100644 --- a/src/CheckSolution.jl +++ b/src/CheckSolution.jl @@ -51,10 +51,10 @@ function distance_to_cone{T<:Interval}(elt::GroupRingElem, Q::AbstractArray{T,2} SOS_diff = elt - SOS ɛ_dist = GroupRings.augmentation(SOS_diff) - info(logger, "ɛ(∑ξᵢ*ξᵢ) ∈ $(ɛ_dist)") + info(LOGGER, "ɛ(∑ξᵢ*ξᵢ) ∈ $(ɛ_dist)") eoi_SOS_L1_dist = norm(SOS_diff,1) - info(logger, "‖Δ² - λΔ - ∑ξᵢ*ξᵢ‖₁ ∈ $(eoi_SOS_L1_dist)") + info(LOGGER, "‖Δ² - λΔ - ∑ξᵢ*ξᵢ‖₁ ∈ $(eoi_SOS_L1_dist)") dist = 2^(wlen-1)*eoi_SOS_L1_dist return dist @@ -65,10 +65,10 @@ function distance_to_cone{T}(elt::GroupRingElem, Q::AbstractArray{T,2}, wlen::In SOS_diff = elt - SOS ɛ_dist = GroupRings.augmentation(SOS_diff) - info(logger, "ɛ(Δ² - λΔ - ∑ξᵢ*ξᵢ) ≈ $(@sprintf("%.10f", ɛ_dist))") + info(LOGGER, "ɛ(Δ² - λΔ - ∑ξᵢ*ξᵢ) ≈ $(@sprintf("%.10f", ɛ_dist))") eoi_SOS_L1_dist = norm(SOS_diff,1) - info(logger, "‖Δ² - λΔ - ∑ξᵢ*ξᵢ‖₁ ≈ $(@sprintf("%.10f", eoi_SOS_L1_dist))") + info(LOGGER, "‖Δ² - λΔ - ∑ξᵢ*ξᵢ‖₁ ≈ $(@sprintf("%.10f", eoi_SOS_L1_dist))") dist = 2^(wlen-1)*eoi_SOS_L1_dist return dist @@ -99,7 +99,7 @@ function augIdproj{T}(Q::AbstractArray{T,2}, logger) return Q end -function distance_to_positive_cone(Δ::GroupRingElem, λ, Q, wlen::Int) +function distance_to_positive_cone(Δ::GroupRingElem, λ, Q, wlen::Int, logger) info(logger, "------------------------------------------------------------") info(logger, "λ = $λ") info(logger, "Checking in floating-point arithmetic...") diff --git a/src/Orbit-wise.jl b/src/Orbit-wise.jl index 5cc7214..71c25f0 100644 --- a/src/Orbit-wise.jl +++ b/src/Orbit-wise.jl @@ -79,7 +79,7 @@ function sparsify!{Tv,Ti}(M::SparseMatrixCSC{Tv,Ti}, eps=eps(Tv); verbose=false) m = nnz(M) if verbose - info(logger, "Sparsified density:", rpad(densM, 20), " → ", rpad(dens(M), 20)) + info(LOGGER, "Sparsified density:", rpad(densM, 20), " → ", rpad(dens(M), 20)) end return M @@ -91,11 +91,11 @@ function sparsify!{T}(M::AbstractArray{T}, eps=eps(T); check=false, verbose=fals M[abs.(M) .< eps] .= zero(T) if check && rankM != rank(M) - warn(logger, "Sparsification decreased the rank!") + warn(LOGGER, "Sparsification decreased the rank!") end if verbose - info(logger, "Sparsified density:", rpad(densM, 20), " → ", rpad(dens(M),20)) + info(LOGGER, "Sparsified density:", rpad(densM, 20), " → ", rpad(dens(M),20)) end return sparse(M) @@ -178,8 +178,8 @@ function init_model(n, sizes) end function create_SDP_problem(sett::Settings) - info(logger, "Loading orbit data....") - @logtime logger SDP_problem, orb_data = OrbitData(sett); + info(LOGGER, "Loading orbit data....") + @logtime LOGGER SDP_problem, orb_data = OrbitData(sett); if sett.upper_bound < Inf λ = JuMP.getvariable(SDP_problem, :λ) @@ -187,8 +187,8 @@ function create_SDP_problem(sett::Settings) end t = length(orb_data.laplacian) - info(logger, "Adding $t constraints ... ") - @logtime logger addconstraints!(SDP_problem, orb_data) + info(LOGGER, "Adding $t constraints ... ") + @logtime LOGGER addconstraints!(SDP_problem, orb_data) return SDP_problem, orb_data end @@ -201,14 +201,14 @@ function λandP(m::JuMP.Model, data::OrbitData, warmstart=true) end function λandP(m::JuMP.Model, data::OrbitData, sett::Settings) - info(logger, "Solving SDP problem...") + info(LOGGER, "Solving SDP problem...") λ, Ps = λandP(m, data, sett.warmstart) - info(logger, "Reconstructing P...") + info(LOGGER, "Reconstructing P...") preps = load_preps(joinpath(prepath(sett), "preps.jld"), sett.autS) - @logtime logger recP = reconstruct_sol(preps, data.Us, Ps, data.dims) + @logtime LOGGER recP = reconstruct_sol(preps, data.Us, Ps, data.dims) fname = PropertyT.λSDPfilenames(fullpath(sett))[2] save(fname, "origP", Ps, "P", recP) @@ -229,22 +229,22 @@ end function check_property_T(sett::Settings) - init_orbit_data(logger, sett, radius=sett.radius) + init_orbit_data(LOGGER, sett, radius=sett.radius) if !sett.warmstart && all(isfile.(λSDPfilenames(fullpath(sett)))) λ, P = PropertyT.λandP(fullpath(sett)) else - info(logger, "Creating SDP problem...") + info(LOGGER, "Creating SDP problem...") SDP_problem, orb_data = create_SDP_problem(sett) JuMP.setsolver(SDP_problem, sett.solver) λ, P = λandP(SDP_problem, orb_data, sett) end - info(logger, "λ = $λ") - info(logger, "sum(P) = $(sum(P))") - info(logger, "maximum(P) = $(maximum(P))") - info(logger, "minimum(P) = $(minimum(P))") + info(LOGGER, "λ = $λ") + info(LOGGER, "sum(P) = $(sum(P))") + info(LOGGER, "maximum(P) = $(maximum(P))") + info(LOGGER, "minimum(P) = $(minimum(P))") if λ > 0 pm_fname, Δ_fname = pmΔfilenames(prepath(sett)) @@ -254,24 +254,24 @@ function check_property_T(sett::Settings) isapprox(eigvals(P), abs.(eigvals(P)), atol=sett.tol) || warn("The solution matrix doesn't seem to be positive definite!") # @assert P == Symmetric(P) - @logtime logger Q = real(sqrtm(Symmetric(P))) + @logtime LOGGER Q = real(sqrtm(Symmetric(P))) - sgap = distance_to_positive_cone(Δ, λ, Q, 2*sett.radius) + sgap = distance_to_positive_cone(Δ, λ, Q, 2*sett.radius, LOGGER) if isa(sgap, Interval) sgap = sgap.lo end if sgap > 0 - info(logger, "λ ≥ $(Float64(trunc(sgap,12)))") + info(LOGGER, "λ ≥ $(Float64(trunc(sgap,12)))") Kazhdan_κ = PropertyT.Kazhdan_from_sgap(sgap, length(sett.S)) Kazhdan_κ = Float64(trunc(Kazhdan_κ, 12)) - info(logger, "κ($(sett.name), S) ≥ $Kazhdan_κ: Group HAS property (T)!") + info(LOGGER, "κ($(sett.name), S) ≥ $Kazhdan_κ: Group HAS property (T)!") return true else sgap = Float64(trunc(sgap, 12)) - info(logger, "λ($(sett.name), S) ≥ $sgap: Group may NOT HAVE property (T)!") + info(LOGGER, "λ($(sett.name), S) ≥ $sgap: Group may NOT HAVE property (T)!") return false end end - info(logger, "κ($(sett.name), S) ≥ $λ < 0: Tells us nothing about property (T)") + info(LOGGER, "κ($(sett.name), S) ≥ $λ < 0: Tells us nothing about property (T)") return false end diff --git a/src/PropertyT.jl b/src/PropertyT.jl index e86ef1e..a73cc45 100644 --- a/src/PropertyT.jl +++ b/src/PropertyT.jl @@ -12,19 +12,21 @@ using MathProgBase using Memento -const logger = Memento.config("info", fmt="{msg}") -const solver_logger = Memento.config("info", fmt="{msg}") +const LOGGER = Memento.config("info", fmt="{msg}") +const LOGGER_SOLVER = Memento.config("info", fmt="{msg}") function setup_logging(name::String) - isdir(name) || mkdir(name) + isdir(name) || mkdir(name) - Memento.add_handler(logger, - Memento.DefaultHandler(joinpath(name,"full_$(string((now()))).log"), - Memento.DefaultFormatter("{date}| {msg}")), "full_log") + handler = Memento.DefaultHandler( + joinpath(name,"full_$(string((now()))).log"), Memento.DefaultFormatter("{date}| {msg}") + ) + handler.levels.x = LOGGER.levels + LOGGER.handlers["full_log"] = handler - e = redirect_stderr(logger.handlers["full_log"].io) + e = redirect_stderr(logger.handlers["full_log"].io) - return logger + return logger end macro logtime(logger, ex) @@ -35,7 +37,7 @@ macro logtime(logger, ex) elapsedtime = Base.time_ns() - elapsedtime local diff = Base.GC_Diff(Base.gc_num(), stats) local ts = time_string(elapsedtime, diff.allocd, diff.total_time, - Base.gc_alloc_count(diff)) + Base.gc_alloc_count(diff)) esc(info(logger, ts)) val end @@ -85,7 +87,7 @@ function λSDPfilenames(prefix::String) end function ΔandSDPconstraints(prefix::String, G::Group) - info(logger, "Loading precomputed pm, Δ, sdp_constraints...") + info(LOGGER, "Loading precomputed pm, Δ, sdp_constraints...") pm_fname, Δ_fname = pmΔfilenames(prefix) product_matrix = load(pm_fname, "pm") @@ -98,7 +100,7 @@ function ΔandSDPconstraints(prefix::String, G::Group) end function ΔandSDPconstraints{T<:GroupElem}(name::String, S::Vector{T}, Id::T; radius::Int=2) - info(logger, "Computing pm, Δ, sdp_constraints...") + info(LOGGER, "Computing pm, Δ, sdp_constraints...") Δ, sdp_constraints = ΔandSDPconstraints(S, Id, radius=radius) pm_fname, Δ_fname = pmΔfilenames(name) save(pm_fname, "pm", parent(Δ).pm) @@ -107,14 +109,14 @@ function ΔandSDPconstraints{T<:GroupElem}(name::String, S::Vector{T}, Id::T; ra end function ΔandSDPconstraints{T<:GroupElem}(S::Vector{T}, Id::T; radius::Int=2) - info(logger, "Generating balls of sizes $sizes") - @logtime logger E_R, sizes = Groups.generate_balls(S, Id, radius=2*radius) + info(LOGGER, "Generating balls of sizes $sizes") + @logtime LOGGER E_R, sizes = Groups.generate_balls(S, Id, radius=2*radius) - info(logger, "Creating product matrix...") - @logtime logger pm = GroupRings.create_pm(E_R, GroupRings.reverse_dict(E_R), sizes[radius]; twisted=true) + info(LOGGER, "Creating product matrix...") + @logtime LOGGER pm = GroupRings.create_pm(E_R, GroupRings.reverse_dict(E_R), sizes[radius]; twisted=true) - info(logger, "Creating sdp_constratints...") - @logtime logger sdp_constraints = PropertyT.constraints(pm) + info(LOGGER, "Creating sdp_constratints...") + @logtime LOGGER sdp_constraints = PropertyT.constraints(pm) RG = GroupRing(parent(Id), E_R, pm) @@ -128,7 +130,7 @@ function λandP(name::String) f₂ = exists(SDP_fname) if f₁ && f₂ - info(logger, "Loading precomputed λ, P...") + info(LOGGER, "Loading precomputed λ, P...") λ = load(λ_fname, "λ") P = load(SDP_fname, "P") else @@ -138,10 +140,14 @@ function λandP(name::String) end function λandP(name::String, SDP_problem::JuMP.Model, varλ, varP, warmstart=false) - add_handler(solver_logger, - DefaultHandler(joinpath(name, "solver_$(string(now())).log"), - DefaultFormatter("{date}| {msg}")), - "solver_log") + + handler = DefaultHandler( + joinpath(name, "solver_$(string(now())).log"), + DefaultFormatter("{date}| {msg}") + ) + handler.levels.x = LOGGER_SOLVER.levels + LOGGER_SOLVER.handlers["solver_log"] = handler + if warmstart && isfile(joinpath(name, "warmstart.jld")) ws = load(joinpath(name, "warmstart.jld"), "warmstart") else @@ -150,7 +156,7 @@ function λandP(name::String, SDP_problem::JuMP.Model, varλ, varP, warmstart=fa λ, P, warmstart = compute_λandP(SDP_problem, varλ, varP, warmstart=ws) - remove_handler(solver_logger, "solver_log") + delete!(LOGGER_SOLVER.handlers, "solver_log") λ_fname, P_fname = λSDPfilenames(name) @@ -276,7 +282,7 @@ function compute_λandP(m, varλ, varP; warmstart=nothing) solve_SDP(m) λ = MathProgBase.getobjval(m.internalModel) catch y - warn(solver_logger, y) + warn(LOGGER_SOLVER, y) end end @@ -308,7 +314,7 @@ function check_property_T(name::String, S, Id, solver, upper_bound, tol, radius) if all(exists.(λSDPfilenames(name))) λ, P = λandP(name) else - info(logger, "Creating SDP problem...") + info(LOGGER, "Creating SDP problem...") SDP_problem, λ, P = create_SDP_problem(Δ, sdp_constraints, upper_bound=upper_bound) JuMP.setsolver(SDP_problem, solver) @@ -316,10 +322,10 @@ function check_property_T(name::String, S, Id, solver, upper_bound, tol, radius) λ, P = λandP(name, SDP_problem, λ, P) end - info(logger, "λ = $λ") - info(logger, "sum(P) = $(sum(P))") - info(logger, "maximum(P) = $(maximum(P))") - info(logger, "minimum(P) = $(minimum(P))") + info(LOGGER, "λ = $λ") + info(LOGGER, "sum(P) = $(sum(P))") + info(LOGGER, "maximum(P) = $(maximum(P))") + info(LOGGER, "minimum(P) = $(minimum(P))") if λ > 0 pm_fname, Δ_fname = pmΔfilenames(name) @@ -329,25 +335,25 @@ function check_property_T(name::String, S, Id, solver, upper_bound, tol, radius) isapprox(eigvals(P), abs(eigvals(P)), atol=tol) || warn("The solution matrix doesn't seem to be positive definite!") # @assert P == Symmetric(P) - @logtime logger Q = real(sqrtm(Symmetric(P))) + @logtime LOGGER Q = real(sqrtm(Symmetric(P))) - sgap = distance_to_positive_cone(Δ, λ, Q, 2*radius) + sgap = distance_to_positive_cone(Δ, λ, Q, 2*radius, LOGGER) if isa(sgap, Interval) sgap = sgap.lo end if sgap > 0 - info(logger, "λ ≥ $(Float64(trunc(sgap,12)))") + info(LOGGER, "λ ≥ $(Float64(trunc(sgap,12)))") Kazhdan_κ = Kazhdan_from_sgap(sgap, length(S)) Kazhdan_κ = Float64(trunc(Kazhdan_κ, 12)) - info(logger, "κ($name, S) ≥ $Kazhdan_κ: Group HAS property (T)!") + info(LOGGER, "κ($name, S) ≥ $Kazhdan_κ: Group HAS property (T)!") return true else sgap = Float64(trunc(sgap, 12)) - info(logger, "λ($name, S) ≥ $sgap: Group may NOT HAVE property (T)!") + info(LOGGER, "λ($name, S) ≥ $sgap: Group may NOT HAVE property (T)!") return false end end - info(logger, "κ($name, S) ≥ $λ < 0: Tells us nothing about property (T)") + info(LOGGER, "κ($name, S) ≥ $λ < 0: Tells us nothing about property (T)") return false end diff --git a/src/SDPs.jl b/src/SDPs.jl index 6360db4..1ab22b9 100644 --- a/src/SDPs.jl +++ b/src/SDPs.jl @@ -56,20 +56,20 @@ function create_SDP_problem(Δ::GroupRingElem, matrix_constraints; upper_bound=I end function solve_SDP(SDP_problem) - info(logger, Base.repr(SDP_problem)) + info(LOGGER, Base.repr(SDP_problem)) - o = redirect_stdout(solver_logger.handlers["solver_log"].io) + o = redirect_stdout(LOGGER_SOLVER.handlers["solver_log"].io) Base.Libc.flush_cstdio() - @logtime logger solution_status = MathProgBase.optimize!(SDP_problem.internalModel) + @logtime LOGGER solution_status = MathProgBase.optimize!(SDP_problem.internalModel) Base.Libc.flush_cstdio() redirect_stdout(o) if solution_status != :Optimal - warn(logger, "The solver did not solve the problem successfully!") + warn(LOGGER, "The solver did not solve the problem successfully!") end - info(logger, solution_status) + info(LOGGER, solution_status) return 0 end From 47f6d3637ee7cb9ec2e81d8848729851a53bcf2d Mon Sep 17 00:00:00 2001 From: kalmarek Date: Mon, 1 Jan 2018 14:06:33 +0100 Subject: [PATCH 03/27] fix indentation to 4 spaces --- src/CheckSolution.jl | 92 +++++------ src/Orbit-wise.jl | 326 +++++++++++++++++++------------------- src/OrbitDecomposition.jl | 144 ++++++++--------- src/Projections.jl | 256 +++++++++++++++--------------- src/PropertyT.jl | 141 ++++++++--------- 5 files changed, 477 insertions(+), 482 deletions(-) diff --git a/src/CheckSolution.jl b/src/CheckSolution.jl index dc2aee7..768397c 100644 --- a/src/CheckSolution.jl +++ b/src/CheckSolution.jl @@ -23,80 +23,80 @@ end function compute_SOS(Q::AbstractArray, pm::Array{Int,2}, l::Int) - # result = zeros(eltype(Q), l) - # r = similar(result) - # for i in 1:size(Q,2) - # print(" $i") - # result += GroupRings.mul!(r, view(Q,:,i), view(Q,:,i), pm) - # end + # result = zeros(eltype(Q), l) + # r = similar(result) + # for i in 1:size(Q,2) + # print(" $i") + # result += GroupRings.mul!(r, view(Q,:,i), view(Q,:,i), pm) + # end - @everywhere groupring_square = PropertyT.groupring_square + @everywhere groupring_square = PropertyT.groupring_square - result = @parallel (+) for i in 1:size(Q,2) - groupring_square(Q[:,i], l, pm) - end + result = @parallel (+) for i in 1:size(Q,2) + groupring_square(Q[:,i], l, pm) +end - println("") +println("") - return result +return result end function compute_SOS(Q::AbstractArray, RG::GroupRing, l::Int) - result = compute_SOS(Q, RG.pm, l) - return GroupRingElem(result, RG) + result = compute_SOS(Q, RG.pm, l) + return GroupRingElem(result, RG) end function distance_to_cone{T<:Interval}(elt::GroupRingElem, Q::AbstractArray{T,2}, wlen::Int) - SOS = compute_SOS(Q, parent(elt), length(elt.coeffs)) - SOS_diff = elt - SOS + SOS = compute_SOS(Q, parent(elt), length(elt.coeffs)) + SOS_diff = elt - SOS - ɛ_dist = GroupRings.augmentation(SOS_diff) - info(LOGGER, "ɛ(∑ξᵢ*ξᵢ) ∈ $(ɛ_dist)") + ɛ_dist = GroupRings.augmentation(SOS_diff) + info(LOGGER, "ɛ(∑ξᵢ*ξᵢ) ∈ $(ɛ_dist)") - eoi_SOS_L1_dist = norm(SOS_diff,1) - info(LOGGER, "‖Δ² - λΔ - ∑ξᵢ*ξᵢ‖₁ ∈ $(eoi_SOS_L1_dist)") + eoi_SOS_L1_dist = norm(SOS_diff,1) + info(LOGGER, "‖Δ² - λΔ - ∑ξᵢ*ξᵢ‖₁ ∈ $(eoi_SOS_L1_dist)") - dist = 2^(wlen-1)*eoi_SOS_L1_dist - return dist + dist = 2^(wlen-1)*eoi_SOS_L1_dist + return dist end function distance_to_cone{T}(elt::GroupRingElem, Q::AbstractArray{T,2}, wlen::Int) - SOS = compute_SOS(Q, parent(elt), length(elt.coeffs)) - SOS_diff = elt - SOS + SOS = compute_SOS(Q, parent(elt), length(elt.coeffs)) + SOS_diff = elt - SOS - ɛ_dist = GroupRings.augmentation(SOS_diff) - info(LOGGER, "ɛ(Δ² - λΔ - ∑ξᵢ*ξᵢ) ≈ $(@sprintf("%.10f", ɛ_dist))") + ɛ_dist = GroupRings.augmentation(SOS_diff) + info(LOGGER, "ɛ(Δ² - λΔ - ∑ξᵢ*ξᵢ) ≈ $(@sprintf("%.10f", ɛ_dist))") - eoi_SOS_L1_dist = norm(SOS_diff,1) - info(LOGGER, "‖Δ² - λΔ - ∑ξᵢ*ξᵢ‖₁ ≈ $(@sprintf("%.10f", eoi_SOS_L1_dist))") + eoi_SOS_L1_dist = norm(SOS_diff,1) + info(LOGGER, "‖Δ² - λΔ - ∑ξᵢ*ξᵢ‖₁ ≈ $(@sprintf("%.10f", eoi_SOS_L1_dist))") - dist = 2^(wlen-1)*eoi_SOS_L1_dist - return dist + dist = 2^(wlen-1)*eoi_SOS_L1_dist + return dist end function augIdproj{T, I<:AbstractInterval}(S::Type{I}, Q::AbstractArray{T,2}) - l = size(Q, 2) - R = zeros(S, (l,l)) - Threads.@threads for j in 1:l - col = sum(view(Q, :,j))/l - for i in 1:l - R[i,j] = Q[i,j] - col ± eps(0.0) - end - end - return R + l = size(Q, 2) + R = zeros(S, (l,l)) + Threads.@threads for j in 1:l + col = sum(view(Q, :,j))/l + for i in 1:l + R[i,j] = Q[i,j] - col ± eps(0.0) + end + end + return R end function augIdproj{T}(Q::AbstractArray{T,2}, logger) - info(logger, "Projecting columns of Q to the augmentation ideal...") - @logtime logger Q = augIdproj(Interval{T}, Q) + info(logger, "Projecting columns of Q to the augmentation ideal...") + @logtime logger Q = augIdproj(Interval{T}, Q) - info(logger, "Checking that sum of every column contains 0.0... ") - check = all([0.0 in sum(view(Q, :, i)) for i in 1:size(Q, 2)]) - info(logger, (check? "They do." : "FAILED!")) + info(logger, "Checking that sum of every column contains 0.0... ") + check = all([0.0 in sum(view(Q, :, i)) for i in 1:size(Q, 2)]) + info(logger, (check? "They do." : "FAILED!")) - @assert check + @assert check - return Q + return Q end function distance_to_positive_cone(Δ::GroupRingElem, λ, Q, wlen::Int, logger) diff --git a/src/Orbit-wise.jl b/src/Orbit-wise.jl index 71c25f0..352c4cf 100644 --- a/src/Orbit-wise.jl +++ b/src/Orbit-wise.jl @@ -4,16 +4,16 @@ using SCS export Settings, OrbitData immutable Settings{T<:AbstractMathProgSolver} - name::String - N::Int - G::Group - S::Vector - autS::Group - radius::Int - solver::T - upper_bound::Float64 - tol::Float64 - warmstart::Bool + name::String + N::Int + G::Group + S::Vector + autS::Group + radius::Int + solver::T + upper_bound::Float64 + tol::Float64 + warmstart::Bool end prefix(s::Settings) = s.name @@ -22,43 +22,43 @@ prepath(s::Settings) = prefix(s) fullpath(s::Settings) = joinpath(prefix(s), suffix(s)) immutable OrbitData{T<:AbstractArray{Float64, 2}, LapType <:AbstractVector{Float64}} - name::String - Us::Vector{T} - Ps::Vector{Array{JuMP.Variable,2}} - cnstr::Vector{SparseMatrixCSC{Float64, Int}} - laplacian::LapType - laplacianSq::LapType - dims::Vector{Int} + name::String + Us::Vector{T} + Ps::Vector{Array{JuMP.Variable,2}} + cnstr::Vector{SparseMatrixCSC{Float64, Int}} + laplacian::LapType + laplacianSq::LapType + dims::Vector{Int} end function OrbitData(sett::Settings) - splap = load(joinpath(prepath(sett), "delta.jld"), "Δ"); - pm = load(joinpath(prepath(sett), "pm.jld"), "pm"); - cnstr = PropertyT.constraints(pm); - splap² = similar(splap) - splap² = GroupRings.mul!(splap², splap, splap, pm); + splap = load(joinpath(prepath(sett), "delta.jld"), "Δ"); + pm = load(joinpath(prepath(sett), "pm.jld"), "pm"); + cnstr = PropertyT.constraints(pm); + splap² = similar(splap) + splap² = GroupRings.mul!(splap², splap, splap, pm); - Uπs = load(joinpath(prepath(sett), "U_pis.jld"), "Uπs") - nzros = [i for i in 1:length(Uπs) if size(Uπs[i],2) !=0] - Uπs = Uπs[nzros] - Uπs = sparsify!.(Uπs, sett.tol, check=true, verbose=true) + Uπs = load(joinpath(prepath(sett), "U_pis.jld"), "Uπs") + nzros = [i for i in 1:length(Uπs) if size(Uπs[i],2) !=0] + Uπs = Uπs[nzros] + Uπs = sparsify!.(Uπs, sett.tol, check=true, verbose=true) - #dimensions of the corresponding πs: - dims = load(joinpath(prepath(sett), "U_pis.jld"), "dims")[nzros] + #dimensions of the corresponding πs: + dims = load(joinpath(prepath(sett), "U_pis.jld"), "dims")[nzros] - m, P = init_model(size(Uπs,1), [size(U,2) for U in Uπs]); + m, P = init_model(size(Uπs,1), [size(U,2) for U in Uπs]); - orbits = load(joinpath(prepath(sett), "orbits.jld"), "orbits"); - n = size(Uπs[1],1) - orb_spcnstrm = [orbit_constraint(cnstr[collect(orb)], n) for orb in orbits] - orb_splap = orbit_spvector(splap, orbits) - orb_splap² = orbit_spvector(splap², orbits) + orbits = load(joinpath(prepath(sett), "orbits.jld"), "orbits"); + n = size(Uπs[1],1) + orb_spcnstrm = [orbit_constraint(cnstr[collect(orb)], n) for orb in orbits] + orb_splap = orbit_spvector(splap, orbits) + orb_splap² = orbit_spvector(splap², orbits) - orbData = OrbitData(fullpath(sett), Uπs, P, orb_spcnstrm, orb_splap, orb_splap², dims); + orbData = OrbitData(fullpath(sett), Uπs, P, orb_spcnstrm, orb_splap, orb_splap², dims); - # orbData = OrbitData(name, Uπs, P, orb_spcnstrm, splap, splap², dims); + # orbData = OrbitData(name, Uπs, P, orb_spcnstrm, splap, splap², dims); - return m, orbData + return m, orbData end include("OrbitDecomposition.jl") @@ -67,152 +67,152 @@ dens(M::SparseMatrixCSC) = length(M.nzval)/length(M) dens(M::AbstractArray) = length(findn(M)[1])/length(M) function sparsify!{Tv,Ti}(M::SparseMatrixCSC{Tv,Ti}, eps=eps(Tv); verbose=false) - n = nnz(M) + n = nnz(M) - densM = dens(M) - for i in eachindex(M.nzval) - if abs(M.nzval[i]) < eps - M.nzval[i] = zero(Tv) - end - end - dropzeros!(M) - m = nnz(M) + densM = dens(M) + for i in eachindex(M.nzval) + if abs(M.nzval[i]) < eps + M.nzval[i] = zero(Tv) + end + end + dropzeros!(M) + m = nnz(M) - if verbose - info(LOGGER, "Sparsified density:", rpad(densM, 20), " → ", rpad(dens(M), 20)) - end + if verbose + info(LOGGER, "Sparsified density:", rpad(densM, 20), " → ", rpad(dens(M), 20)) + end - return M + return M end function sparsify!{T}(M::AbstractArray{T}, eps=eps(T); check=false, verbose=false) - densM = dens(M) - rankM = rank(M) - M[abs.(M) .< eps] .= zero(T) + densM = dens(M) + rankM = rank(M) + M[abs.(M) .< eps] .= zero(T) - if check && rankM != rank(M) - warn(LOGGER, "Sparsification decreased the rank!") - end + if check && rankM != rank(M) + warn(LOGGER, "Sparsification decreased the rank!") + end - if verbose - info(LOGGER, "Sparsified density:", rpad(densM, 20), " → ", rpad(dens(M),20)) - end + if verbose + info(LOGGER, "Sparsified density:", rpad(densM, 20), " → ", rpad(dens(M),20)) + end - return sparse(M) + return sparse(M) end sparsify{T}(U::AbstractArray{T}, tol=eps(T); check=true, verbose=false) = sparsify!(deepcopy(U), tol, check=check, verbose=verbose) function init_orbit_data(logger, sett::Settings; radius=2) - ex(fname) = isfile(joinpath(prepath(sett), fname)) + ex(fname) = isfile(joinpath(prepath(sett), fname)) - files_exists = ex.(["delta.jld", "pm.jld", "U_pis.jld", "orbits.jld", "preps.jld"]) + files_exists = ex.(["delta.jld", "pm.jld", "U_pis.jld", "orbits.jld", "preps.jld"]) - if !all(files_exists) - compute_orbit_data(logger, prepath(sett), sett.G, sett.S, sett.autS, radius=radius) - end + if !all(files_exists) + compute_orbit_data(logger, prepath(sett), sett.G, sett.S, sett.autS, radius=radius) + end - return 0 + return 0 end function transform(U::AbstractArray, V::AbstractArray; sparse=true) - if sparse - return sparsify!(U'*V*U) - else - return U'*V*U - end + if sparse + return sparsify!(U'*V*U) + else + return U'*V*U + end end A(data::OrbitData, π, t) = data.dims[π].*transform(data.Us[π], data.cnstr[t]) function constrLHS(m::JuMP.Model, data::OrbitData, t) - l = endof(data.Us) - lhs = @expression(m, sum(vecdot(A(data, π, t), data.Ps[π]) for π in 1:l)) - return lhs + l = endof(data.Us) + lhs = @expression(m, sum(vecdot(A(data, π, t), data.Ps[π]) for π in 1:l)) + return lhs end function constrLHS(m::JuMP.Model, cnstr, Us, Ust, dims, vars, eps=100*eps(1.0)) - M = [PropertyT.sparsify!(dims[π].*Ust[π]*cnstr*Us[π], eps) for π in 1:endof(Us)] - return @expression(m, sum(vecdot(M[π], vars[π]) for π in 1:endof(Us))) + M = [PropertyT.sparsify!(dims[π].*Ust[π]*cnstr*Us[π], eps) for π in 1:endof(Us)] + return @expression(m, sum(vecdot(M[π], vars[π]) for π in 1:endof(Us))) end function addconstraints!(m::JuMP.Model, data::OrbitData, l::Int=length(data.laplacian); var::Symbol=:λ) - λ = m[var] - Ust = [U' for U in data.Us] - idx = [π for π in 1:endof(data.Us) if size(data.Us[π],2) != 0] + λ = m[var] + Ust = [U' for U in data.Us] + idx = [π for π in 1:endof(data.Us) if size(data.Us[π],2) != 0] - for t in 1:l - if t % 100 == 0 - print(t, ", ") - end - # lhs = constrLHS(m, data, t) - lhs = constrLHS(m, data.cnstr[t], data.Us[idx], Ust[idx], data.dims[idx], data.Ps[idx]) + for t in 1:l + if t % 100 == 0 + print(t, ", ") + end + # lhs = constrLHS(m, data, t) + lhs = constrLHS(m, data.cnstr[t], data.Us[idx], Ust[idx], data.dims[idx], data.Ps[idx]) - d, d² = data.laplacian[t], data.laplacianSq[t] - # if lhs == zero(lhs) - # if d == 0 && d² == 0 - # info("Detected empty constraint") - # continue - # else - # warn("Adding unsatisfiable constraint!") - # end - # end - JuMP.@constraint(m, lhs == d² - λ*d) - end - println("") + d, d² = data.laplacian[t], data.laplacianSq[t] + # if lhs == zero(lhs) + # if d == 0 && d² == 0 + # info("Detected empty constraint") + # continue + # else + # warn("Adding unsatisfiable constraint!") + # end + # end + JuMP.@constraint(m, lhs == d² - λ*d) + end + println("") end function init_model(n, sizes) - m = JuMP.Model(); - P = Vector{Array{JuMP.Variable,2}}(n) + m = JuMP.Model(); + P = Vector{Array{JuMP.Variable,2}}(n) - for (k,s) in enumerate(sizes) - P[k] = JuMP.@variable(m, [i=1:s, j=1:s]) - JuMP.@SDconstraint(m, P[k] >= 0.0) - end + for (k,s) in enumerate(sizes) + P[k] = JuMP.@variable(m, [i=1:s, j=1:s]) + JuMP.@SDconstraint(m, P[k] >= 0.0) + end - JuMP.@variable(m, λ >= 0.0) - JuMP.@objective(m, Max, λ) - return m, P + JuMP.@variable(m, λ >= 0.0) + JuMP.@objective(m, Max, λ) + return m, P end function create_SDP_problem(sett::Settings) - info(LOGGER, "Loading orbit data....") - @logtime LOGGER SDP_problem, orb_data = OrbitData(sett); + info(LOGGER, "Loading orbit data....") + @logtime LOGGER SDP_problem, orb_data = OrbitData(sett); - if sett.upper_bound < Inf - λ = JuMP.getvariable(SDP_problem, :λ) - JuMP.@constraint(SDP_problem, λ <= sett.upper_bound) - end + if sett.upper_bound < Inf + λ = JuMP.getvariable(SDP_problem, :λ) + JuMP.@constraint(SDP_problem, λ <= sett.upper_bound) + end - t = length(orb_data.laplacian) - info(LOGGER, "Adding $t constraints ... ") - @logtime LOGGER addconstraints!(SDP_problem, orb_data) + t = length(orb_data.laplacian) + info(LOGGER, "Adding $t constraints ... ") + @logtime LOGGER addconstraints!(SDP_problem, orb_data) - return SDP_problem, orb_data + return SDP_problem, orb_data end function λandP(m::JuMP.Model, data::OrbitData, warmstart=true) - varλ = m[:λ] - varP = data.Ps - λ, Ps = PropertyT.λandP(data.name, m, varλ, varP, warmstart) - return λ, Ps + varλ = m[:λ] + varP = data.Ps + λ, Ps = PropertyT.λandP(data.name, m, varλ, varP, warmstart) + return λ, Ps end function λandP(m::JuMP.Model, data::OrbitData, sett::Settings) - info(LOGGER, "Solving SDP problem...") - λ, Ps = λandP(m, data, sett.warmstart) + info(LOGGER, "Solving SDP problem...") + λ, Ps = λandP(m, data, sett.warmstart) - info(LOGGER, "Reconstructing P...") + info(LOGGER, "Reconstructing P...") - preps = load_preps(joinpath(prepath(sett), "preps.jld"), sett.autS) + preps = load_preps(joinpath(prepath(sett), "preps.jld"), sett.autS) - @logtime LOGGER recP = reconstruct_sol(preps, data.Us, Ps, data.dims) + @logtime LOGGER recP = reconstruct_sol(preps, data.Us, Ps, data.dims) - fname = PropertyT.λSDPfilenames(fullpath(sett))[2] - save(fname, "origP", Ps, "P", recP) - return λ, recP + fname = PropertyT.λSDPfilenames(fullpath(sett))[2] + save(fname, "origP", Ps, "P", recP) + return λ, recP end function load_preps(fname::String, G::Nemo.Group) @@ -229,49 +229,49 @@ end function check_property_T(sett::Settings) - init_orbit_data(LOGGER, sett, radius=sett.radius) + init_orbit_data(LOGGER, sett, radius=sett.radius) - if !sett.warmstart && all(isfile.(λSDPfilenames(fullpath(sett)))) - λ, P = PropertyT.λandP(fullpath(sett)) - else - info(LOGGER, "Creating SDP problem...") - SDP_problem, orb_data = create_SDP_problem(sett) - JuMP.setsolver(SDP_problem, sett.solver) + if !sett.warmstart && all(isfile.(λSDPfilenames(fullpath(sett)))) + λ, P = PropertyT.λandP(fullpath(sett)) + else + info(LOGGER, "Creating SDP problem...") + SDP_problem, orb_data = create_SDP_problem(sett) + JuMP.setsolver(SDP_problem, sett.solver) - λ, P = λandP(SDP_problem, orb_data, sett) - end + λ, P = λandP(SDP_problem, orb_data, sett) + end - info(LOGGER, "λ = $λ") - info(LOGGER, "sum(P) = $(sum(P))") - info(LOGGER, "maximum(P) = $(maximum(P))") - info(LOGGER, "minimum(P) = $(minimum(P))") + info(LOGGER, "λ = $λ") + info(LOGGER, "sum(P) = $(sum(P))") + info(LOGGER, "maximum(P) = $(maximum(P))") + info(LOGGER, "minimum(P) = $(minimum(P))") - if λ > 0 - pm_fname, Δ_fname = pmΔfilenames(prepath(sett)) - RG = GroupRing(sett.G, load(pm_fname, "pm")) - Δ = GroupRingElem(load(Δ_fname, "Δ")[:, 1], RG) + if λ > 0 + pm_fname, Δ_fname = pmΔfilenames(prepath(sett)) + RG = GroupRing(sett.G, load(pm_fname, "pm")) + Δ = GroupRingElem(load(Δ_fname, "Δ")[:, 1], RG) - isapprox(eigvals(P), abs.(eigvals(P)), atol=sett.tol) || - warn("The solution matrix doesn't seem to be positive definite!") - # @assert P == Symmetric(P) - @logtime LOGGER Q = real(sqrtm(Symmetric(P))) + isapprox(eigvals(P), abs.(eigvals(P)), atol=sett.tol) || + warn("The solution matrix doesn't seem to be positive definite!") + # @assert P == Symmetric(P) + @logtime LOGGER Q = real(sqrtm(Symmetric(P))) - sgap = distance_to_positive_cone(Δ, λ, Q, 2*sett.radius, LOGGER) - if isa(sgap, Interval) - sgap = sgap.lo - end - if sgap > 0 - info(LOGGER, "λ ≥ $(Float64(trunc(sgap,12)))") + sgap = distance_to_positive_cone(Δ, λ, Q, 2*sett.radius, LOGGER) + if isa(sgap, Interval) + sgap = sgap.lo + end + if sgap > 0 + info(LOGGER, "λ ≥ $(Float64(trunc(sgap,12)))") Kazhdan_κ = PropertyT.Kazhdan_from_sgap(sgap, length(sett.S)) Kazhdan_κ = Float64(trunc(Kazhdan_κ, 12)) info(LOGGER, "κ($(sett.name), S) ≥ $Kazhdan_κ: Group HAS property (T)!") return true - else - sgap = Float64(trunc(sgap, 12)) - info(LOGGER, "λ($(sett.name), S) ≥ $sgap: Group may NOT HAVE property (T)!") - return false - end - end - info(LOGGER, "κ($(sett.name), S) ≥ $λ < 0: Tells us nothing about property (T)") - return false + else + sgap = Float64(trunc(sgap, 12)) + info(LOGGER, "λ($(sett.name), S) ≥ $sgap: Group may NOT HAVE property (T)!") + return false + end + end + info(LOGGER, "κ($(sett.name), S) ≥ $λ < 0: Tells us nothing about property (T)") + return false end diff --git a/src/OrbitDecomposition.jl b/src/OrbitDecomposition.jl index 1c5d357..93a122b 100644 --- a/src/OrbitDecomposition.jl +++ b/src/OrbitDecomposition.jl @@ -57,7 +57,7 @@ function orbit_decomposition(G::Nemo.Group, E::Vector, rdict=GroupRings.reverse_ orbit = zeros(Int, length(elts)) a = E[i] Threads.@threads for i in 1:length(elts) - orbit[i] = rdict[elts[i](a)] + orbit[i] = rdict[elts[i](a)] end tovisit[orbit] = false push!(orbits, unique(orbit)) @@ -110,110 +110,110 @@ function matrix_reps{T<:GroupElem}(preps::Dict{T,perm}) end function perm_repr(g::GroupElem, E::Vector, E_dict) - p = Vector{Int}(length(E)) - for (i,elt) in enumerate(E) - p[i] = E_dict[g(elt)] - end - return p + p = Vector{Int}(length(E)) + for (i,elt) in enumerate(E) + p[i] = E_dict[g(elt)] + end + return p end function perm_reps(G::Group, E::Vector, E_rdict=GroupRings.reverse_dict(E)) - elts = collect(elements(G)) - l = length(elts) - preps = Vector{Generic.perm}(l) + elts = collect(elements(G)) + l = length(elts) + preps = Vector{Generic.perm}(l) - permG = Nemo.PermutationGroup(length(E)) + permG = Nemo.PermutationGroup(length(E)) - Threads.@threads for i in 1:l - preps[i] = permG(PropertyT.perm_repr(elts[i], E, E_rdict)) - end + Threads.@threads for i in 1:l + preps[i] = permG(PropertyT.perm_repr(elts[i], E, E_rdict)) + end - return Dict(elts[i]=>preps[i] for i in 1:l) + return Dict(elts[i]=>preps[i] for i in 1:l) end function perm_reps(S::Vector, autS::Group, radius::Int) - E, _ = Groups.generate_balls(S, radius=radius) - return perm_reps(autS, E) + E, _ = Groups.generate_balls(S, radius=radius) + return perm_reps(autS, E) end function reconstruct_sol{T<:GroupElem, S<:perm}(preps::Dict{T, S}, - Us::Vector, Ps::Vector, dims::Vector) + Us::Vector, Ps::Vector, dims::Vector) - l = length(Us) - transfP = [dims[π].*Us[π]*Ps[π]*Us[π]' for π in 1:l] - tmp = [zeros(Float64, size(first(transfP))) for _ in 1:l] - perms = collect(keys(preps)) + l = length(Us) + transfP = [dims[π].*Us[π]*Ps[π]*Us[π]' for π in 1:l] + tmp = [zeros(Float64, size(first(transfP))) for _ in 1:l] + perms = collect(keys(preps)) - @inbounds Threads.@threads for π in 1:l - for p in perms - BLAS.axpy!(1.0, view(transfP[π], preps[p].d, preps[p].d), tmp[π]) - end - end + @inbounds Threads.@threads for π in 1:l + for p in perms + BLAS.axpy!(1.0, view(transfP[π], preps[p].d, preps[p].d), tmp[π]) + end + end - recP = 1/length(perms) .* sum(tmp) - recP[abs.(recP) .< eps(eltype(recP))] = zero(eltype(recP)) - return recP + recP = 1/length(perms) .* sum(tmp) + recP[abs.(recP) .< eps(eltype(recP))] = zero(eltype(recP)) + return recP end function Cstar_repr(x::GroupRingElem{T}, mreps::Dict) where {T} - return sum(x[i].*mreps[parent(x).basis[i]] for i in findn(x.coeffs)) + return sum(x[i].*mreps[parent(x).basis[i]] for i in findn(x.coeffs)) end function orthSVD{T}(M::AbstractMatrix{T}) - M = full(M) - fact = svdfact(M) - M_rank = sum(fact[:S] .> maximum(size(M))*eps(T)) - return fact[:U][:,1:M_rank] + M = full(M) + fact = svdfact(M) + M_rank = sum(fact[:S] .> maximum(size(M))*eps(T)) + return fact[:U][:,1:M_rank] end function compute_orbit_data{T<:GroupElem}(logger, name::String, G::Nemo.Group, S::Vector{T}, autS::Nemo.Group; radius=2) - isdir(name) || mkdir(name) + isdir(name) || mkdir(name) - info(logger, "Generating ball of radius $(2*radius)") + info(logger, "Generating ball of radius $(2*radius)") - # TODO: Fix that by multiple dispatch? - Id = (isa(G, Nemo.Ring) ? one(G) : G()) + # TODO: Fix that by multiple dispatch? + Id = (isa(G, Nemo.Ring) ? one(G) : G()) - @logtime logger E_2R, sizes = Groups.generate_balls(S, Id, radius=2*radius); - info(logger, "Balls of sizes $sizes.") - info(logger, "Reverse dict") - @logtime logger E_rdict = GroupRings.reverse_dict(E_2R) + @logtime logger E_2R, sizes = Groups.generate_balls(S, Id, radius=2*radius); + info(logger, "Balls of sizes $sizes.") + info(logger, "Reverse dict") + @logtime logger E_rdict = GroupRings.reverse_dict(E_2R) - info(logger, "Product matrix") - @logtime logger pm = GroupRings.create_pm(E_2R, E_rdict, sizes[radius], twisted=true) - RG = GroupRing(G, E_2R, E_rdict, pm) - Δ = PropertyT.splaplacian(RG, S) - @assert GroupRings.augmentation(Δ) == 0 - save(joinpath(name, "delta.jld"), "Δ", Δ.coeffs) - save(joinpath(name, "pm.jld"), "pm", pm) + info(logger, "Product matrix") + @logtime logger pm = GroupRings.create_pm(E_2R, E_rdict, sizes[radius], twisted=true) + RG = GroupRing(G, E_2R, E_rdict, pm) + Δ = PropertyT.splaplacian(RG, S) + @assert GroupRings.augmentation(Δ) == 0 + save(joinpath(name, "delta.jld"), "Δ", Δ.coeffs) + save(joinpath(name, "pm.jld"), "pm", pm) - info(logger, "Decomposing E into orbits of $(autS)") - @logtime logger orbs = orbit_decomposition(autS, E_2R, E_rdict) - @assert sum(length(o) for o in orbs) == length(E_2R) - info(logger, "E consists of $(length(orbs)) orbits!") - save(joinpath(name, "orbits.jld"), "orbits", orbs) + info(logger, "Decomposing E into orbits of $(autS)") + @logtime logger orbs = orbit_decomposition(autS, E_2R, E_rdict) + @assert sum(length(o) for o in orbs) == length(E_2R) + info(logger, "E consists of $(length(orbs)) orbits!") + save(joinpath(name, "orbits.jld"), "orbits", orbs) - info(logger, "Action matrices") - @logtime logger reps = perm_reps(autS, E_2R[1:sizes[radius]], E_rdict) - save_preps(joinpath(name, "preps.jld"), reps) - reps = matrix_reps(reps) + info(logger, "Action matrices") + @logtime logger reps = perm_reps(autS, E_2R[1:sizes[radius]], E_rdict) + save_preps(joinpath(name, "preps.jld"), reps) + reps = matrix_reps(reps) - info(logger, "Projections") - @logtime logger autS_mps = rankOne_projections(autS); + info(logger, "Projections") + @logtime logger autS_mps = rankOne_projections(autS); - @logtime logger π_E_projections = [Cstar_repr(p, reps) for p in autS_mps] + @logtime logger π_E_projections = [Cstar_repr(p, reps) for p in autS_mps] - info(logger, "Uπs...") - @logtime logger Uπs = orthSVD.(π_E_projections) + info(logger, "Uπs...") + @logtime logger Uπs = orthSVD.(π_E_projections) - multiplicities = size.(Uπs,2) - info(logger, "multiplicities = $multiplicities") - dimensions = [Int(p[autS()]*Int(order(autS))) for p in autS_mps]; - info(logger, "dimensions = $dimensions") - @assert dot(multiplicities, dimensions) == sizes[radius] + multiplicities = size.(Uπs,2) + info(logger, "multiplicities = $multiplicities") + dimensions = [Int(p[autS()]*Int(order(autS))) for p in autS_mps]; + info(logger, "dimensions = $dimensions") + @assert dot(multiplicities, dimensions) == sizes[radius] - save(joinpath(name, "U_pis.jld"), - "Uπs", Uπs, - "dims", dimensions) - return 0 + save(joinpath(name, "U_pis.jld"), + "Uπs", Uπs, + "dims", dimensions) + return 0 end diff --git a/src/Projections.jl b/src/Projections.jl index ae468d1..4506846 100644 --- a/src/Projections.jl +++ b/src/Projections.jl @@ -7,17 +7,17 @@ abstract type AbstractCharacter end struct PermCharacter <: AbstractCharacter - p::Generic.Partition + p::Generic.Partition end struct DirectProdCharacter <: AbstractCharacter - i::Int + i::Int end function (chi::PermCharacter)(g::Generic.perm) - R = Nemo.partitionseq(chi.p) - p = Partition(Nemo.Generic.permtype(g)) - return Int(Nemo.Generic.MN1inner(R, p, 1, Nemo.Generic._charvalsTable)) + R = Nemo.partitionseq(chi.p) + p = Partition(Nemo.Generic.permtype(g)) + return Int(Nemo.Generic.MN1inner(R, p, 1, Nemo.Generic._charvalsTable)) end Nemo.isone(p::GroupElem) = p == parent(p)() @@ -29,23 +29,23 @@ end ## NOTE: this works only for Z/2!!!! function (chi::DirectProdCharacter)(g::DirectProductGroupElem) - return reduce(*, 1, ((-1)^isone(g.elts[j]) for j in 1:chi.i)) + return reduce(*, 1, ((-1)^isone(g.elts[j]) for j in 1:chi.i)) end for T in [PermCharacter, DirectProdCharacter] - @eval begin - function (chi::$T)(X::GroupRingElem) - RG = parent(X) - z = zero(eltype(X)) - result = z - for i in 1:length(X.coeffs) - if X.coeffs[i] != z - result += chi(RG.basis[i])*X.coeffs[i] + @eval begin + function (chi::$T)(X::GroupRingElem) + RG = parent(X) + z = zero(eltype(X)) + result = z + for i in 1:length(X.coeffs) + if X.coeffs[i] != z + result += chi(RG.basis[i])*X.coeffs[i] + end end - end - return result - end - end + return result + end + end end ############################################################################### @@ -55,16 +55,16 @@ end ############################################################################### function central_projection(RG::GroupRing, chi::AbstractCharacter, T::Type=Rational{Int}) - result = RG(T) - result.coeffs = full(result.coeffs) - dim = chi(RG.group()) - ord = Int(order(RG.group)) + result = RG(T) + result.coeffs = full(result.coeffs) + dim = chi(RG.group()) + ord = Int(order(RG.group)) - for g in RG.basis - result[g] = convert(T, (dim//ord)*chi(g)) - end + for g in RG.basis + result[g] = convert(T, (dim//ord)*chi(g)) + end - return result + return result end function idempotents(RG::GroupRing{Generic.PermGroup}, T::Type=Rational{Int}) @@ -97,132 +97,132 @@ function idempotents(RG::GroupRing{Generic.PermGroup}, T::Type=Rational{Int}) end function rankOne_projection(chi::PropertyT.PermCharacter, - idems::Vector{T}) where {T<:GroupRingElem} + idems::Vector{T}) where {T<:GroupRingElem} - RG = parent(first(idems)) - S = eltype(first(idems)) + RG = parent(first(idems)) + S = eltype(first(idems)) - ids = [one(RG, S); idems] - zzz = zero(S) + ids = [one(RG, S); idems] + zzz = zero(S) - for (i,j,k) in Base.product(ids, ids, ids) - if chi(i) == zzz || chi(j) == zzz || chi(k) == zzz - continue - end - elt = i*j*k - elt^2 == elt || continue - if chi(elt) == one(S) - return elt - # return (i,j,k) - end - end - throw("Couldn't find rank-one projection for $chi") + for (i,j,k) in Base.product(ids, ids, ids) + if chi(i) == zzz || chi(j) == zzz || chi(k) == zzz + continue + end + elt = i*j*k + elt^2 == elt || continue + if chi(elt) == one(S) + return elt + # return (i,j,k) + end + end + throw("Couldn't find rank-one projection for $chi") end function rankOne_projections(G::Generic.PermGroup, T::Type=Rational{Int}) - if G.n == 1 - return [one(GroupRing(G), T)] - elseif G.n < 8 - RG = GroupRing(G, fastm=true) - else - RG = GroupRing(G, fastm=false) - end + if G.n == 1 + return [one(GroupRing(G), T)] + elseif G.n < 8 + RG = GroupRing(G, fastm=true) + else + RG = GroupRing(G, fastm=false) + end - RGidems = idempotents(RG, T) - l = length(Partitions(G.n)) + RGidems = idempotents(RG, T) + l = length(Partitions(G.n)) - parts = collect(Partitions(G.n)) - chars = [PropertyT.PermCharacter(p) for p in parts] - min_projs = Vector{eltype(RGidems)}(l) + parts = collect(Partitions(G.n)) + chars = [PropertyT.PermCharacter(p) for p in parts] + min_projs = Vector{eltype(RGidems)}(l) - for i in 1:l - chi = PropertyT.PermCharacter(parts[i]) - min_projs[i] = rankOne_projection(chi,RGidems)*central_projection(RG,chi) - end + for i in 1:l + chi = PropertyT.PermCharacter(parts[i]) + min_projs[i] = rankOne_projection(chi,RGidems)*central_projection(RG,chi) + end - return min_projs + return min_projs end function rankOne_projections(BN::WreathProduct, T::Type=Rational{Int}) - N = BN.P.n - # projections as elements of the group rings RSₙ - SNprojs_nc = [rankOne_projections(PermutationGroup(i)) for i in 1:N] + N = BN.P.n + # projections as elements of the group rings RSₙ + SNprojs_nc = [rankOne_projections(PermutationGroup(i)) for i in 1:N] - # embedding into group ring of BN - RBN = GroupRing(BN) - RFFFF_projs = [central_projection(GroupRing(BN.N), DirectProdCharacter(i),T) - for i in 1:BN.P.n] + # embedding into group ring of BN + RBN = GroupRing(BN) + RFFFF_projs = [central_projection(GroupRing(BN.N), DirectProdCharacter(i),T) + for i in 1:BN.P.n] - e0 = central_projection(GroupRing(BN.N), DirectProdCharacter(0), T) - Q0 = RBN(e0, g -> BN(g)) - Qs = [RBN(q, g -> BN(g)) for q in RFFFF_projs] + e0 = central_projection(GroupRing(BN.N), DirectProdCharacter(0), T) + Q0 = RBN(e0, g -> BN(g)) + Qs = [RBN(q, g -> BN(g)) for q in RFFFF_projs] - all_projs = [Q0*RBN(p, g->BN(g)) for p in SNprojs_nc[N]] + all_projs = [Q0*RBN(p, g->BN(g)) for p in SNprojs_nc[N]] - range = collect(1:N) - for i in 1:N-1 - first_emb = g->BN(Nemo.Generic.emb!(BN.P(), g, range[1:i])) - last_emb = g->BN(Nemo.Generic.emb!(BN.P(), g, range[i+1:end])) + range = collect(1:N) + for i in 1:N-1 + first_emb = g->BN(Nemo.Generic.emb!(BN.P(), g, range[1:i])) + last_emb = g->BN(Nemo.Generic.emb!(BN.P(), g, range[i+1:end])) - Sk_first = [RBN(p, first_emb) for p in SNprojs_nc[i]] - Sk_last = [RBN(p, last_emb) for p in SNprojs_nc[N-i]] + Sk_first = [RBN(p, first_emb) for p in SNprojs_nc[i]] + Sk_last = [RBN(p, last_emb) for p in SNprojs_nc[N-i]] - append!(all_projs, - [Qs[i]*p1*p2 for (p1,p2) in Base.product(Sk_first,Sk_last)]) - end + append!(all_projs, + [Qs[i]*p1*p2 for (p1,p2) in Base.product(Sk_first,Sk_last)]) + end - append!(all_projs, [Qs[N]*RBN(p, g->BN(g)) for p in SNprojs_nc[N]]) + append!(all_projs, [Qs[N]*RBN(p, g->BN(g)) for p in SNprojs_nc[N]]) - return all_projs -end + return all_projs + end -############################################################################## -# -# General Groups Misc -# -############################################################################## + ############################################################################## + # + # General Groups Misc + # + ############################################################################## -doc""" + doc""" products(X::Vector{GroupElem}, Y::Vector{GroupElem}, op=*) -> Returns a vector of all possible products (or `op(x,y)`), where $x\in X$ and -> $y\in Y$ are group elements. You may specify which operation is used when -> forming 'products' by adding `op` (which is `*` by default). -""" -function products{T<:GroupElem}(X::AbstractVector{T}, Y::AbstractVector{T}, op=*) - result = Vector{T}() - seen = Set{T}() - for x in X - for y in Y - z = op(x,y) - if !in(z, seen) - push!(seen, z) - push!(result, z) - end - end - end - return result -end + > Returns a vector of all possible products (or `op(x,y)`), where $x\in X$ and + > $y\in Y$ are group elements. You may specify which operation is used when + > forming 'products' by adding `op` (which is `*` by default). + """ + function products{T<:GroupElem}(X::AbstractVector{T}, Y::AbstractVector{T}, op=*) + result = Vector{T}() + seen = Set{T}() + for x in X + for y in Y + z = op(x,y) + if !in(z, seen) + push!(seen, z) + push!(result, z) + end + end + end + return result + end -doc""" + doc""" generateGroup(gens::Vector{GroupElem}, r=2, Id=parent(first(gens))(), op=*) -> Produces all elements of a group generated by elements in `gens` in ball of -> radius `r` (word-length metric induced by `gens`). -> If `r(=2)` is specified the procedure will terminate after generating ball -> of radius `r` in the word-length metric induced by `gens`. -> The identity element `Id` and binary operation function `op` can be supplied -> to e.g. take advantage of additive group structure. -""" -function generateGroup{T<:GroupElem}(gens::Vector{T}, r=2, Id::T=parent(first(gens))(), op=*) - n = 0 - R = 1 - elts = gens - gens = [Id; gens] - while n ≠ length(elts) && R < r - # @show elts - R += 1 - n = length(elts) - elts = products(elts, gens, op) - end - return elts -end + > Produces all elements of a group generated by elements in `gens` in ball of + > radius `r` (word-length metric induced by `gens`). + > If `r(=2)` is specified the procedure will terminate after generating ball + > of radius `r` in the word-length metric induced by `gens`. + > The identity element `Id` and binary operation function `op` can be supplied + > to e.g. take advantage of additive group structure. + """ + function generateGroup{T<:GroupElem}(gens::Vector{T}, r=2, Id::T=parent(first(gens))(), op=*) + n = 0 + R = 1 + elts = gens + gens = [Id; gens] + while n ≠ length(elts) && R < r + # @show elts + R += 1 + n = length(elts) + elts = products(elts, gens, op) + end + return elts + end diff --git a/src/PropertyT.jl b/src/PropertyT.jl index a73cc45..6239b53 100644 --- a/src/PropertyT.jl +++ b/src/PropertyT.jl @@ -68,22 +68,20 @@ function time_string(elapsedtime, bytes, gctime, allocs) return str end -function exists(fname::String) - return isfile(fname) || islink(fname) -end +exists(fname::String) = isfile(fname) || islink(fname) function pmΔfilenames(prefix::String) - isdir(prefix) || mkdir(prefix) - pm_filename = joinpath(prefix, "pm.jld") - Δ_coeff_filename = joinpath(prefix, "delta.jld") - return pm_filename, Δ_coeff_filename + isdir(prefix) || mkdir(prefix) + pm_filename = joinpath(prefix, "pm.jld") + Δ_coeff_filename = joinpath(prefix, "delta.jld") + return pm_filename, Δ_coeff_filename end function λSDPfilenames(prefix::String) - isdir(prefix) || mkdir(prefix) - λ_filename = joinpath(prefix, "lambda.jld") - SDP_filename = joinpath(prefix, "SDPmatrix.jld") - return λ_filename, SDP_filename + isdir(prefix) || mkdir(prefix) + λ_filename = joinpath(prefix, "lambda.jld") + SDP_filename = joinpath(prefix, "SDPmatrix.jld") + return λ_filename, SDP_filename end function ΔandSDPconstraints(prefix::String, G::Group) @@ -100,12 +98,12 @@ function ΔandSDPconstraints(prefix::String, G::Group) end function ΔandSDPconstraints{T<:GroupElem}(name::String, S::Vector{T}, Id::T; radius::Int=2) - info(LOGGER, "Computing pm, Δ, sdp_constraints...") - Δ, sdp_constraints = ΔandSDPconstraints(S, Id, radius=radius) - pm_fname, Δ_fname = pmΔfilenames(name) - save(pm_fname, "pm", parent(Δ).pm) - save(Δ_fname, "Δ", Δ.coeffs) - return Δ, sdp_constraints + info(LOGGER, "Computing pm, Δ, sdp_constraints...") + Δ, sdp_constraints = ΔandSDPconstraints(S, Id, radius=radius) + pm_fname, Δ_fname = pmΔfilenames(name) + save(pm_fname, "pm", parent(Δ).pm) + save(Δ_fname, "Δ", Δ.coeffs) + return Δ, sdp_constraints end function ΔandSDPconstraints{T<:GroupElem}(S::Vector{T}, Id::T; radius::Int=2) @@ -148,27 +146,26 @@ function λandP(name::String, SDP_problem::JuMP.Model, varλ, varP, warmstart=fa handler.levels.x = LOGGER_SOLVER.levels LOGGER_SOLVER.handlers["solver_log"] = handler - if warmstart && isfile(joinpath(name, "warmstart.jld")) - ws = load(joinpath(name, "warmstart.jld"), "warmstart") - else - ws = nothing - end + if warmstart && isfile(joinpath(name, "warmstart.jld")) + ws = load(joinpath(name, "warmstart.jld"), "warmstart") + else + ws = nothing + end - λ, P, warmstart = compute_λandP(SDP_problem, varλ, varP, warmstart=ws) + λ, P, warmstart = compute_λandP(SDP_problem, varλ, varP, warmstart=ws) - delete!(LOGGER_SOLVER.handlers, "solver_log") + delete!(LOGGER_SOLVER.handlers, "solver_log") - λ_fname, P_fname = λSDPfilenames(name) - - if λ > 0 - save(λ_fname, "λ", λ) - save(P_fname, "P", P) - save(joinpath(name, "warmstart.jld"), "warmstart", warmstart) - else - throw(ErrorException("Solver did not produce a valid solution!: λ = $λ")) - end - return λ, P + λ_fname, P_fname = λSDPfilenames(name) + if λ > 0 + save(λ_fname, "λ", λ) + save(P_fname, "P", P) + save(joinpath(name, "warmstart.jld"), "warmstart", warmstart) + else + throw(ErrorException("Solver did not produce a valid solution!: λ = $λ")) + end + return λ, P end function fillfrominternal!(m::JuMP.Model, traits) @@ -311,50 +308,48 @@ function check_property_T(name::String, S, Id, solver, upper_bound, tol, radius) Δ, sdp_constraints = ΔandSDPconstraints(name, S, Id, radius=radius) end - if all(exists.(λSDPfilenames(name))) - λ, P = λandP(name) - else - info(LOGGER, "Creating SDP problem...") - SDP_problem, λ, P = create_SDP_problem(Δ, sdp_constraints, upper_bound=upper_bound) - JuMP.setsolver(SDP_problem, solver) + if all(exists.(λSDPfilenames(name))) + λ, P = λandP(name) + else + info(LOGGER, "Creating SDP problem...") + SDP_problem, λ, P = create_SDP_problem(Δ, sdp_constraints, upper_bound=upper_bound) + JuMP.setsolver(SDP_problem, solver) + λ, P = λandP(name, SDP_problem, λ, P) + end - λ, P = λandP(name, SDP_problem, λ, P) - end + info(LOGGER, "λ = $λ") + info(LOGGER, "sum(P) = $(sum(P))") + info(LOGGER, "maximum(P) = $(maximum(P))") + info(LOGGER, "minimum(P) = $(minimum(P))") - info(LOGGER, "λ = $λ") - info(LOGGER, "sum(P) = $(sum(P))") - info(LOGGER, "maximum(P) = $(maximum(P))") - info(LOGGER, "minimum(P) = $(minimum(P))") + if λ > 0 + pm_fname, Δ_fname = pmΔfilenames(name) + RG = GroupRing(parent(first(S)), load(pm_fname, "pm")) + Δ = GroupRingElem(load(Δ_fname, "Δ")[:, 1], RG) - if λ > 0 - pm_fname, Δ_fname = pmΔfilenames(name) - RG = GroupRing(parent(first(S)), load(pm_fname, "pm")) - Δ = GroupRingElem(load(Δ_fname, "Δ")[:, 1], RG) + isapprox(eigvals(P), abs(eigvals(P)), atol=tol) || + warn("The solution matrix doesn't seem to be positive definite!") + @logtime LOGGER Q = real(sqrtm(Symmetric(P))) - isapprox(eigvals(P), abs(eigvals(P)), atol=tol) || - warn("The solution matrix doesn't seem to be positive definite!") - # @assert P == Symmetric(P) - @logtime LOGGER Q = real(sqrtm(Symmetric(P))) - - sgap = distance_to_positive_cone(Δ, λ, Q, 2*radius, LOGGER) - if isa(sgap, Interval) - sgap = sgap.lo - end - if sgap > 0 - info(LOGGER, "λ ≥ $(Float64(trunc(sgap,12)))") - Kazhdan_κ = Kazhdan_from_sgap(sgap, length(S)) - Kazhdan_κ = Float64(trunc(Kazhdan_κ, 12)) - info(LOGGER, "κ($name, S) ≥ $Kazhdan_κ: Group HAS property (T)!") - return true - else - sgap = Float64(trunc(sgap, 12)) - info(LOGGER, "λ($name, S) ≥ $sgap: Group may NOT HAVE property (T)!") - return false - end - end - info(LOGGER, "κ($name, S) ≥ $λ < 0: Tells us nothing about property (T)") - return false + sgap = distance_to_positive_cone(Δ, λ, Q, 2*radius, LOGGER) + if isa(sgap, Interval) + sgap = sgap.lo + end + if sgap > 0 + info(LOGGER, "λ ≥ $(Float64(trunc(sgap,12)))") + Kazhdan_κ = Kazhdan_from_sgap(sgap, length(S)) + Kazhdan_κ = Float64(trunc(Kazhdan_κ, 12)) + info(LOGGER, "κ($name, S) ≥ $Kazhdan_κ: Group HAS property (T)!") + return true + else + sgap = Float64(trunc(sgap, 12)) + info(LOGGER, "λ($name, S) ≥ $sgap: Group may NOT HAVE property (T)!") + return false + end + end + info(LOGGER, "κ($name, S) ≥ $λ < 0: Tells us nothing about property (T)") + return false end include("SDPs.jl") From 923d892da061509b3d9b9b1669a59dd9931cf2d8 Mon Sep 17 00:00:00 2001 From: kalmarek Date: Mon, 1 Jan 2018 23:45:49 +0100 Subject: [PATCH 04/27] fix indentation, again --- src/CheckSolution.jl | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/CheckSolution.jl b/src/CheckSolution.jl index 768397c..7f74600 100644 --- a/src/CheckSolution.jl +++ b/src/CheckSolution.jl @@ -33,12 +33,11 @@ function compute_SOS(Q::AbstractArray, pm::Array{Int,2}, l::Int) @everywhere groupring_square = PropertyT.groupring_square result = @parallel (+) for i in 1:size(Q,2) - groupring_square(Q[:,i], l, pm) -end + groupring_square(Q[:,i], l, pm) + end -println("") + return result -return result end function compute_SOS(Q::AbstractArray, RG::GroupRing, l::Int) From 5918e20569e59fe4b297f88dbcffc4ac7e5c8cf9 Mon Sep 17 00:00:00 2001 From: kalmarek Date: Mon, 1 Jan 2018 23:48:17 +0100 Subject: [PATCH 05/27] replace distance_to_cone by distances_to_cone without logging --- src/CheckSolution.jl | 27 ++++----------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/src/CheckSolution.jl b/src/CheckSolution.jl index 7f74600..04aeedb 100644 --- a/src/CheckSolution.jl +++ b/src/CheckSolution.jl @@ -45,32 +45,13 @@ function compute_SOS(Q::AbstractArray, RG::GroupRing, l::Int) return GroupRingElem(result, RG) end -function distance_to_cone{T<:Interval}(elt::GroupRingElem, Q::AbstractArray{T,2}, wlen::Int) - SOS = compute_SOS(Q, parent(elt), length(elt.coeffs)) - SOS_diff = elt - SOS +function distances_to_cone(elt::GroupRingElem, wlen::Int) + ɛ_dist = GroupRings.augmentation(elt) - ɛ_dist = GroupRings.augmentation(SOS_diff) - info(LOGGER, "ɛ(∑ξᵢ*ξᵢ) ∈ $(ɛ_dist)") - - eoi_SOS_L1_dist = norm(SOS_diff,1) - info(LOGGER, "‖Δ² - λΔ - ∑ξᵢ*ξᵢ‖₁ ∈ $(eoi_SOS_L1_dist)") + eoi_SOS_L1_dist = norm(elt,1) dist = 2^(wlen-1)*eoi_SOS_L1_dist - return dist -end - -function distance_to_cone{T}(elt::GroupRingElem, Q::AbstractArray{T,2}, wlen::Int) - SOS = compute_SOS(Q, parent(elt), length(elt.coeffs)) - SOS_diff = elt - SOS - - ɛ_dist = GroupRings.augmentation(SOS_diff) - info(LOGGER, "ɛ(Δ² - λΔ - ∑ξᵢ*ξᵢ) ≈ $(@sprintf("%.10f", ɛ_dist))") - - eoi_SOS_L1_dist = norm(SOS_diff,1) - info(LOGGER, "‖Δ² - λΔ - ∑ξᵢ*ξᵢ‖₁ ≈ $(@sprintf("%.10f", eoi_SOS_L1_dist))") - - dist = 2^(wlen-1)*eoi_SOS_L1_dist - return dist + return dist, ɛ_dist, eoi_SOS_L1_dist end function augIdproj{T, I<:AbstractInterval}(S::Type{I}, Q::AbstractArray{T,2}) From b2f4360ef43da702a0337f9b8b8c99fd9857e6b6 Mon Sep 17 00:00:00 2001 From: kalmarek Date: Mon, 1 Jan 2018 23:49:27 +0100 Subject: [PATCH 06/27] distence_to_cone(...) where {T<:...} does all the logging --- src/CheckSolution.jl | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/CheckSolution.jl b/src/CheckSolution.jl index 04aeedb..76d134c 100644 --- a/src/CheckSolution.jl +++ b/src/CheckSolution.jl @@ -79,14 +79,42 @@ function augIdproj{T}(Q::AbstractArray{T,2}, logger) return Q end -function distance_to_positive_cone(Δ::GroupRingElem, λ, Q, wlen::Int, logger) +function distance_to_cone(elt::GroupRingElem, λ::T, Q::AbstractArray{T,2}, wlen::Int, logger) where {T<:AbstractFloat} + info(logger, "------------------------------------------------------------") info(logger, "λ = $λ") info(logger, "Checking in floating-point arithmetic...") - Δ²_λΔ = EOI(Δ, λ) - @logtime logger fp_distance = λ - distance_to_cone(Δ²_λΔ, Q, wlen) - info(logger, "Floating point distance (to positive cone) ≈ $(@sprintf("%.10f", fp_distance))") + @logtime logger SOS_diff = elt - compute_SOS(Q, parent(elt), length(elt.coeffs)) + dist, ɛ_dist, eoi_SOS_L1_dist = distances_to_cone(SOS_diff, wlen) + info(logger, "ɛ(Δ² - λΔ - ∑ξᵢ*ξᵢ) ≈ $(@sprintf("%.10f", ɛ_dist))") + info(logger, "‖Δ² - λΔ - ∑ξᵢ*ξᵢ‖₁ ≈ $(@sprintf("%.10f", eoi_SOS_L1_dist))") + + fp_distance = λ - dist + + info(logger, "Floating point distance (to positive cone) ≈") + info(logger, "$(@sprintf("%.10f", fp_distance))") + info(logger, "") + + return fp_distance +end + +function distance_to_cone(elt::GroupRingElem, λ::T, Q::AbstractArray{T,2}, wlen::Int, logger) where {T<:AbstractInterval} info(logger, "------------------------------------------------------------") + info(logger, "λ = $λ") + info(logger, "Checking in interval arithmetic...") + @logtime logger SOS_diff = elt - compute_SOS(Q, parent(elt), length(elt.coeffs)) + dist, ɛ_dist, eoi_SOS_L1_dist = distances_to_cone(SOS_diff, wlen) + info(logger, "ɛ(∑ξᵢ*ξᵢ) ∈ $(ɛ_dist)") + info(logger, "‖Δ² - λΔ - ∑ξᵢ*ξᵢ‖₁ ∈ $(eoi_SOS_L1_dist)") + + int_distance = λ - dist + + info(logger, "The Augmentation-projected actual distance (to positive cone) ∈") + info(logger, "$(int_distance)") + info(logger, "") + + return int_distance +end if fp_distance ≤ 0 return fp_distance From 3066046fdb8efa1f10ea3abf6add02b503bfddb7 Mon Sep 17 00:00:00 2001 From: kalmarek Date: Mon, 1 Jan 2018 23:50:36 +0100 Subject: [PATCH 07/27] move checking logic to check_distance_to_cone function --- src/CheckSolution.jl | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/CheckSolution.jl b/src/CheckSolution.jl index 76d134c..5e8cde5 100644 --- a/src/CheckSolution.jl +++ b/src/CheckSolution.jl @@ -116,21 +116,19 @@ function distance_to_cone(elt::GroupRingElem, λ::T, Q::AbstractArray{T,2}, wlen return int_distance end +function check_distance_to_cone(Δ::GroupRingElem, λ, Q, wlen::Int, logger) + + fp_distance = distance_to_cone(EOI(Δ, λ), λ, Q, wlen, logger) + if fp_distance ≤ 0 return fp_distance end - info(logger, "") - Q = augIdproj(Q, logger) - - info(logger, "Checking in interval arithmetic") λ = @interval(λ) Δ = GroupRingElem([@interval(c) for c in Δ.coeffs], parent(Δ)) - Δ²_λΔ = EOI(Δ, λ) + Q = augIdproj(Q, logger) - @logtime logger Interval_dist_to_ΣSq = λ - distance_to_cone(Δ²_λΔ, Q, wlen) - info(logger, "The Augmentation-projected actual distance (to positive cone) ∈ $(Interval_dist_to_ΣSq)") - info(logger, "------------------------------------------------------------") + int_distance = distance_to_cone(EOI(Δ, λ), λ, Q, wlen, logger) - return Interval_dist_to_ΣSq + return int_distance.lo end From 7ac194f98a77a2d02f5de7609d27c7e3bc3c5dff Mon Sep 17 00:00:00 2001 From: kalmarek Date: Mon, 1 Jan 2018 23:54:36 +0100 Subject: [PATCH 08/27] fix logtime macro --- src/PropertyT.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PropertyT.jl b/src/PropertyT.jl index 6239b53..235744e 100644 --- a/src/PropertyT.jl +++ b/src/PropertyT.jl @@ -38,7 +38,7 @@ macro logtime(logger, ex) local diff = Base.GC_Diff(Base.gc_num(), stats) local ts = time_string(elapsedtime, diff.allocd, diff.total_time, Base.gc_alloc_count(diff)) - esc(info(logger, ts)) + $(esc(info))($(esc(logger)), ts) val end end From f48e8ba8d739cf9d81b0b574f49453209712f83a Mon Sep 17 00:00:00 2001 From: kalmarek Date: Mon, 1 Jan 2018 23:55:07 +0100 Subject: [PATCH 09/27] return the global logger for now --- src/PropertyT.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PropertyT.jl b/src/PropertyT.jl index 235744e..646126a 100644 --- a/src/PropertyT.jl +++ b/src/PropertyT.jl @@ -26,7 +26,7 @@ function setup_logging(name::String) e = redirect_stderr(logger.handlers["full_log"].io) - return logger + return LOGGER end macro logtime(logger, ex) From d5a4f4957a9261d7d5294cc1558f32252b0274ec Mon Sep 17 00:00:00 2001 From: kalmarek Date: Mon, 1 Jan 2018 23:57:03 +0100 Subject: [PATCH 10/27] rework filename logic --- src/Orbit-wise.jl | 10 +++++++--- src/PropertyT.jl | 47 ++++++++++++++++++++--------------------------- 2 files changed, 27 insertions(+), 30 deletions(-) diff --git a/src/Orbit-wise.jl b/src/Orbit-wise.jl index 352c4cf..0975d02 100644 --- a/src/Orbit-wise.jl +++ b/src/Orbit-wise.jl @@ -210,7 +210,7 @@ function λandP(m::JuMP.Model, data::OrbitData, sett::Settings) @logtime LOGGER recP = reconstruct_sol(preps, data.Us, Ps, data.dims) - fname = PropertyT.λSDPfilenames(fullpath(sett))[2] + fname = filename(fullpath(sett), :P) save(fname, "origP", Ps, "P", recP) return λ, recP end @@ -231,7 +231,10 @@ function check_property_T(sett::Settings) init_orbit_data(LOGGER, sett, radius=sett.radius) - if !sett.warmstart && all(isfile.(λSDPfilenames(fullpath(sett)))) + cond1 = exists(filename(fullpath(sett), :λ)) + cond2 = exists(filename(fullpath(sett), :P)) + + if !sett.warmstart && cond1 && cond2 λ, P = PropertyT.λandP(fullpath(sett)) else info(LOGGER, "Creating SDP problem...") @@ -247,7 +250,8 @@ function check_property_T(sett::Settings) info(LOGGER, "minimum(P) = $(minimum(P))") if λ > 0 - pm_fname, Δ_fname = pmΔfilenames(prepath(sett)) + pm_fname = filename(prepath(sett), :pm) + Δ_fname = filename(prepath(sett), :Δ) RG = GroupRing(sett.G, load(pm_fname, "pm")) Δ = GroupRingElem(load(Δ_fname, "Δ")[:, 1], RG) diff --git a/src/PropertyT.jl b/src/PropertyT.jl index 646126a..c7c4904 100644 --- a/src/PropertyT.jl +++ b/src/PropertyT.jl @@ -70,19 +70,15 @@ end exists(fname::String) = isfile(fname) || islink(fname) -function pmΔfilenames(prefix::String) +function filename(prefix, s::Symbol) isdir(prefix) || mkdir(prefix) - pm_filename = joinpath(prefix, "pm.jld") - Δ_coeff_filename = joinpath(prefix, "delta.jld") - return pm_filename, Δ_coeff_filename + return filename(prefix, Val{s}) end -function λSDPfilenames(prefix::String) - isdir(prefix) || mkdir(prefix) - λ_filename = joinpath(prefix, "lambda.jld") - SDP_filename = joinpath(prefix, "SDPmatrix.jld") - return λ_filename, SDP_filename -end +filename(prefix::String, ::Type{Val{:pm}}) = joinpath(prefix, "pm.jld") +filename(prefix::String, ::Type{Val{:Δ}}) = joinpath(prefix, "delta.jld") +filename(prefix::String, ::Type{Val{:λ}}) = joinpath(prefix, "lambda.jld") +filename(prefix::String, ::Type{Val{:P}}) = joinpath(prefix, "SDPmatrix.jld") function ΔandSDPconstraints(prefix::String, G::Group) info(LOGGER, "Loading precomputed pm, Δ, sdp_constraints...") @@ -123,16 +119,14 @@ function ΔandSDPconstraints{T<:GroupElem}(S::Vector{T}, Id::T; radius::Int=2) end function λandP(name::String) - λ_fname, SDP_fname = λSDPfilenames(name) - f₁ = exists(λ_fname) - f₂ = exists(SDP_fname) + λ_fname = filename(name, :λ) + P_fname = filename(name, :P) - if f₁ && f₂ - info(LOGGER, "Loading precomputed λ, P...") + if exists(λ_fname) && exists(P_fname) λ = load(λ_fname, "λ") - P = load(SDP_fname, "P") + P = load(P_fname, "P") else - throw(ArgumentError("You need to precompute λ and SDP matrix P to load it!")) + throw("You need to precompute $λ_fname and $P_fname to load it!") end return λ, P end @@ -156,14 +150,12 @@ function λandP(name::String, SDP_problem::JuMP.Model, varλ, varP, warmstart=fa delete!(LOGGER_SOLVER.handlers, "solver_log") - λ_fname, P_fname = λSDPfilenames(name) - if λ > 0 - save(λ_fname, "λ", λ) - save(P_fname, "P", P) + save(filename(name, :λ), "λ", λ) + save(filename(name, :P), "P", P) save(joinpath(name, "warmstart.jld"), "warmstart", warmstart) else - throw(ErrorException("Solver did not produce a valid solution!: λ = $λ")) + throw(ErrorException("Solver did not produce a valid solution: λ = $λ")) end return λ, P end @@ -300,7 +292,7 @@ function check_property_T(name::String, S, Id, solver, upper_bound, tol, radius) isdir(name) || mkdir(name) - if all(exists.(pmΔfilenames(name))) + if exists(filename(name, :pm)) && exists(filename(name, :Δ)) # cached Δ, sdp_constraints = ΔandSDPconstraints(name, parent(S[1])) else @@ -308,7 +300,8 @@ function check_property_T(name::String, S, Id, solver, upper_bound, tol, radius) Δ, sdp_constraints = ΔandSDPconstraints(name, S, Id, radius=radius) end - if all(exists.(λSDPfilenames(name))) + if exists(filename(name, :λ)) && exists(filename(name, :P)) + info(LOGGER, "Loading precomputed λ, P...") λ, P = λandP(name) else info(LOGGER, "Creating SDP problem...") @@ -324,9 +317,9 @@ function check_property_T(name::String, S, Id, solver, upper_bound, tol, radius) info(LOGGER, "minimum(P) = $(minimum(P))") if λ > 0 - pm_fname, Δ_fname = pmΔfilenames(name) - RG = GroupRing(parent(first(S)), load(pm_fname, "pm")) - Δ = GroupRingElem(load(Δ_fname, "Δ")[:, 1], RG) + + RG = GroupRing(parent(first(S)), load(filename(name, :pm), "pm")) + Δ = GroupRingElem(load(filename(name, :Δ), "Δ")[:, 1], RG) isapprox(eigvals(P), abs(eigvals(P)), atol=tol) || warn("The solution matrix doesn't seem to be positive definite!") From 523003cc2a5c685df32189116845270a76192455 Mon Sep 17 00:00:00 2001 From: kalmarek Date: Mon, 1 Jan 2018 23:59:31 +0100 Subject: [PATCH 11/27] move fillfrominternal! to SDPs.jl --- src/PropertyT.jl | 113 +++-------------------------------------------- src/SDPs.jl | 95 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 107 deletions(-) diff --git a/src/PropertyT.jl b/src/PropertyT.jl index c7c4904..c6f1a5a 100644 --- a/src/PropertyT.jl +++ b/src/PropertyT.jl @@ -160,120 +160,19 @@ function λandP(name::String, SDP_problem::JuMP.Model, varλ, varP, warmstart=fa return λ, P end -function fillfrominternal!(m::JuMP.Model, traits) - # Copied from JuMP/src/solvers.jl:178 - - stat::Symbol = MathProgBase.status(m.internalModel) - - numRows, numCols = length(m.linconstr), m.numCols - m.objBound = NaN - m.objVal = NaN - m.colVal = fill(NaN, numCols) - m.linconstrDuals = Array{Float64}(0) - - discrete = (traits.int || traits.sos) - - if stat == :Optimal - # If we think dual information might be available, try to get it - # If not, return an array of the correct length - if discrete - m.redCosts = fill(NaN, numCols) - m.linconstrDuals = fill(NaN, numRows) - else - if !traits.conic - m.redCosts = try - MathProgBase.getreducedcosts(m.internalModel)[1:numCols] - catch - fill(NaN, numCols) - end - - m.linconstrDuals = try - MathProgBase.getconstrduals(m.internalModel)[1:numRows] - catch - fill(NaN, numRows) - end - elseif !traits.qp && !traits.qc - JuMP.fillConicDuals(m) - end - end - else - # Problem was not solved to optimality, attempt to extract useful - # information anyway - - if traits.lin - if stat == :Infeasible - m.linconstrDuals = try - infray = MathProgBase.getinfeasibilityray(m.internalModel) - @assert length(infray) == numRows - infray - catch - suppress_warnings || warn("Infeasibility ray (Farkas proof) not available") - fill(NaN, numRows) - end - elseif stat == :Unbounded - m.colVal = try - unbdray = MathProgBase.getunboundedray(m.internalModel) - @assert length(unbdray) == numCols - unbdray - catch - suppress_warnings || warn("Unbounded ray not available") - fill(NaN, numCols) - end - end - end - # conic duals (currently, SOC and SDP only) - if !discrete && traits.conic && !traits.qp && !traits.qc - if stat == :Infeasible - JuMP.fillConicDuals(m) - end - end - end - - # If the problem was solved, or if it terminated prematurely, try - # to extract a solution anyway. This commonly occurs when a time - # limit or tolerance is set (:UserLimit) - if !(stat == :Infeasible || stat == :Unbounded) - try - # Do a separate try since getobjval could work while getobjbound does not and vice versa - objBound = MathProgBase.getobjbound(m.internalModel) + m.obj.aff.constant - m.objBound = objBound - end - try - objVal = MathProgBase.getobjval(m.internalModel) + m.obj.aff.constant - colVal = MathProgBase.getsolution(m.internalModel)[1:numCols] - # Rescale off-diagonal terms of SDP variables - if traits.sdp - offdiagvars = JuMP.offdiagsdpvars(m) - colVal[offdiagvars] /= sqrt(2) - end - # Don't corrupt the answers if one of the above two calls fails - m.objVal = objVal - m.colVal = colVal - end - end - - return stat -end - function compute_λandP(m, varλ, varP; warmstart=nothing) λ = 0.0 P = nothing traits = JuMP.ProblemTraits(m, relaxation=false) - while λ == 0.0 - try - JuMP.build(m, traits=traits) - if warmstart != nothing - p_sol, d_sol, s = warmstart - MathProgBase.SolverInterface.setwarmstart!(m.internalModel, p_sol; dual_sol = d_sol, slack=s); - end - solve_SDP(m) - λ = MathProgBase.getobjval(m.internalModel) - catch y - warn(LOGGER_SOLVER, y) - end + JuMP.build(m, traits=traits) + if warmstart != nothing + p_sol, d_sol, s = warmstart + MathProgBase.SolverInterface.setwarmstart!(m.internalModel, p_sol; dual_sol = d_sol, slack=s); end + solve_SDP(m) + λ = MathProgBase.getobjval(m.internalModel) warmstart = (m.internalModel.primal_sol, m.internalModel.dual_sol, m.internalModel.slack) diff --git a/src/SDPs.jl b/src/SDPs.jl index 1ab22b9..2fcb3dc 100644 --- a/src/SDPs.jl +++ b/src/SDPs.jl @@ -73,3 +73,98 @@ function solve_SDP(SDP_problem) return 0 end + +function fillfrominternal!(m::JuMP.Model, traits) + # Copied from JuMP/src/solvers.jl:178 + + stat::Symbol = MathProgBase.status(m.internalModel) + + numRows, numCols = length(m.linconstr), m.numCols + m.objBound = NaN + m.objVal = NaN + m.colVal = fill(NaN, numCols) + m.linconstrDuals = Array{Float64}(0) + + discrete = (traits.int || traits.sos) + + if stat == :Optimal + # If we think dual information might be available, try to get it + # If not, return an array of the correct length + if discrete + m.redCosts = fill(NaN, numCols) + m.linconstrDuals = fill(NaN, numRows) + else + if !traits.conic + m.redCosts = try + MathProgBase.getreducedcosts(m.internalModel)[1:numCols] + catch + fill(NaN, numCols) + end + + m.linconstrDuals = try + MathProgBase.getconstrduals(m.internalModel)[1:numRows] + catch + fill(NaN, numRows) + end + elseif !traits.qp && !traits.qc + JuMP.fillConicDuals(m) + end + end + else + # Problem was not solved to optimality, attempt to extract useful + # information anyway + + if traits.lin + if stat == :Infeasible + m.linconstrDuals = try + infray = MathProgBase.getinfeasibilityray(m.internalModel) + @assert length(infray) == numRows + infray + catch + suppress_warnings || warn("Infeasibility ray (Farkas proof) not available") + fill(NaN, numRows) + end + elseif stat == :Unbounded + m.colVal = try + unbdray = MathProgBase.getunboundedray(m.internalModel) + @assert length(unbdray) == numCols + unbdray + catch + suppress_warnings || warn("Unbounded ray not available") + fill(NaN, numCols) + end + end + end + # conic duals (currently, SOC and SDP only) + if !discrete && traits.conic && !traits.qp && !traits.qc + if stat == :Infeasible + JuMP.fillConicDuals(m) + end + end + end + + # If the problem was solved, or if it terminated prematurely, try + # to extract a solution anyway. This commonly occurs when a time + # limit or tolerance is set (:UserLimit) + if !(stat == :Infeasible || stat == :Unbounded) + try + # Do a separate try since getobjval could work while getobjbound does not and vice versa + objBound = MathProgBase.getobjbound(m.internalModel) + m.obj.aff.constant + m.objBound = objBound + end + try + objVal = MathProgBase.getobjval(m.internalModel) + m.obj.aff.constant + colVal = MathProgBase.getsolution(m.internalModel)[1:numCols] + # Rescale off-diagonal terms of SDP variables + if traits.sdp + offdiagvars = JuMP.offdiagsdpvars(m) + colVal[offdiagvars] /= sqrt(2) + end + # Don't corrupt the answers if one of the above two calls fails + m.objVal = objVal + m.colVal = colVal + end + end + + return stat +end From e5366b7305f8d69c47f73523c6e7281d73dd5ae4 Mon Sep 17 00:00:00 2001 From: kalmarek Date: Tue, 2 Jan 2018 00:01:24 +0100 Subject: [PATCH 12/27] decouple obtaining Delta from constraints --- src/PropertyT.jl | 51 ++++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/src/PropertyT.jl b/src/PropertyT.jl index c6f1a5a..be2b477 100644 --- a/src/PropertyT.jl +++ b/src/PropertyT.jl @@ -80,42 +80,37 @@ filename(prefix::String, ::Type{Val{:Δ}}) = joinpath(prefix, "delta.jld") filename(prefix::String, ::Type{Val{:λ}}) = joinpath(prefix, "lambda.jld") filename(prefix::String, ::Type{Val{:P}}) = joinpath(prefix, "SDPmatrix.jld") -function ΔandSDPconstraints(prefix::String, G::Group) - info(LOGGER, "Loading precomputed pm, Δ, sdp_constraints...") - pm_fname, Δ_fname = pmΔfilenames(prefix) - - product_matrix = load(pm_fname, "pm") - sdp_constraints = constraints(product_matrix) - - RG = GroupRing(G, product_matrix) - Δ = GroupRingElem(load(Δ_fname, "Δ")[:, 1], RG) - - return Δ, sdp_constraints +function Delta(name::String, G::Group) + info(LOGGER, "Loading precomputed Δ...") + if exists(filename(name, :Δ)) && exists(filename(name, :pm)) + RG = GroupRing(G, load(filename(name, :pm), "pm")) + Δ = GroupRingElem(load(filename(name, :Δ), "Δ")[:, 1], RG) + else + throw("You need to precompute $(filename(name, :pm)) and $(filename(name, :Δ)) to load it!") + end + return Δ end -function ΔandSDPconstraints{T<:GroupElem}(name::String, S::Vector{T}, Id::T; radius::Int=2) - info(LOGGER, "Computing pm, Δ, sdp_constraints...") - Δ, sdp_constraints = ΔandSDPconstraints(S, Id, radius=radius) - pm_fname, Δ_fname = pmΔfilenames(name) - save(pm_fname, "pm", parent(Δ).pm) - save(Δ_fname, "Δ", Δ.coeffs) - return Δ, sdp_constraints +function Delta{T<:GroupElem}(name::String, S::Vector{T}, Id::T; radius::Int=2) + info(LOGGER, "Computing multiplication table, Δ...") + Δ = Delta(S, Id, radius=radius) + save(filename(name, :pm), "pm", parent(Δ).pm) + save(filename(name, :Δ), "Δ", Δ.coeffs) + return Δ end -function ΔandSDPconstraints{T<:GroupElem}(S::Vector{T}, Id::T; radius::Int=2) - info(LOGGER, "Generating balls of sizes $sizes") +function Delta{T<:GroupElem}(S::Vector{T}, Id::T; radius::Int=2) + info(LOGGER, "Generating metric ball of radius $radius...") @logtime LOGGER E_R, sizes = Groups.generate_balls(S, Id, radius=2*radius) + info(LOGGER, "Generated balls of sizes $sizes.") info(LOGGER, "Creating product matrix...") @logtime LOGGER pm = GroupRings.create_pm(E_R, GroupRings.reverse_dict(E_R), sizes[radius]; twisted=true) - info(LOGGER, "Creating sdp_constratints...") - @logtime LOGGER sdp_constraints = PropertyT.constraints(pm) - RG = GroupRing(parent(Id), E_R, pm) Δ = splaplacian(RG, S) - return Δ, sdp_constraints + return Δ end function λandP(name::String) @@ -193,10 +188,10 @@ function check_property_T(name::String, S, Id, solver, upper_bound, tol, radius) if exists(filename(name, :pm)) && exists(filename(name, :Δ)) # cached - Δ, sdp_constraints = ΔandSDPconstraints(name, parent(S[1])) + Δ = Delta(name, parent(S[1])) else # compute - Δ, sdp_constraints = ΔandSDPconstraints(name, S, Id, radius=radius) + Δ = Delta(name, S, Id, radius=radius) end if exists(filename(name, :λ)) && exists(filename(name, :P)) @@ -204,10 +199,10 @@ function check_property_T(name::String, S, Id, solver, upper_bound, tol, radius) λ, P = λandP(name) else info(LOGGER, "Creating SDP problem...") - SDP_problem, λ, P = create_SDP_problem(Δ, sdp_constraints, upper_bound=upper_bound) + SDP_problem, λ_var, P_var = create_SDP_problem(Δ, PropertyT.constraints(parent(Δ).pm), upper_bound=upper_bound) JuMP.setsolver(SDP_problem, solver) - λ, P = λandP(name, SDP_problem, λ, P) + λ, P = λandP(name, SDP_problem, λ_var, P_var) end info(LOGGER, "λ = $λ") From b43482325d505f4d2f7b8edbf6ea2521e2ad6daa Mon Sep 17 00:00:00 2001 From: kalmarek Date: Tue, 2 Jan 2018 00:02:00 +0100 Subject: [PATCH 13/27] check_distance_to_cone returns single float --- src/PropertyT.jl | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/PropertyT.jl b/src/PropertyT.jl index be2b477..05d1872 100644 --- a/src/PropertyT.jl +++ b/src/PropertyT.jl @@ -219,10 +219,8 @@ function check_property_T(name::String, S, Id, solver, upper_bound, tol, radius) warn("The solution matrix doesn't seem to be positive definite!") @logtime LOGGER Q = real(sqrtm(Symmetric(P))) - sgap = distance_to_positive_cone(Δ, λ, Q, 2*radius, LOGGER) - if isa(sgap, Interval) - sgap = sgap.lo - end + sgap = check_distance_to_cone(Δ, λ, Q, 2*radius, LOGGER) + if sgap > 0 info(LOGGER, "λ ≥ $(Float64(trunc(sgap,12)))") Kazhdan_κ = Kazhdan_from_sgap(sgap, length(S)) From 13f49027dd90db29b91eb1a98bd7a9b9adfeb820 Mon Sep 17 00:00:00 2001 From: kalmarek Date: Tue, 2 Jan 2018 00:07:05 +0100 Subject: [PATCH 14/27] rename Delta -> Laplacian, splaplacian -> spLaplacian --- src/OrbitDecomposition.jl | 2 +- src/PropertyT.jl | 12 ++++++------ src/SDPs.jl | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/OrbitDecomposition.jl b/src/OrbitDecomposition.jl index 93a122b..bfffef2 100644 --- a/src/OrbitDecomposition.jl +++ b/src/OrbitDecomposition.jl @@ -182,7 +182,7 @@ function compute_orbit_data{T<:GroupElem}(logger, name::String, G::Nemo.Group, S info(logger, "Product matrix") @logtime logger pm = GroupRings.create_pm(E_2R, E_rdict, sizes[radius], twisted=true) RG = GroupRing(G, E_2R, E_rdict, pm) - Δ = PropertyT.splaplacian(RG, S) + Δ = PropertyT.spLaplacian(RG, S) @assert GroupRings.augmentation(Δ) == 0 save(joinpath(name, "delta.jld"), "Δ", Δ.coeffs) save(joinpath(name, "pm.jld"), "pm", pm) diff --git a/src/PropertyT.jl b/src/PropertyT.jl index 05d1872..9638d0b 100644 --- a/src/PropertyT.jl +++ b/src/PropertyT.jl @@ -80,7 +80,7 @@ filename(prefix::String, ::Type{Val{:Δ}}) = joinpath(prefix, "delta.jld") filename(prefix::String, ::Type{Val{:λ}}) = joinpath(prefix, "lambda.jld") filename(prefix::String, ::Type{Val{:P}}) = joinpath(prefix, "SDPmatrix.jld") -function Delta(name::String, G::Group) +function Laplacian(name::String, G::Group) info(LOGGER, "Loading precomputed Δ...") if exists(filename(name, :Δ)) && exists(filename(name, :pm)) RG = GroupRing(G, load(filename(name, :pm), "pm")) @@ -91,15 +91,15 @@ function Delta(name::String, G::Group) return Δ end -function Delta{T<:GroupElem}(name::String, S::Vector{T}, Id::T; radius::Int=2) +function Laplacian{T<:GroupElem}(name::String, S::Vector{T}, Id::T; radius::Int=2) info(LOGGER, "Computing multiplication table, Δ...") - Δ = Delta(S, Id, radius=radius) + Δ = Laplacian(S, Id, radius=radius) save(filename(name, :pm), "pm", parent(Δ).pm) save(filename(name, :Δ), "Δ", Δ.coeffs) return Δ end -function Delta{T<:GroupElem}(S::Vector{T}, Id::T; radius::Int=2) +function Laplacian{T<:GroupElem}(S::Vector{T}, Id::T; radius::Int=2) info(LOGGER, "Generating metric ball of radius $radius...") @logtime LOGGER E_R, sizes = Groups.generate_balls(S, Id, radius=2*radius) info(LOGGER, "Generated balls of sizes $sizes.") @@ -188,10 +188,10 @@ function check_property_T(name::String, S, Id, solver, upper_bound, tol, radius) if exists(filename(name, :pm)) && exists(filename(name, :Δ)) # cached - Δ = Delta(name, parent(S[1])) + Δ = Laplacian(name, parent(S[1])) else # compute - Δ = Delta(name, S, Id, radius=radius) + Δ = Laplacian(name, S, Id, radius=radius) end if exists(filename(name, :λ)) && exists(filename(name, :P)) diff --git a/src/SDPs.jl b/src/SDPs.jl index 2fcb3dc..c8439f0 100644 --- a/src/SDPs.jl +++ b/src/SDPs.jl @@ -13,7 +13,7 @@ function constraints(pm, total_length=maximum(pm)) return constraints end -function splaplacian(RG::GroupRing, S, T::Type=Float64) +function spLaplacian(RG::GroupRing, S, T::Type=Float64) result = RG(T) result[RG.group()] = T(length(S)) for s in S @@ -22,7 +22,7 @@ function splaplacian(RG::GroupRing, S, T::Type=Float64) return result end -function splaplacian{TT<:Ring}(RG::GroupRing{TT}, S, T::Type=Float64) +function spLaplacian{TT<:Ring}(RG::GroupRing{TT}, S, T::Type=Float64) result = RG(T) result[one(RG.group)] = T(length(S)) for s in S From 0d17e4b877f3ca1708cdf3cdeb3b61c9d189fe8e Mon Sep 17 00:00:00 2001 From: kalmarek Date: Tue, 2 Jan 2018 02:52:45 +0100 Subject: [PATCH 15/27] rework lambdaandP && solve_SDP --- src/PropertyT.jl | 53 ++++++++++++++---------------------------------- src/SDPs.jl | 32 +++++++++++++++++------------ 2 files changed, 34 insertions(+), 51 deletions(-) diff --git a/src/PropertyT.jl b/src/PropertyT.jl index 9638d0b..46607bb 100644 --- a/src/PropertyT.jl +++ b/src/PropertyT.jl @@ -126,60 +126,37 @@ function λandP(name::String) return λ, P end -function λandP(name::String, SDP_problem::JuMP.Model, varλ, varP, warmstart=false) +function λandP(name::String, SDP::JuMP.Model, varλ, varP, warmstart=true) - handler = DefaultHandler( - joinpath(name, "solver_$(string(now())).log"), - DefaultFormatter("{date}| {msg}") - ) - handler.levels.x = LOGGER_SOLVER.levels - LOGGER_SOLVER.handlers["solver_log"] = handler - - if warmstart && isfile(joinpath(name, "warmstart.jld")) - ws = load(joinpath(name, "warmstart.jld"), "warmstart") + if warmstart && isfile(filename(name, :warm)) + ws = load(filename(name, :warm), "warmstart") else ws = nothing end - λ, P, warmstart = compute_λandP(SDP_problem, varλ, varP, warmstart=ws) + solver_log = solverlogger(name) - delete!(LOGGER_SOLVER.handlers, "solver_log") + Base.Libc.flush_cstdio() + o = redirect_stdout(solver_log.handlers["solver_log"].io) + Base.Libc.flush_cstdio() + + λ, P, warmstart = solve_SDP(SDP, varλ, varP, warmstart=ws) + + Base.Libc.flush_cstdio() + redirect_stdout(o) + + delete!(solver_log.handlers, "solver_log") if λ > 0 save(filename(name, :λ), "λ", λ) save(filename(name, :P), "P", P) - save(joinpath(name, "warmstart.jld"), "warmstart", warmstart) + save(filename(name, :warm), "warmstart", warmstart) else throw(ErrorException("Solver did not produce a valid solution: λ = $λ")) end return λ, P end -function compute_λandP(m, varλ, varP; warmstart=nothing) - λ = 0.0 - P = nothing - - traits = JuMP.ProblemTraits(m, relaxation=false) - - JuMP.build(m, traits=traits) - if warmstart != nothing - p_sol, d_sol, s = warmstart - MathProgBase.SolverInterface.setwarmstart!(m.internalModel, p_sol; dual_sol = d_sol, slack=s); - end - solve_SDP(m) - λ = MathProgBase.getobjval(m.internalModel) - - warmstart = (m.internalModel.primal_sol, m.internalModel.dual_sol, - m.internalModel.slack) - - fillfrominternal!(m, traits) - - P = JuMP.getvalue(varP) - λ = JuMP.getvalue(varλ) - - return λ, P, warmstart -end - Kazhdan_from_sgap(λ,N) = sqrt(2*λ/N) function check_property_T(name::String, S, Id, solver, upper_bound, tol, radius) diff --git a/src/SDPs.jl b/src/SDPs.jl index c8439f0..9c9275e 100644 --- a/src/SDPs.jl +++ b/src/SDPs.jl @@ -55,23 +55,29 @@ function create_SDP_problem(Δ::GroupRingElem, matrix_constraints; upper_bound=I return m, λ, P end -function solve_SDP(SDP_problem) - info(LOGGER, Base.repr(SDP_problem)) +function solve_SDP(m, varλ, varP; warmstart=nothing) - o = redirect_stdout(LOGGER_SOLVER.handlers["solver_log"].io) - Base.Libc.flush_cstdio() + traits = JuMP.ProblemTraits(m, relaxation=false) - @logtime LOGGER solution_status = MathProgBase.optimize!(SDP_problem.internalModel) - Base.Libc.flush_cstdio() - - redirect_stdout(o) - - if solution_status != :Optimal - warn(LOGGER, "The solver did not solve the problem successfully!") + JuMP.build(m, traits=traits) + if warmstart != nothing + p_sol, d_sol, s = warmstart + MathProgBase.SolverInterface.setwarmstart!(m.internalModel, p_sol; dual_sol = d_sol, slack=s); end - info(LOGGER, solution_status) - return 0 + MathProgBase.optimize!(m.internalModel) + + λ = MathProgBase.getobjval(m.internalModel) + + warmstart = (m.internalModel.primal_sol, m.internalModel.dual_sol, + m.internalModel.slack) + + fillfrominternal!(m, traits) + + P = JuMP.getvalue(varP) + λ = JuMP.getvalue(varλ) + + return λ, P, warmstart end function fillfrominternal!(m::JuMP.Model, traits) From 7d22e8dce0730f62498b0abe988a035cfaa12d42 Mon Sep 17 00:00:00 2001 From: kalmarek Date: Tue, 2 Jan 2018 02:55:53 +0100 Subject: [PATCH 16/27] another rework of filenames --- src/Orbit-wise.jl | 12 ++++++------ src/OrbitDecomposition.jl | 6 +++--- src/PropertyT.jl | 27 +++++++++++++++++++-------- 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/Orbit-wise.jl b/src/Orbit-wise.jl index 0975d02..f11c33b 100644 --- a/src/Orbit-wise.jl +++ b/src/Orbit-wise.jl @@ -32,23 +32,23 @@ immutable OrbitData{T<:AbstractArray{Float64, 2}, LapType <:AbstractVector{Float end function OrbitData(sett::Settings) - splap = load(joinpath(prepath(sett), "delta.jld"), "Δ"); - pm = load(joinpath(prepath(sett), "pm.jld"), "pm"); + splap = load(filename(prepath(sett), :Δ), "Δ"); + pm = load(filename(prepath(sett), :pm), "pm"); cnstr = PropertyT.constraints(pm); splap² = similar(splap) splap² = GroupRings.mul!(splap², splap, splap, pm); - Uπs = load(joinpath(prepath(sett), "U_pis.jld"), "Uπs") + Uπs = load(filename(prepath(sett), :Uπs), "Uπs") nzros = [i for i in 1:length(Uπs) if size(Uπs[i],2) !=0] Uπs = Uπs[nzros] Uπs = sparsify!.(Uπs, sett.tol, check=true, verbose=true) #dimensions of the corresponding πs: - dims = load(joinpath(prepath(sett), "U_pis.jld"), "dims")[nzros] + dims = load(filename(prepath(sett), :Uπs), "dims")[nzros] m, P = init_model(size(Uπs,1), [size(U,2) for U in Uπs]); - orbits = load(joinpath(prepath(sett), "orbits.jld"), "orbits"); + orbits = load(filename(prepath(sett), :orb), "orbits"); n = size(Uπs[1],1) orb_spcnstrm = [orbit_constraint(cnstr[collect(orb)], n) for orb in orbits] orb_splap = orbit_spvector(splap, orbits) @@ -206,7 +206,7 @@ function λandP(m::JuMP.Model, data::OrbitData, sett::Settings) info(LOGGER, "Reconstructing P...") - preps = load_preps(joinpath(prepath(sett), "preps.jld"), sett.autS) + preps = load_preps(filename(prepath(sett), :preps), sett.autS) @logtime LOGGER recP = reconstruct_sol(preps, data.Us, Ps, data.dims) diff --git a/src/OrbitDecomposition.jl b/src/OrbitDecomposition.jl index bfffef2..2ad2e96 100644 --- a/src/OrbitDecomposition.jl +++ b/src/OrbitDecomposition.jl @@ -184,8 +184,8 @@ function compute_orbit_data{T<:GroupElem}(logger, name::String, G::Nemo.Group, S RG = GroupRing(G, E_2R, E_rdict, pm) Δ = PropertyT.spLaplacian(RG, S) @assert GroupRings.augmentation(Δ) == 0 - save(joinpath(name, "delta.jld"), "Δ", Δ.coeffs) - save(joinpath(name, "pm.jld"), "pm", pm) + save(filename(name, :Δ), "Δ", Δ.coeffs) + save(filename(name, :pm), "pm", pm) info(logger, "Decomposing E into orbits of $(autS)") @logtime logger orbs = orbit_decomposition(autS, E_2R, E_rdict) @@ -195,7 +195,7 @@ function compute_orbit_data{T<:GroupElem}(logger, name::String, G::Nemo.Group, S info(logger, "Action matrices") @logtime logger reps = perm_reps(autS, E_2R[1:sizes[radius]], E_rdict) - save_preps(joinpath(name, "preps.jld"), reps) + save_preps(filename(name, :preps), reps) reps = matrix_reps(reps) info(logger, "Projections") diff --git a/src/PropertyT.jl b/src/PropertyT.jl index 46607bb..97dbf59 100644 --- a/src/PropertyT.jl +++ b/src/PropertyT.jl @@ -70,15 +70,26 @@ end exists(fname::String) = isfile(fname) || islink(fname) -function filename(prefix, s::Symbol) - isdir(prefix) || mkdir(prefix) - return filename(prefix, Val{s}) -end +filename(prefix, s::Symbol) = filename(prefix, Val{s}) -filename(prefix::String, ::Type{Val{:pm}}) = joinpath(prefix, "pm.jld") -filename(prefix::String, ::Type{Val{:Δ}}) = joinpath(prefix, "delta.jld") -filename(prefix::String, ::Type{Val{:λ}}) = joinpath(prefix, "lambda.jld") -filename(prefix::String, ::Type{Val{:P}}) = joinpath(prefix, "SDPmatrix.jld") +@eval begin + for (s,n) in [ + [:pm, "pm.jld"], + [:Δ, "delta.jld"], + [:λ, "lambda.jld"], + [:P, "SDPmatrix.jld"], + [:warm, "warmstart.jld"], + [:Uπs, "U_pis.jld"], + [:orb, "orbits.jld"], + [:preps,"preps.jld"], + + [:logall, "full_$(string(now())).log"], + [:logsolver,"solver_$(string(now())).log"] + ] + + filename(prefix::String, ::Type{Val{$:(s)}}) = joinpath(prefix, :($n)) + end +end function Laplacian(name::String, G::Group) info(LOGGER, "Loading precomputed Δ...") From fd88de171b7d4b3cd9d09a09931d93b8dfaadbce Mon Sep 17 00:00:00 2001 From: kalmarek Date: Tue, 2 Jan 2018 02:59:10 +0100 Subject: [PATCH 17/27] get rid of global loggers --- src/PropertyT.jl | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/PropertyT.jl b/src/PropertyT.jl index 97dbf59..911ca64 100644 --- a/src/PropertyT.jl +++ b/src/PropertyT.jl @@ -12,21 +12,29 @@ using MathProgBase using Memento -const LOGGER = Memento.config("info", fmt="{msg}") -const LOGGER_SOLVER = Memento.config("info", fmt="{msg}") - function setup_logging(name::String) isdir(name) || mkdir(name) + L = Memento.config("info", fmt="{date}| {msg}") handler = Memento.DefaultHandler( - joinpath(name,"full_$(string((now()))).log"), Memento.DefaultFormatter("{date}| {msg}") - ) - handler.levels.x = LOGGER.levels - LOGGER.handlers["full_log"] = handler + filename(name, :logall), Memento.DefaultFormatter("{date}| {msg}")) - e = redirect_stderr(logger.handlers["full_log"].io) + handler.levels.x = L.levels + L.handlers["all"] = handler - return LOGGER + # e = redirect_stderr(L.handlers["all"].io) + + return L +end + +function solverlogger(name) + logger = Memento.config("info", fmt="{msg}") + + handler = DefaultHandler( + filename(name, :logsolver), DefaultFormatter("{date}| {msg}")) + handler.levels.x = logger.levels + logger.handlers["solver_log"] = handler + return logger end macro logtime(logger, ex) @@ -173,6 +181,7 @@ Kazhdan_from_sgap(λ,N) = sqrt(2*λ/N) function check_property_T(name::String, S, Id, solver, upper_bound, tol, radius) isdir(name) || mkdir(name) + LOGGER = Memento.getlogger() if exists(filename(name, :pm)) && exists(filename(name, :Δ)) # cached From 35615c34cf37a8586e511b87df59734ce8cdf46b Mon Sep 17 00:00:00 2001 From: kalmarek Date: Tue, 2 Jan 2018 03:02:22 +0100 Subject: [PATCH 18/27] logged and clean version of Laplacian --- src/PropertyT.jl | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/PropertyT.jl b/src/PropertyT.jl index 911ca64..1a02d64 100644 --- a/src/PropertyT.jl +++ b/src/PropertyT.jl @@ -100,7 +100,6 @@ filename(prefix, s::Symbol) = filename(prefix, Val{s}) end function Laplacian(name::String, G::Group) - info(LOGGER, "Loading precomputed Δ...") if exists(filename(name, :Δ)) && exists(filename(name, :pm)) RG = GroupRing(G, load(filename(name, :pm), "pm")) Δ = GroupRingElem(load(filename(name, :Δ), "Δ")[:, 1], RG) @@ -110,25 +109,19 @@ function Laplacian(name::String, G::Group) return Δ end -function Laplacian{T<:GroupElem}(name::String, S::Vector{T}, Id::T; radius::Int=2) - info(LOGGER, "Computing multiplication table, Δ...") - Δ = Laplacian(S, Id, radius=radius) - save(filename(name, :pm), "pm", parent(Δ).pm) - save(filename(name, :Δ), "Δ", Δ.coeffs) - return Δ -end +function Laplacian{T<:GroupElem}(S::Vector{T}, Id::T, + logger=getlogger(); radius::Int=2) -function Laplacian{T<:GroupElem}(S::Vector{T}, Id::T; radius::Int=2) - info(LOGGER, "Generating metric ball of radius $radius...") - @logtime LOGGER E_R, sizes = Groups.generate_balls(S, Id, radius=2*radius) - info(LOGGER, "Generated balls of sizes $sizes.") + info(logger, "Generating metric ball of radius $radius...") + @logtime logger E_R, sizes = Groups.generate_balls(S, Id, radius=2*radius) + info(logger, "Generated balls of sizes $sizes.") - info(LOGGER, "Creating product matrix...") - @logtime LOGGER pm = GroupRings.create_pm(E_R, GroupRings.reverse_dict(E_R), sizes[radius]; twisted=true) + info(logger, "Creating product matrix...") + @logtime logger pm = GroupRings.create_pm(E_R, GroupRings.reverse_dict(E_R), sizes[radius]; twisted=true) RG = GroupRing(parent(Id), E_R, pm) - Δ = splaplacian(RG, S) + Δ = spLaplacian(RG, S) return Δ end @@ -185,10 +178,13 @@ function check_property_T(name::String, S, Id, solver, upper_bound, tol, radius) if exists(filename(name, :pm)) && exists(filename(name, :Δ)) # cached + info(LOGGER, "Loading precomputed Δ...") Δ = Laplacian(name, parent(S[1])) else # compute - Δ = Laplacian(name, S, Id, radius=radius) + Δ = Laplacian(S, Id, LOGGER, radius=radius) + save(filename(name, :pm), "pm", parent(Δ).pm) + save(filename(name, :Δ), "Δ", Δ.coeffs) end if exists(filename(name, :λ)) && exists(filename(name, :P)) From a87b587c1a9a4392a4cc1d80c3419088825bea26 Mon Sep 17 00:00:00 2001 From: kalmarek Date: Tue, 2 Jan 2018 03:17:44 +0100 Subject: [PATCH 19/27] add logger field to sett --- src/Orbit-wise.jl | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/Orbit-wise.jl b/src/Orbit-wise.jl index f11c33b..0bd0942 100644 --- a/src/Orbit-wise.jl +++ b/src/Orbit-wise.jl @@ -14,6 +14,7 @@ immutable Settings{T<:AbstractMathProgSolver} upper_bound::Float64 tol::Float64 warmstart::Bool + logger end prefix(s::Settings) = s.name @@ -178,8 +179,8 @@ function init_model(n, sizes) end function create_SDP_problem(sett::Settings) - info(LOGGER, "Loading orbit data....") - @logtime LOGGER SDP_problem, orb_data = OrbitData(sett); + info(sett.logger, "Loading orbit data....") + @logtime sett.logger SDP_problem, orb_data = OrbitData(sett); if sett.upper_bound < Inf λ = JuMP.getvariable(SDP_problem, :λ) @@ -187,8 +188,8 @@ function create_SDP_problem(sett::Settings) end t = length(orb_data.laplacian) - info(LOGGER, "Adding $t constraints ... ") - @logtime LOGGER addconstraints!(SDP_problem, orb_data) + info(sett.logger, "Adding $t constraints ... ") + @logtime sett.logger addconstraints!(SDP_problem, orb_data) return SDP_problem, orb_data end @@ -201,14 +202,14 @@ function λandP(m::JuMP.Model, data::OrbitData, warmstart=true) end function λandP(m::JuMP.Model, data::OrbitData, sett::Settings) - info(LOGGER, "Solving SDP problem...") + info(sett.logger, "Solving SDP problem...") λ, Ps = λandP(m, data, sett.warmstart) - info(LOGGER, "Reconstructing P...") + info(sett.logger, "Reconstructing P...") preps = load_preps(filename(prepath(sett), :preps), sett.autS) - @logtime LOGGER recP = reconstruct_sol(preps, data.Us, Ps, data.dims) + @logtime sett.logger recP = reconstruct_sol(preps, data.Us, Ps, data.dims) fname = filename(fullpath(sett), :P) save(fname, "origP", Ps, "P", recP) @@ -237,17 +238,17 @@ function check_property_T(sett::Settings) if !sett.warmstart && cond1 && cond2 λ, P = PropertyT.λandP(fullpath(sett)) else - info(LOGGER, "Creating SDP problem...") + info(sett.logger, "Creating SDP problem...") SDP_problem, orb_data = create_SDP_problem(sett) JuMP.setsolver(SDP_problem, sett.solver) λ, P = λandP(SDP_problem, orb_data, sett) end - info(LOGGER, "λ = $λ") - info(LOGGER, "sum(P) = $(sum(P))") - info(LOGGER, "maximum(P) = $(maximum(P))") - info(LOGGER, "minimum(P) = $(minimum(P))") + info(sett.logger, "λ = $λ") + info(sett.logger, "sum(P) = $(sum(P))") + info(sett.logger, "maximum(P) = $(maximum(P))") + info(sett.logger, "minimum(P) = $(minimum(P))") if λ > 0 pm_fname = filename(prepath(sett), :pm) @@ -276,6 +277,6 @@ function check_property_T(sett::Settings) return false end end - info(LOGGER, "κ($(sett.name), S) ≥ $λ < 0: Tells us nothing about property (T)") + info(sett.logger, "κ($(sett.name), S) ≥ $λ < 0: Tells us nothing about property (T)") return false end From 955c8fc49edcec25ef80fb0e5765cca28ad8c693 Mon Sep 17 00:00:00 2001 From: kalmarek Date: Tue, 2 Jan 2018 03:19:57 +0100 Subject: [PATCH 20/27] remove init_orbit_data --- src/Orbit-wise.jl | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/src/Orbit-wise.jl b/src/Orbit-wise.jl index 0bd0942..3217272 100644 --- a/src/Orbit-wise.jl +++ b/src/Orbit-wise.jl @@ -104,19 +104,6 @@ end sparsify{T}(U::AbstractArray{T}, tol=eps(T); check=true, verbose=false) = sparsify!(deepcopy(U), tol, check=check, verbose=verbose) -function init_orbit_data(logger, sett::Settings; radius=2) - - ex(fname) = isfile(joinpath(prepath(sett), fname)) - - files_exists = ex.(["delta.jld", "pm.jld", "U_pis.jld", "orbits.jld", "preps.jld"]) - - if !all(files_exists) - compute_orbit_data(logger, prepath(sett), sett.G, sett.S, sett.autS, radius=radius) - end - - return 0 -end - function transform(U::AbstractArray, V::AbstractArray; sparse=true) if sparse return sparsify!(U'*V*U) @@ -230,7 +217,13 @@ end function check_property_T(sett::Settings) - init_orbit_data(LOGGER, sett, radius=sett.radius) + ex(s) = exists(filename(prepath(sett), s)) + + files_exists = ex.([:pm, :Δ, :Uπs, :orb, :preps]) + + if !all(files_exists) + compute_orbit_data(sett.logger, prepath(sett), sett.G, sett.S, sett.autS, radius=sett.radius) + end cond1 = exists(filename(fullpath(sett), :λ)) cond2 = exists(filename(fullpath(sett), :P)) From f478081d4e681ad3a9c33f4ef57d767d232ff762 Mon Sep 17 00:00:00 2001 From: kalmarek Date: Tue, 2 Jan 2018 03:22:46 +0100 Subject: [PATCH 21/27] reduce code duplication --- src/Orbit-wise.jl | 27 +++------------------------ src/PropertyT.jl | 47 ++++++++++++++++++++++++++--------------------- 2 files changed, 29 insertions(+), 45 deletions(-) diff --git a/src/Orbit-wise.jl b/src/Orbit-wise.jl index 3217272..f300cda 100644 --- a/src/Orbit-wise.jl +++ b/src/Orbit-wise.jl @@ -243,32 +243,11 @@ function check_property_T(sett::Settings) info(sett.logger, "maximum(P) = $(maximum(P))") info(sett.logger, "minimum(P) = $(minimum(P))") - if λ > 0 - pm_fname = filename(prepath(sett), :pm) - Δ_fname = filename(prepath(sett), :Δ) - RG = GroupRing(sett.G, load(pm_fname, "pm")) - Δ = GroupRingElem(load(Δ_fname, "Δ")[:, 1], RG) - - isapprox(eigvals(P), abs.(eigvals(P)), atol=sett.tol) || + isapprox(eigvals(P), abs.(eigvals(P)), atol=sett.tol) || warn("The solution matrix doesn't seem to be positive definite!") - # @assert P == Symmetric(P) - @logtime LOGGER Q = real(sqrtm(Symmetric(P))) - sgap = distance_to_positive_cone(Δ, λ, Q, 2*sett.radius, LOGGER) - if isa(sgap, Interval) - sgap = sgap.lo - end - if sgap > 0 - info(LOGGER, "λ ≥ $(Float64(trunc(sgap,12)))") - Kazhdan_κ = PropertyT.Kazhdan_from_sgap(sgap, length(sett.S)) - Kazhdan_κ = Float64(trunc(Kazhdan_κ, 12)) - info(LOGGER, "κ($(sett.name), S) ≥ $Kazhdan_κ: Group HAS property (T)!") - return true - else - sgap = Float64(trunc(sgap, 12)) - info(LOGGER, "λ($(sett.name), S) ≥ $sgap: Group may NOT HAVE property (T)!") - return false - end + if λ > 0 + return check_λ(sett.name, sett.S, λ, P, sett.radius, sett.logger) end info(sett.logger, "κ($(sett.name), S) ≥ $λ < 0: Tells us nothing about property (T)") return false diff --git a/src/PropertyT.jl b/src/PropertyT.jl index 1a02d64..5773e6c 100644 --- a/src/PropertyT.jl +++ b/src/PropertyT.jl @@ -171,6 +171,28 @@ end Kazhdan_from_sgap(λ,N) = sqrt(2*λ/N) +function check_λ(name, S, λ, P, radius, logger) + + RG = GroupRing(parent(first(S)), load(filename(name, :pm), "pm")) + Δ = GroupRingElem(load(filename(name, :Δ), "Δ")[:, 1], RG) + + @logtime logger Q = real(sqrtm(Symmetric(P))) + + sgap = check_distance_to_cone(Δ, λ, Q, 2*radius, logger) + + if sgap > 0 + info(logger, "λ ≥ $(Float64(trunc(sgap,12)))") + Kazhdan_κ = Kazhdan_from_sgap(sgap, length(S)) + Kazhdan_κ = Float64(trunc(Kazhdan_κ, 12)) + info(logger, "κ($name, S) ≥ $Kazhdan_κ: Group HAS property (T)!") + return true + else + sgap = Float64(trunc(sgap, 12)) + info(logger, "λ($name, S) ≥ $sgap: Group may NOT HAVE property (T)!") + return false + end +end + function check_property_T(name::String, S, Id, solver, upper_bound, tol, radius) isdir(name) || mkdir(name) @@ -203,28 +225,11 @@ function check_property_T(name::String, S, Id, solver, upper_bound, tol, radius) info(LOGGER, "maximum(P) = $(maximum(P))") info(LOGGER, "minimum(P) = $(minimum(P))") + isapprox(eigvals(P), abs.(eigvals(P)), atol=tol) || + warn("The solution matrix doesn't seem to be positive definite!") + if λ > 0 - - RG = GroupRing(parent(first(S)), load(filename(name, :pm), "pm")) - Δ = GroupRingElem(load(filename(name, :Δ), "Δ")[:, 1], RG) - - isapprox(eigvals(P), abs(eigvals(P)), atol=tol) || - warn("The solution matrix doesn't seem to be positive definite!") - @logtime LOGGER Q = real(sqrtm(Symmetric(P))) - - sgap = check_distance_to_cone(Δ, λ, Q, 2*radius, LOGGER) - - if sgap > 0 - info(LOGGER, "λ ≥ $(Float64(trunc(sgap,12)))") - Kazhdan_κ = Kazhdan_from_sgap(sgap, length(S)) - Kazhdan_κ = Float64(trunc(Kazhdan_κ, 12)) - info(LOGGER, "κ($name, S) ≥ $Kazhdan_κ: Group HAS property (T)!") - return true - else - sgap = Float64(trunc(sgap, 12)) - info(LOGGER, "λ($name, S) ≥ $sgap: Group may NOT HAVE property (T)!") - return false - end + return check_λ(name, S, λ, P, radius, logger) end info(LOGGER, "κ($name, S) ≥ $λ < 0: Tells us nothing about property (T)") return false From ac4ef92ef04ace635e3003e48f50baccee518e43 Mon Sep 17 00:00:00 2001 From: kalmarek Date: Tue, 2 Jan 2018 03:28:34 +0100 Subject: [PATCH 22/27] no need to pass both Group and S as arguments --- src/Orbit-wise.jl | 2 +- src/OrbitDecomposition.jl | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Orbit-wise.jl b/src/Orbit-wise.jl index f300cda..cc34a3c 100644 --- a/src/Orbit-wise.jl +++ b/src/Orbit-wise.jl @@ -222,7 +222,7 @@ function check_property_T(sett::Settings) files_exists = ex.([:pm, :Δ, :Uπs, :orb, :preps]) if !all(files_exists) - compute_orbit_data(sett.logger, prepath(sett), sett.G, sett.S, sett.autS, radius=sett.radius) + compute_orbit_data(sett.logger, prepath(sett), sett.S, sett.autS, radius=sett.radius) end cond1 = exists(filename(fullpath(sett), :λ)) diff --git a/src/OrbitDecomposition.jl b/src/OrbitDecomposition.jl index 2ad2e96..1b69e28 100644 --- a/src/OrbitDecomposition.jl +++ b/src/OrbitDecomposition.jl @@ -166,12 +166,13 @@ function orthSVD{T}(M::AbstractMatrix{T}) return fact[:U][:,1:M_rank] end -function compute_orbit_data{T<:GroupElem}(logger, name::String, G::Nemo.Group, S::Vector{T}, autS::Nemo.Group; radius=2) +function compute_orbit_data{T<:GroupElem}(logger, name::String, S::Vector{T}, autS::Nemo.Group; radius=2) isdir(name) || mkdir(name) info(logger, "Generating ball of radius $(2*radius)") # TODO: Fix that by multiple dispatch? + G = parent(first(S)) Id = (isa(G, Nemo.Ring) ? one(G) : G()) @logtime logger E_2R, sizes = Groups.generate_balls(S, Id, radius=2*radius); From f7534c2b97eae1dc41dd0b5714788163e09b6b98 Mon Sep 17 00:00:00 2001 From: kalmarek Date: Tue, 2 Jan 2018 03:32:04 +0100 Subject: [PATCH 23/27] logtime of lambdaandP; use LOGGER everywere --- src/PropertyT.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/PropertyT.jl b/src/PropertyT.jl index 5773e6c..b1c9881 100644 --- a/src/PropertyT.jl +++ b/src/PropertyT.jl @@ -214,10 +214,11 @@ function check_property_T(name::String, S, Id, solver, upper_bound, tol, radius) λ, P = λandP(name) else info(LOGGER, "Creating SDP problem...") - SDP_problem, λ_var, P_var = create_SDP_problem(Δ, PropertyT.constraints(parent(Δ).pm), upper_bound=upper_bound) + SDP_problem, varλ, varP = create_SDP_problem(Δ, constraints(parent(Δ).pm), upper_bound=upper_bound) JuMP.setsolver(SDP_problem, solver) + info(LOGGER, Base.repr(SDP_problem)) - λ, P = λandP(name, SDP_problem, λ_var, P_var) + @logtime LOGGER λ, P = λandP(name, SDP_problem, varλ, varP) end info(LOGGER, "λ = $λ") @@ -229,7 +230,7 @@ function check_property_T(name::String, S, Id, solver, upper_bound, tol, radius) warn("The solution matrix doesn't seem to be positive definite!") if λ > 0 - return check_λ(name, S, λ, P, radius, logger) + return check_λ(name, S, λ, P, radius, LOGGER) end info(LOGGER, "κ($name, S) ≥ $λ < 0: Tells us nothing about property (T)") return false From 6affa6876f899a5ef3bb3947f488eba5440af1b2 Mon Sep 17 00:00:00 2001 From: kalmarek Date: Tue, 2 Jan 2018 03:32:24 +0100 Subject: [PATCH 24/27] sparsify prints only to stdout --- src/Orbit-wise.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Orbit-wise.jl b/src/Orbit-wise.jl index cc34a3c..57f8a27 100644 --- a/src/Orbit-wise.jl +++ b/src/Orbit-wise.jl @@ -80,7 +80,7 @@ function sparsify!{Tv,Ti}(M::SparseMatrixCSC{Tv,Ti}, eps=eps(Tv); verbose=false) m = nnz(M) if verbose - info(LOGGER, "Sparsified density:", rpad(densM, 20), " → ", rpad(dens(M), 20)) + info("Sparsified density:", rpad(densM, 20), " → ", rpad(dens(M), 20)) end return M @@ -92,11 +92,11 @@ function sparsify!{T}(M::AbstractArray{T}, eps=eps(T); check=false, verbose=fals M[abs.(M) .< eps] .= zero(T) if check && rankM != rank(M) - warn(LOGGER, "Sparsification decreased the rank!") + warn("Sparsification decreased the rank!") end if verbose - info(LOGGER, "Sparsified density:", rpad(densM, 20), " → ", rpad(dens(M),20)) + info("Sparsified density:", rpad(densM, 20), " → ", rpad(dens(M),20)) end return sparse(M) From dc91735bfc80e4c21e146404c97829c4b1e54410 Mon Sep 17 00:00:00 2001 From: kalmarek Date: Tue, 2 Jan 2018 03:52:24 +0100 Subject: [PATCH 25/27] logtime of sdp solution; print the reresentation of SDP to log --- src/Orbit-wise.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Orbit-wise.jl b/src/Orbit-wise.jl index 57f8a27..aa9b20a 100644 --- a/src/Orbit-wise.jl +++ b/src/Orbit-wise.jl @@ -190,7 +190,7 @@ end function λandP(m::JuMP.Model, data::OrbitData, sett::Settings) info(sett.logger, "Solving SDP problem...") - λ, Ps = λandP(m, data, sett.warmstart) + @logtime sett.logger λ, Ps = λandP(m, data, sett.warmstart) info(sett.logger, "Reconstructing P...") @@ -234,6 +234,7 @@ function check_property_T(sett::Settings) info(sett.logger, "Creating SDP problem...") SDP_problem, orb_data = create_SDP_problem(sett) JuMP.setsolver(SDP_problem, sett.solver) + info(sett.logger, Base.repr(SDP_problem)) λ, P = λandP(SDP_problem, orb_data, sett) end From 46ac64a207dcb127eeec8c5073d5ab3f5e35b6e4 Mon Sep 17 00:00:00 2001 From: kalmarek Date: Tue, 2 Jan 2018 03:53:01 +0100 Subject: [PATCH 26/27] use the same directory structure as the orbit version --- src/PropertyT.jl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/PropertyT.jl b/src/PropertyT.jl index b1c9881..b72e8cb 100644 --- a/src/PropertyT.jl +++ b/src/PropertyT.jl @@ -209,16 +209,19 @@ function check_property_T(name::String, S, Id, solver, upper_bound, tol, radius) save(filename(name, :Δ), "Δ", Δ.coeffs) end - if exists(filename(name, :λ)) && exists(filename(name, :P)) + fullpath = joinpath(name, string(upper_bound)) + isdir(fullpath) || mkdir(fullpath) + + if exists(filename(fullpath, :λ)) && exists(filename(fullpath, :P)) info(LOGGER, "Loading precomputed λ, P...") - λ, P = λandP(name) + λ, P = λandP(fullpath) else info(LOGGER, "Creating SDP problem...") SDP_problem, varλ, varP = create_SDP_problem(Δ, constraints(parent(Δ).pm), upper_bound=upper_bound) JuMP.setsolver(SDP_problem, solver) info(LOGGER, Base.repr(SDP_problem)) - @logtime LOGGER λ, P = λandP(name, SDP_problem, varλ, varP) + @logtime LOGGER λ, P = λandP(fullpath, SDP_problem, varλ, varP) end info(LOGGER, "λ = $λ") From cb3c6a0ef5ec155b212fd2985b2847f39370ee20 Mon Sep 17 00:00:00 2001 From: kalmarek Date: Thu, 4 Jan 2018 20:13:41 +0100 Subject: [PATCH 27/27] better printing of lambda --- src/PropertyT.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PropertyT.jl b/src/PropertyT.jl index b72e8cb..87bc963 100644 --- a/src/PropertyT.jl +++ b/src/PropertyT.jl @@ -181,7 +181,7 @@ function check_λ(name, S, λ, P, radius, logger) sgap = check_distance_to_cone(Δ, λ, Q, 2*radius, logger) if sgap > 0 - info(logger, "λ ≥ $(Float64(trunc(sgap,12)))") + info(logger, "λ($name, S) ≥ $(Float64(trunc(sgap,12)))") Kazhdan_κ = Kazhdan_from_sgap(sgap, length(S)) Kazhdan_κ = Float64(trunc(Kazhdan_κ, 12)) info(logger, "κ($name, S) ≥ $Kazhdan_κ: Group HAS property (T)!")