fpylll icon indicating copy to clipboard operation
fpylll copied to clipboard

Loading strategies

Open SnarkBoojum opened this issue 3 years ago • 47 comments
trafficstars

After a from fpylll import *, load_strategies_json(BKZ.DEFAULT_STRATEGY) fails stating "Cannot open strategies file." ; because in fact it should be: load_strategies_json(BKZ.DEFAULT_STRATEGY_PATH + BKZ.DEFAULT_STRATEGY) or some such.

Notice that all of the comments/tests in the source point to the broken way ; only check_delta in src/fpylll/fplll/bkz_param.pyx tries to do the right thing by using strategy_full_path.

Arguably fplll's load_strategies_json should detect a relative filename and try to prepend its default path -- that would simplify matters.

SnarkBoojum avatar Feb 05 '22 08:02 SnarkBoojum

In sagemath, sage/src/sage/matrix/matrix_integer_dense.pyx, the line kwds["strategies"] = load_strategies_json(BKZ.DEFAULT_STRATEGY) is hence broken.

SnarkBoojum avatar Feb 05 '22 08:02 SnarkBoojum

Sigh. Since last release, I see it's now even worse! Commit a249d630debd8e96d536c37762f250d562aaec65 makes fpylll search for SAGE!? It's definitely an incorrect change: sagemath's fplll package should be configured so its DEFAULT_STRATEGY_PATH points to where default.json is installed, and fpylll should use just that!

SnarkBoojum avatar Feb 05 '22 09:02 SnarkBoojum

Indeed, there should be no fooling around with Sage/SAGE_LOCAL here, the strategies info is in /usr/include/fplll/fplll_config.h: see macros FPLLL_DEFAULT_STRATEGY_PATH and FPLLL_DEFAULT_STRATEGY (as @SnarkBoojum pointed out to me on a Debian list) so it's a matter for a simple (say) Cython function to get these value for fpylll. Although it could be even better to store them in fplll.pc- then it could be obtained from Python very easily.

dimpase avatar Feb 05 '22 09:02 dimpase

See #133

dimpase avatar Feb 05 '22 09:02 dimpase

@joerowell

dimpase avatar Feb 05 '22 09:02 dimpase

In fact, I think the best fix is a single-liner in fplll's load_strategies_json: std::ifstream fs(filename); in its source should become std::ifstream fs(strategy_full_path(filename));

SnarkBoojum avatar Feb 05 '22 12:02 SnarkBoojum

Reported on fplll here.

This issue on fpylll is now about purging the code from anything fancy about sagemath.

SnarkBoojum avatar Feb 05 '22 12:02 SnarkBoojum

Happy to purge the Sagemath stuff from here: the suggested idea seems much better (mea culpa!)

I can't replicate the bug on my Debian box, but I'll trust from the reports that it exists and go from there.

joerowell avatar Feb 05 '22 12:02 joerowell

to fix this in Sage, I opened https://trac.sagemath.org/ticket/33302

dimpase avatar Feb 06 '22 14:02 dimpase

In sagemath, sage/src/sage/matrix/matrix_integer_dense.pyx, the line kwds["strategies"] = load_strategies_json(BKZ.DEFAULT_STRATEGY) is hence broken.

I think this is probably the best place to fix this. The biggest problem here is the lack of documentation on fp(y)lll side - how are these values, BKZ.DEFAULT_STRATEGY and BKZ.DEFAULT_STRATEGY_PATH, formed? Are they just taking what's in the fplll header (macros FPLLL_DEFAULT_STRATEGY and FPLLL_DEFAULT_STRATEGY_PATH), and the latter are always correct (since some version of fplll)? Or it's something more complicated?

The fix suggested by @SnarkBoojum might be the best for Debian, but it's suboptimal for mutiplatform Python libaries fpylll and Sage, which might rely on pre-compiled fplll, IMHO.

dimpase avatar Feb 07 '22 12:02 dimpase

It's all quite messy. While talking about Debian 11's fplll, it's version 5.4.0, with FPLLL_DEFAULT_STRATEGY and FPLLL_DEFAULT_STRATEGY_PATH set to the correct path, and to default.json, respectively, in fplll/fplll_config.h. But on e.g. Fedora 34, there is fplll 5.4.1, and there are no such macros in fplll/fplll_config.h. Instead, these macros as in fplll/defs.h, and they are set to "". Somehow, on Fedora 34 in Sage 9.5, BKZ.DEFAULT_STRATEGY is getting set to the correct full path to default.json (in /usr/share/fplll/strategies).

How this is happening, is hard to say without knowing the corresponding change in fplll in 5.4.1.

dimpase avatar Feb 07 '22 12:02 dimpase

I'm trying to compile and run (with g++ foo.C -lfplll && ./a.out)

/* foo.C */
#include <iostream>
#include <fplll/fplll.h>
#include <fplll/bkz_param.h>
int main ()
{
std::cout << fplll::default_strategy_path() << "\n";
return 0;
}

on various systems. So on Fedora 34 (with unpatched (?) fplll 5.4.1) I get /usr/share/fplll/strategies, as it should be, even though this value is not in the headers anywhere. So it seems to be hardcoded during build time.

On Debian 11, with fplll 5.4.0, I get /usr/share/libfplll7/strategies/, as it should be, and this same value is in the headers.

dimpase avatar Feb 07 '22 13:02 dimpase

It's actually handled in fplll's Makefile.am, and I added a patch in Debian so it's versioned (make libfplll257 libfplll314 coinstallable). In 2017 according to git blame.

SnarkBoojum avatar Feb 07 '22 14:02 SnarkBoojum

It seems to be a good patch, why isn't it upstreamed? The current situation with the headers in 5.4.1 is confusing at best.

dimpase avatar Feb 07 '22 16:02 dimpase

Well, I forwarded it to upstream but it wasn't applied... perhaps you can propose again?

SnarkBoojum avatar Feb 07 '22 16:02 SnarkBoojum

One way or another, I don't see the point of having these two macros set to "" in the header. Either they should be removed there completely, or kept with meaningful values. But "meaningful values" in an un-versioned header only makes sense if there is just one version of libfplll installed --- this is something I don't get about your patch.

dimpase avatar Feb 07 '22 16:02 dimpase

There can be a singe libfplll-dev providing the headers at the same time, of course. But the binary packages will depend on the libfplll that was available at build-time.

If you have "foo" depending on libfplll6 and "bar" depending on libfplll7, then they can be installed at the same time because libfplll6 and libfplll7 care co-installable, and each can find its correct strategies file.

This is why my patch works.

SnarkBoojum avatar Feb 07 '22 20:02 SnarkBoojum

libfplll6 and libfplll7 are co-installable, and each can find its correct strategies file.

yes, but FPLLL_DEFAULT_STRATEGY* macros will only be correct for one of them.

dimpase avatar Feb 07 '22 20:02 dimpase

Those macros set the path at compile-time, while libfplll is a runtime dep. Link to the right one, run with the right one, find the right files. No problem.

SnarkBoojum avatar Feb 07 '22 20:02 SnarkBoojum

why are these macros needed in the header file at all?

dimpase avatar Feb 07 '22 20:02 dimpase

(Just to make sure I understand the state of this issue) is your argument:

  • that the macros could be placed elsewhere during building, or

  • that we shouldn't have the macros at all, and instead store this information differently?

Is there anything extra that needs to be done here for this? From what I can tell this looks like a building issue, which I'm inclined to look into as a fplll issue (rather than an fpylll issue).

On Mon, 7 Feb 2022, 20:52 Dima Pasechnik, @.***> wrote:

why are these macros needed in the header file at all?

— Reply to this email directly, view it on GitHub https://github.com/fplll/fpylll/issues/221#issuecomment-1031908963, or unsubscribe https://github.com/notifications/unsubscribe-auth/AF7CASBDQLJNHHRFJU4NGDTU2AWIRANCNFSM5NTVQXLQ . You are receiving this because you were assigned.Message ID: @.***>

joerowell avatar Feb 07 '22 21:02 joerowell

If fplll's api only allowed "load_strategies()", they wouldn't be needed.

But its "load_strategies(path + filename)", so the downstream developers need to access the default path and default filename to actually call that function with meaningful values.

SnarkBoojum avatar Feb 07 '22 21:02 SnarkBoojum

From C++ it's all available via concatenating fplll::default_strategy_path() and fplll::default_strategy(). The values are baked in at build time.

dimpase avatar Feb 07 '22 21:02 dimpase

to fix this in Sage, I opened https://trac.sagemath.org/ticket/33302

it's ready for review, please check.

dimpase avatar Feb 10 '22 17:02 dimpase

The patch looks fine, but it's not entirely satisfying for fpylll (if there's an issue with paths in fplll we should fix it across all systems). Still, it's good this will work for Sagemath.

@malb what do you think? I'm thinking of #133 primarily, but also the examples that @dimpase has brought up for e.g Fedora.

joerowell avatar Feb 10 '22 19:02 joerowell

I've just positively reviewed the Sage ticket. I've lost the plot, is there anything else we should do? Sorry and thanks all for your work on this!

malb avatar Feb 11 '22 11:02 malb

is there anything else we should do?

as long as you don't break what you have now regarding BKZ.DEFAULT_STRATEGY_PATH and BKZ.DEFAULT_STRATEGY, all is good and taken care of by the fix in Sage ticket.

dimpase avatar Feb 11 '22 14:02 dimpase

I wanted to upload the latest fpylll to Debian, but had to add this patch, because it insisted on looking at the wrong place:

--- fpylll.orig/src/fpylll/fplll/bkz_param.pyx
+++ fpylll/src/fpylll/fplll/bkz_param.pyx
@@ -26,7 +26,7 @@
 from fpylll.util cimport check_delta, check_pruner_metric
 from cython.operator cimport dereference as deref, preincrement as inc
 
-from fpylll.config import default_strategy
+from fpylll.config import default_strategy_path, default_strategy
 
 from .pruner cimport PruningParams
 
@@ -278,8 +278,8 @@
     #  catch. If it just so happens that we fail, we read the Sagemath environment variables and try
     #  to navigate to the default file relative to that directory.
 
-    if not path.exists(filename) and filename == "default.json":
-        filename = path.join(environ['SAGE_LOCAL'], 'fplll', 'strategies', 'default.json')
+    if not path.exists(filename):
+        filename = path.join(default_strategy_path, filename)
 
     if not path.exists(filename):
         raise FileNotFoundError("File '%s' not found."%filename)

SnarkBoojum avatar Oct 29 '22 05:10 SnarkBoojum

handling of default.json was seriously messed up, by too eager changes done by fpylll devs to fix upstream a Sage issue. I recall untangling it a while ago.

dimpase avatar Oct 29 '22 08:10 dimpase

of course it's an fpylll bug to assume that SAGE_LOCAL is always set.

dimpase avatar Oct 29 '22 08:10 dimpase