Giter VIP home page Giter VIP logo

proximal's People

Contributors

adler-j avatar antonysigma avatar gfacciol avatar grlee77 avatar hayatoikoma avatar stevediamond avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

proximal's Issues

Website can't be reached

Thanks for your wonderful works. But the website: proximal-lang.org can't be reached.

It shows an error: DNS_PROBE_FINISHED_NXDOMAIN

Could you check this?

Thank you!

set_ methods should be property setters

There are several instances of set_some_attribute in the code, this is considered a Python anti-pattern, see e.g. this and this stackoverflow thread. These should perhaps be changed to either a property + setter pair, e.g. like Variable.value currently does it:

@property
def value(self):
    return self._value

@value.setter
def value(self, val):
    """Assign a value to the variable.
    """
    self._value = val

or simply by removing the set_SOMEVARIABLE method and setting the attribute as usual: object.some_attribute = new_value.

Callback parameter for solvers

It is often of interest to inspect partial results of a solver, perhaps for debugging or for somehow displaying partial results.

The solvers in Scipy provides a solution to this in allowing users to pass a callable that is called with the current iterate, see e.g. scipy.optimize.minimize and scipy.optimize.fmin_bfgs. ODL does the same in all of its solvers and also provides some standardized callbacks, see odl.solvers.util.callback.

It would be nice if ProxImaL also had this functionality.

CompGraph class destructor not called

For my last project I had to perform an extensive hyperparameter optimisation during which I regularly ran out of memory. After spending some time to find the memory leak, I came across the CompGraph class which has a self reference cycle. Such a cycle prevents a class from being deleted.

The problem is the self injected into the other objects in those two lines:

self.forward_log = TimingsLog(self.nodes + [self])
self.adjoint_log = TimingsLog(self.nodes + [self])

To fix the problem I changed the code to [str(self)] which then only injects a string. Since there is generally only one computational graph, time logging stills works (exact object references should only be necessary for graph elements which appear more than once). But there is probably a more elegant way to resolve this issue.

Problem having 17 individual `sum_squares(conv(x))` takes too long to group/absorb. Image deconvolution with spatially varying PSFs

I'm trying to solve an implementation of the space-variant deconvolution algorithm presented in Flicker & Rigaut (2005) and reviewed here.

I have PSFs sampled over the field, which are centered and stacked in a matrix, of which we compute the SVD to get weights and kernels that form the low-rank approximation of the spatially varying blur forward model. (Image, im, weights, W, and kernels, U, are each vectors in R^n, n=1e7 (image of ~10million pixels)).

I construct my problem like so, but it is not able to return after 100s of minutes of runtime. It does not print any debug information either, despite the verbose flag, so I'm not sure what is going on.

P.S. I'm running Python 3.10.1 on a macOS Ventura on an M1 Max 64GB RAM

import proximal as px

def forward(im, G, W):
    for i in range(15):
        weight = W[i,:].reshape(*im.shape)
        psf_mode = G[:,i].reshape(*im.shape)
        im += px.conv(psf_mode, px.mul_elemwise(weight, im))
    return im

def cost_function(x, im, U, W, mu): 
    im_blur = forward(x, U, W)
    data_term = px.sum_squares(px.subsample(im_blur, steps=2) - im) 
    grad_term = mu*px.norm1(px.grad(im_blur)) + (1-mu)*px.sum_squares(px.grad(im_blur))
    return data_term + grad_term + px.nonneg(im_blur)

x = px.Variable(im.shape)
prob = px.Problem(cost_function(x, im, U, W, mu=0.01))
prob.solve(solver='pc', max_iters=2, verbose=True, x0=im.copy())

Can you please tell me:

  1. if I'm doing anything obviously wrong in setting up the problem?
  2. how should I get some debug info be printed to get a sense of where it's at in the optimization?

Compiler error in fft2_r2c.cpp

My compiler (MSVC) complains about WTARGET and HTARGET undeclared identifiers in fft2_r2c.cpp:

C:\WinPython\3.5.2.3-64bit-qt5\python-3.5.2.amd64\lib\site-packages\proximal\halide\src\fft2_r2c.cpp(52): error C2065: 'WTARGET': undeclared identifier
C:\WinPython\3.5.2.3-64bit-qt5\python-3.5.2.amd64\lib\site-packages\proximal\halide\src\fft2_r2c.cpp(52): error C2065: 'HTARGET': undeclared identifier
C:\WinPython\3.5.2.3-64bit-qt5\python-3.5.2.amd64\lib\site-packages\proximal\halide\src\fft2_r2c.cpp(56): error C2065: 'WTARGET': undeclared identifier
C:\WinPython\3.5.2.3-64bit-qt5\python-3.5.2.amd64\lib\site-packages\proximal\halide\src\fft2_r2c.cpp(56): error C2065: 'HTARGET': undeclared identifier

I didn't find references for these anywhere in the code, so I'm unsure about how to fix these.

Applying operators to input image

Sometimes, it is desirable to apply operators to the input image, e.g. in optical flow.

I cannot figure out if this is even possible. I tried defining e.g. (this functional makes no sense, its just supposed to be a minimum example).

I = imread(...) # read input picture
x = Variable(*I.shape)
prob = Problem( grad(I) - grad(x)) + sum_squares(v1)
prob.solve()

but I end up with some error because the problem contains grad(I). The actual error differs, depending on what I'm actually trying to do in my functional.

I know that I could substitute grad(I-x) above but that trick will not work for arbitrary combinations of the operators (I actually need something like sum_squares(mul_elemwise(grad(I,1),x))).

So I guess the big question is: Is it currently possible in proximal to define problems by applying operators to input images, or do I need to make the appropriate transformations by hand?

Thanks in advance :)

initializing subsample in 1d

Initializing a proximal.subsample in 1d seems to have harsher requirements on the input than for example Variable:

>>> x = proximal.Variable(4)
>>> proximal.subsample(x, 2)  # this fails
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "e:\github\proximal\proximal\lin_ops\subsample.py", line 12, in __init__
    shape = tuple([(dim - 1) // step + 1 for dim, step in zip(arg.shape, steps)])
TypeError: zip argument #2 must support iteration
>>> proximal.subsample(x, [2])  # this works

Using Halide implementation leads to 'undefined types' error

I tried to use the Halide implementation of proximal by setting implem=Impl['halide'] in the Problem class, but I got a lot of errors if I try to use the ADMM algorithm. With the Pock-Chambolle algorithm, everything seems to work fine.

Any ideas what might be the cause of this? The first lines of the log seems to suggest that proximal is using halide types that do not exist but I somehow doubt that that is the problem^^

Btw, halide on its own is working fine for me, but running grep -r FuncRefVar in the halide root directory does not yield any results.

I also tried changing the include-statements in funct.h to point directly to Halide.h (in case there was a search-path related problem, but that did not change the error output)

Estimated params [sigma = 1.000 | tau = 1.000 | theta = 1.000 | L_est = 1.0000]
0.0818989276886
In file included from /home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/complex.h:6:0,
                 from /home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/fft.h:14,
                 from /home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft2_r2c.cpp:11:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:11:5: error: ‘FuncRefVar’ in namespace ‘Halide’ does not name a type
     Halide::FuncRefVar untyped;
     ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:17:23: error: ‘FuncRefVar’ in namespace ‘Halide’ does not name a type
     FuncRefVarT(const Halide::FuncRefVar& untyped)
                       ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:17:43: error: ISO C++ forbids declaration of ‘untyped’ with no type [-fpermissive]
     FuncRefVarT(const Halide::FuncRefVar& untyped)
                                           ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h: In constructor ‘FuncRefVarT<T>::FuncRefVarT(const int&)’:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:18:21: error: request for member ‘function’ in ‘untyped’, which is of non-class type ‘const int’
         : T(untyped.function().has_pure_definition() ? T(Tuple(untyped)) : T()),
                     ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:19:13: error: class ‘FuncRefVarT<T>’ does not have any field named ‘untyped’
             untyped(untyped) {}
             ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h: In member function ‘FuncRefVarT<T>::Stage FuncRefVarT<T>::operator=(T)’:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:21:35: error: ‘untyped’ was not declared in this scope
     Stage operator=(T x) { return untyped = x; }
                                   ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h: In member function ‘FuncRefVarT<T>::Stage FuncRefVarT<T>::operator+=(T)’:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:22:36: error: ‘untyped’ was not declared in this scope
     Stage operator+=(T x) { return untyped = T(Tuple(untyped)) + x; }
                                    ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h: In member function ‘FuncRefVarT<T>::Stage FuncRefVarT<T>::operator-=(T)’:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:23:36: error: ‘untyped’ was not declared in this scope
     Stage operator-=(T x) { return untyped = T(Tuple(untyped)) - x; }
                                    ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h: In member function ‘FuncRefVarT<T>::Stage FuncRefVarT<T>::operator*=(T)’:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:24:36: error: ‘untyped’ was not declared in this scope
     Stage operator*=(T x) { return untyped = T(Tuple(untyped)) * x; }
                                    ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h: In member function ‘FuncRefVarT<T>::Stage FuncRefVarT<T>::operator/=(T)’:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:25:36: error: ‘untyped’ was not declared in this scope
     Stage operator/=(T x) { return untyped = T(Tuple(untyped)) / x; }
                                    ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h: At global scope:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:30:5: error: ‘FuncRefExpr’ in namespace ‘Halide’ does not name a type
     Halide::FuncRefExpr untyped;
     ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:36:24: error: ‘FuncRefExpr’ in namespace ‘Halide’ does not name a type
     FuncRefExprT(const Halide::FuncRefExpr& untyped)
                        ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:36:45: error: ISO C++ forbids declaration of ‘untyped’ with no type [-fpermissive]
     FuncRefExprT(const Halide::FuncRefExpr& untyped)
                                             ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h: In constructor ‘FuncRefExprT<T>::FuncRefExprT(const int&)’:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:37:30: error: class ‘FuncRefExprT<T>’ does not have any field named ‘untyped’
         : T(Tuple(untyped)), untyped(untyped) {}
                              ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h: In member function ‘FuncRefExprT<T>::Stage FuncRefExprT<T>::operator=(T)’:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:39:35: error: ‘untyped’ was not declared in this scope
     Stage operator=(T x) { return untyped = x; }
                                   ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h: In member function ‘FuncRefExprT<T>::Stage FuncRefExprT<T>::operator+=(T)’:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:40:36: error: ‘untyped’ was not declared in this scope
     Stage operator+=(T x) { return untyped = T(Tuple(untyped)) + x; }
                                    ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h: In member function ‘FuncRefExprT<T>::Stage FuncRefExprT<T>::operator-=(T)’:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:41:36: error: ‘untyped’ was not declared in this scope
     Stage operator-=(T x) { return untyped = T(Tuple(untyped)) - x;}
                                    ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h: In member function ‘FuncRefExprT<T>::Stage FuncRefExprT<T>::operator*=(T)’:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:42:36: error: ‘untyped’ was not declared in this scope
     Stage operator*=(T x) { return untyped = T(Tuple(untyped)) * x; }
                                    ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h: In member function ‘FuncRefExprT<T>::Stage FuncRefExprT<T>::operator/=(T)’:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:43:36: error: ‘untyped’ was not declared in this scope
     Stage operator/=(T x) { return untyped = T(Tuple(untyped)) / x; }
                                    ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft2_r2c.cpp: In member function ‘Halide::NamesInterface::Func fft2_r2c_gen::build()’:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft2_r2c.cpp:52:71: error: ‘WTARGET’ was not declared in this scope
         paddedInput = repeat_image( constant_exterior(input, 0.f), 0, WTARGET, 0, HTARGET);
                                                                       ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft2_r2c.cpp:52:83: error: ‘HTARGET’ was not declared in this scope
         paddedInput = repeat_image( constant_exterior(input, 0.f), 0, WTARGET, 0, HTARGET);
                                                                                   ^
In file included from /home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/complex.h:6:0,
                 from /home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/fft.h:14,
                 from /home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft2_r2c.cpp:11:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h: In instantiation of ‘FuncRefExprT<T> FuncT<T>::operator()(std::vector<Halide::Expr>) const [with T = ComplexExpr]’:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/fft.h:150:53:   required from here
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:74:92: error: could not convert ‘Halide::Func::operator()(std::vector<Halide::Expr>) const(std::vector<Halide::Expr>((*(const std::vector<Halide::Expr>*)(& vars))))’ from ‘Halide::FuncRef’ to ‘FuncRefExprT<ComplexExpr>’
     FuncRefExprT<T> operator()(std::vector<Expr> vars) const { return Func::operator()(vars); }
                                                                                            ^
In file included from /home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/complex.h:6:0,
                 from /home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/fft.h:14,
                 from /home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft2_r2c.cpp:11:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h: In instantiation of ‘FuncRefVarT<T> FuncT<T>::operator()(std::vector<Halide::Var>) const [with T = ComplexExpr]’:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/fft.h:169:15:   required from here
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:66:90: error: could not convert ‘Halide::Func::operator()(std::vector<Halide::Var>) const(std::vector<Halide::Var>((*(const std::vector<Halide::Var>*)(& vars))))’ from ‘Halide::FuncRef’ to ‘FuncRefVarT<ComplexExpr>’
     FuncRefVarT<T> operator()(std::vector<Var> vars) const { return Func::operator()(vars); }
                                                                                          ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h: In instantiation of ‘FuncRefVarT<T> FuncT<T>::operator()(FuncT<T>::Var) const [with T = ComplexExpr; FuncT<T>::Var = Halide::Var]’:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/fft.h:301:12:   required from here
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:60:71: error: could not convert ‘Halide::Func::operator()(Args&& ...) const [with Args = {Halide::Var&}; typename std::enable_if<Halide::Internal::all_are_convertible<Halide::Var, Args ...>::value, Halide::FuncRef>::type = Halide::FuncRef]((* & x))’ from ‘std::enable_if<true, Halide::FuncRef>::type {aka Halide::FuncRef}’ to ‘FuncRefVarT<ComplexExpr>’
     FuncRefVarT<T> operator()(Var x) const { return Func::operator()(x); }
                                                                       ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h: In instantiation of ‘FuncRefExprT<T> FuncT<T>::operator()(FuncT<T>::Expr) const [with T = ComplexExpr; FuncT<T>::Expr = Halide::Expr]’:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/fft.h:353:79:   required from here
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:68:73: error: could not convert ‘Halide::Func::operator()(Halide::Expr, Args&& ...) const [with Args = {}; typename std::enable_if<Halide::Internal::all_are_convertible<Halide::Expr, Args ...>::value, Halide::FuncRef>::type = Halide::FuncRef](Halide::Expr((*(const Halide::Expr*)(& x))))’ from ‘std::enable_if<true, Halide::FuncRef>::type {aka Halide::FuncRef}’ to ‘FuncRefExprT<ComplexExpr>’
     FuncRefExprT<T> operator()(Expr x) const { return Func::operator()(x); }
                                                                         ^
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h: In instantiation of ‘FuncRefVarT<T> FuncT<T>::operator()(FuncT<T>::Var, FuncT<T>::Var, FuncT<T>::Var) const [with T = ComplexExpr; FuncT<T>::Var = Halide::Var]’:
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft2_r2c.cpp:32:50:   required from here
/home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/src/fft/funct.h:62:91: error: could not convert ‘Halide::Func::operator()(Args&& ...) const [with Args = {Halide::Var&, Halide::Var&, Halide::Var&}; typename std::enable_if<Halide::Internal::all_are_convertible<Halide::Var, Args ...>::value, Halide::FuncRef>::type = Halide::FuncRef]((* & x), (* & y), (* & z))’ from ‘std::enable_if<true, Halide::FuncRef>::type {aka Halide::FuncRef}’ to ‘FuncRefVarT<ComplexExpr>’
     FuncRefVarT<T> operator()(Var x, Var y, Var z) const { return Func::operator()(x, y, z); }
                                                                                           ^
/bin/sh: 1: /home/sebastian/anaconda2/lib/python2.7/site-packages/proximal/halide/build/gengen.XXXX: not found
Error genererator compilation: 

Windows install instructions

Currently, when following the installation guide on windows (tested on win 7 and 10) the following error is given:

$ conda install numpy scipy pil pip opencv
Fetching package metadata: ....
Error: No packages found in current win-64 channels matching: opencv

You can search for this package on anaconda.org with

    anaconda search -t conda opencv

This can be solved (according to this stackoverflow thread) by running

conda install -c https://conda.binstar.org/menpo opencv

After doing this, the installation works as expected. This tip may need to be added to the installation instructions.

Github Action: Halide-Python binding does not match the Python version specified

Ok I tried to switch things over to github actions, got pretty far but ran into compilation issues. If you're able to take a look at all I'd really appreciate it!

Originally posted by @SteveDiamond in #54 (comment)

The problem: Github actions wants to test the ProxImaL project in the non-native Python environment, e.g. v3.7. However, the C++ build system detects the system python (v3.8) and then refuses to link the binaries.

Evidence: https://github.com/comp-imaging/ProxImaL/runs/2214159928#step:6:473

@SteveDiamond Possible solutions:

  1. Edit Github action workflows to always use system python (e.g. python 3.6 on Ubuntu 18.04, python 3.8 on Ubuntu 20.04)
  2. Edit Meson configuration to always detect the "current" python runtime that the Meson runtime is running on.
    Link: https://mesonbuild.com/Python-module.html#find_installation

Halide's Anderson2021 auto-scheduler reports segfault on L-ADMM algorithm generator

Symptom: Refer to the Address sanitizer report below.

Potential root cause: is the segfault related to halide/Halide#7606 ? I expect an runtime exception, not a segfault though.

Changes that triggers the segmentation fault: antonysigma@8f0cc04

diff --git a/proximal/halide/src/user-problem/meson.build b/proximal/halide/src/user-problem/meson.build
index 99004b7..b98c9e2 100644
--- a/proximal/halide/src/user-problem/meson.build
+++ b/proximal/halide/src/user-problem/meson.build
@@ -31,13 +31,11 @@ solver_bin = custom_target(
         '-o', meson.current_build_dir(),
         '-g', 'ladmm_iter',
         '-e', 'static_library,h,stmt_html',
-        'target=host',
+        'target=host-cuda-cuda_capability_75',
 
-        '-p', 'autoschedule_mullapudi2016',
-        'autoscheduler=Mullapudi2016',
+        '-p', 'autoschedule_anderson2021',
+        'autoscheduler=Anderson2021',
         'autoscheduler.parallelism=4',
-        'autoscheduler.last_level_cache_size=6291000',
-        'autoscheduler.balance=40',

Environment: Ubuntu 20.04 w/ gcc toolchain, Halide 16.0.0

Logs detailing the segmentation fault:

env LD_LIBRARY_PATH=/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib /home/antony/Projects/ProxImaL/proximal/halide/build-clang/src/user-problem/solver-generator -o /home/antony/Projects/ProxImaL/proximal/halide/build-clang/src/user-problem -g ladmm_iter -e static_library,h,stmt_html target=host-cuda-cuda_capability_75 -p autoschedule_anderson2021 autoscheduler=Anderson2021 autoscheduler.parallelism=4 n_iter=1 mu=0.333 lmb=3.0
AddressSanitizer:DEADLYSIGNAL
=================================================================
==3232855==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000070 (pc 0x7fb6062507ce bp 0x000000000008 sp 0x7ffc51d9e8b0 T0)
==3232855==The signal is caused by a READ memory access.
==3232855==Hint: address points to the zero page.
    #0 0x7fb6062507ce in Halide::Internal::Autoscheduler::LoopNest::compute_strides(Halide::Internal::Autoscheduler::LoadJacobian const&, int, Halide::Internal::Autoscheduler::FunctionDAG::Node const*, Halide::Internal::IntrusivePtr<Halide::Internal::Autoscheduler::BoundContents const> const&, Halide::Internal::Autoscheduler::ThreadInfo const&, bool) const (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x657ce)
    #1 0x7fb606272f6c in void Halide::Internal::Autoscheduler::LoopNest::compute_num_mem_accesses_per_block<Halide::Internal::Autoscheduler::GlobalMem>(Halide::Internal::Autoscheduler::LoadJacobian const&, Halide::Internal::Autoscheduler::FunctionDAG::Node const*, Halide::Internal::IntrusivePtr<Halide::Internal::Autoscheduler::BoundContents const> const&, Halide::Internal::Autoscheduler::ThreadInfo const&, int, double, Halide::Internal::Autoscheduler::MemInfo<Halide::Internal::Autoscheduler::MemTraits<Halide::Internal::Autoscheduler::GlobalMem>::MemInfoType>&, bool) const (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x87f6c)
    #2 0x7fb606273f9d in void Halide::Internal::Autoscheduler::LoopNest::compute_mem_load_features<Halide::Internal::Autoscheduler::GlobalMem>(Halide::Internal::Autoscheduler::LoadJacobian const&, int, Halide::Internal::Autoscheduler::FunctionDAG::Node const*, Halide::Internal::IntrusivePtr<Halide::Internal::Autoscheduler::BoundContents const> const&, bool, Halide::Internal::Autoscheduler::ThreadInfo const&, Halide::Internal::Autoscheduler::MemInfo<Halide::Internal::Autoscheduler::MemTraits<Halide::Internal::Autoscheduler::GlobalMem>::MemInfoType>&, double, bool) const (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x88f9d)
    #3 0x7fb60625ca37 in Halide::Internal::Autoscheduler::LoopNest::compute_features(Halide::Internal::Autoscheduler::FunctionDAG const&, Halide::Internal::Autoscheduler::Anderson2021Params const&, Halide::Target const&, PerfectHashMap<Halide::Internal::Autoscheduler::FunctionDAG::Node::Stage, Halide::Internal::Autoscheduler::LoopNest::Sites, 4, PerfectHashMapAsserter> const&, long, long, Halide::Internal::Autoscheduler::LoopNest const*, Halide::Internal::Autoscheduler::LoopNest const*, Halide::Internal::Autoscheduler::LoopNest const&, Halide::Internal::Autoscheduler::GPULoopInfo, bool, PerfectHashMap<Halide::Internal::Autoscheduler::FunctionDAG::Node::Stage, long, 4, PerfectHashMapAsserter> const&, long*, long*, long*, PerfectHashMap<Halide::Internal::Autoscheduler::FunctionDAG::Node::Stage, Halide::Internal::ScheduleFeatures, 4, PerfectHashMapAsserter>*, Halide::Internal::Autoscheduler::Statistics&, bool) const (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x71a37)
    #4 0x7fb60625b0ab in Halide::Internal::Autoscheduler::LoopNest::compute_features(Halide::Internal::Autoscheduler::FunctionDAG const&, Halide::Internal::Autoscheduler::Anderson2021Params const&, Halide::Target const&, PerfectHashMap<Halide::Internal::Autoscheduler::FunctionDAG::Node::Stage, Halide::Internal::Autoscheduler::LoopNest::Sites, 4, PerfectHashMapAsserter> const&, long, long, Halide::Internal::Autoscheduler::LoopNest const*, Halide::Internal::Autoscheduler::LoopNest const*, Halide::Internal::Autoscheduler::LoopNest const&, Halide::Internal::Autoscheduler::GPULoopInfo, bool, PerfectHashMap<Halide::Internal::Autoscheduler::FunctionDAG::Node::Stage, long, 4, PerfectHashMapAsserter> const&, long*, long*, long*, PerfectHashMap<Halide::Internal::Autoscheduler::FunctionDAG::Node::Stage, Halide::Internal::ScheduleFeatures, 4, PerfectHashMapAsserter>*, Halide::Internal::Autoscheduler::Statistics&, bool) const (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x700ab)
    #5 0x7fb60625ac49 in Halide::Internal::Autoscheduler::LoopNest::compute_features(Halide::Internal::Autoscheduler::FunctionDAG const&, Halide::Internal::Autoscheduler::Anderson2021Params const&, Halide::Target const&, PerfectHashMap<Halide::Internal::Autoscheduler::FunctionDAG::Node::Stage, Halide::Internal::Autoscheduler::LoopNest::Sites, 4, PerfectHashMapAsserter> const&, long, long, Halide::Internal::Autoscheduler::LoopNest const*, Halide::Internal::Autoscheduler::LoopNest const*, Halide::Internal::Autoscheduler::LoopNest const&, Halide::Internal::Autoscheduler::GPULoopInfo, bool, PerfectHashMap<Halide::Internal::Autoscheduler::FunctionDAG::Node::Stage, long, 4, PerfectHashMapAsserter> const&, long*, long*, long*, PerfectHashMap<Halide::Internal::Autoscheduler::FunctionDAG::Node::Stage, Halide::Internal::ScheduleFeatures, 4, PerfectHashMapAsserter>*, Halide::Internal::Autoscheduler::Statistics&, bool) const (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x6fc49)
    #6 0x7fb60628c1bd in Halide::Internal::Autoscheduler::State::compute_featurization(Halide::Internal::Autoscheduler::FunctionDAG const&, Halide::Internal::Autoscheduler::Anderson2021Params const&, Halide::Target const&, PerfectHashMap<Halide::Internal::Autoscheduler::FunctionDAG::Node::Stage, Halide::Internal::ScheduleFeatures, 4, PerfectHashMapAsserter>*, Halide::Internal::Autoscheduler::Statistics&, bool) const (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0xa11bd)
    #7 0x7fb60628cec0 in Halide::Internal::Autoscheduler::State::calculate_cost(Halide::Internal::Autoscheduler::FunctionDAG const&, Halide::Internal::Autoscheduler::Anderson2021Params const&, Halide::Target const&, Halide::CostModel*, Halide::Internal::Autoscheduler::Statistics&, bool) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0xa1ec0)
    #8 0x7fb60627c076 in Halide::Internal::Autoscheduler::SearchSpace::add_child(Halide::Internal::IntrusivePtr<Halide::Internal::Autoscheduler::State> const&, Halide::Internal::IntrusivePtr<Halide::Internal::Autoscheduler::LoopNest const> const&, std::function<void (Halide::Internal::IntrusivePtr<Halide::Internal::Autoscheduler::State>&&)>&) const (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x91076)
    #9 0x7fb606281839 in Halide::Internal::Autoscheduler::SearchSpace::generate_children(Halide::Internal::IntrusivePtr<Halide::Internal::Autoscheduler::State> const&, std::function<void (Halide::Internal::IntrusivePtr<Halide::Internal::Autoscheduler::State>&&)>&, int, bool) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x96839)
    #10 0x7fb60620926e in Halide::Internal::Autoscheduler::AutoSchedule::optimal_schedule_pass(int, int, int, Halide::Internal::Autoscheduler::ProgressBar&, std::unordered_set<unsigned long, std::hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<unsigned long> >&) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x1e26e)
    #11 0x7fb60620b144 in Halide::Internal::Autoscheduler::AutoSchedule::optimal_schedule(int) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x20144)
    #12 0x7fb60620c0d2 in Halide::Internal::Autoscheduler::generate_schedule(std::vector<Halide::Internal::Function, std::allocator<Halide::Internal::Function> > const&, Halide::Target const&, Halide::Internal::Autoscheduler::Anderson2021Params const&, Halide::AutoSchedulerResults*) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x210d2)
    #13 0x7fb606217f4b in Halide::Internal::Autoscheduler::Anderson2021::operator()(Halide::Pipeline const&, Halide::Target const&, Halide::AutoschedulerParams const&, Halide::AutoSchedulerResults*) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x2cf4b)
    #14 0x7fb60ade3c82 in Halide::Pipeline::apply_autoscheduler(Halide::Target const&, Halide::AutoschedulerParams const&) const (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-15.0.0-x86-64-linux/lib/libHalide.so.16+0xd9fc82)
    #15 0x7fb60a917e7c in Halide::Internal::AbstractGenerator::build_module(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libHalide.so.16+0x8d3e7c)
    #16 0x7fb60ac39eaa in std::_Function_handler<Halide::Module (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Halide::Target const&), Halide::Internal::execute_generator(Halide::Internal::ExecuteGeneratorArgs const&)::'lambda2'(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Halide::Target const&)>::_M_invoke(std::_Any_data const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Halide::Target const&) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libHalide.so.16+0xbf5eaa)
    #17 0x7fb60adad309 in Halide::compile_multitarget(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::map<Halide::OutputFileType, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<Halide::OutputFileType>, std::allocator<std::pair<Halide::OutputFileType const, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > > const&, std::vector<Halide::Target, std::allocator<Halide::Target> > const&, std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::function<Halide::Module (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Halide::Target const&)> const&, std::function<std::unique_ptr<Halide::Internal::CompilerLogger, std::default_delete<Halide::Internal::CompilerLogger> > (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, Halide::Target const&)> const&) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libHalide.so.16+0xd69309)
    #18 0x7fb60ac42edf in Halide::Internal::execute_generator(Halide::Internal::ExecuteGeneratorArgs const&) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libHalide.so.16+0xbfeedf)
    #19 0x7fb60ac444ed in Halide::Internal::(anonymous namespace)::generate_filter_main_inner(int, char**, Halide::Internal::GeneratorFactoryProvider const&) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libHalide.so.16+0xc004ed)
    #20 0x7fb60ac4527f in Halide::Internal::generate_filter_main(int, char**, Halide::Internal::GeneratorFactoryProvider const&) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libHalide.so.16+0xc0127f)
    #21 0x7fb60ac452ca in Halide::Internal::generate_filter_main(int, char**) (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libHalide.so.16+0xc012ca)
    #22 0x7fb609acd082 in __libc_start_main /build/glibc-SzIz7B/glibc-2.31/csu/../csu/libc-start.c:308:16
    #23 0x42329d in _start (/home/antony/Projects/ProxImaL/proximal/halide/build-clang/src/user-problem/solver-generator+0x42329d)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (/home/antony/Projects/ProxImaL/proximal/halide/subprojects/Halide-16.0.0-x86-64-linux/lib/libautoschedule_anderson2021.so+0x657ce) in Halide::Internal::Autoscheduler::LoopNest::compute_strides(Halide::Internal::Autoscheduler::LoadJacobian const&, int, Halide::Internal::Autoscheduler::FunctionDAG::Node const*, Halide::Internal::IntrusivePtr<Halide::Internal::Autoscheduler::BoundContents const> const&, Halide::Internal::Autoscheduler::ThreadInfo const&, bool) const
==3232855==ABORTING

PEP8 style conformance

I've been looking some at the code now in order to get it working nicely with ODL, and one thing I've come to notice is that you do not seem to follow the official python style as given in PEP8. Python differs from most other languages in there being an official style guide that should be used with it, and it is highly recommended to follow it. Further, it is often easier to get started with style conformance early on in the project than waiting until later (trust me, we waited far to long before we did this in ODL).

There are several tools available in order to both check that your code is conforming (such as pytest pep8 and the built in pep8 checker for spyder) and also a few that can help you make the code conforming such as autopep8 and autoflakes.

ProxFn least_squares Halide compilation error

Solving a problem with the least_squares prox function in Halide implementation modus throws the following errors during compilation:

`../ProxImaL/build/lib/proximal/halide/src/fft2_r2c.cpp:52:71: error: use of undeclared identifier 'WTARGET'

    paddedInput = repeat_image( constant_exterior(input, 0.f), 0, WTARGET, 0, HTARGET);
                                                                  ^

../ProxImaL/build/lib/proximal/halide/src/fft2_r2c.cpp:52:83: error: use of undeclared identifier 'HTARGET'

    paddedInput = repeat_image( constant_exterior(input, 0.f), 0, WTARGET, 0, HTARGET);
                                                                              ^

../ProxImaL/build/lib/proximal/halide/src/fft2_r2c.cpp:56:43: error: use of undeclared identifier 'WTARGET'

    Func fftIn = fft2_r2c(input_func, WTARGET, HTARGET);
                                      ^

../ProxImaL/build/lib/proximal/halide/src/fft2_r2c.cpp:56:52: error: use of undeclared identifier 'HTARGET'

    Func fftIn = fft2_r2c(input_func, WTARGET, HTARGET);`

I resolved the error by adding the necessary flags to the compilation in sum_squares.py:

hflags = ['-DWTARGET={0} -DHTARGET={1}'.format(self.freq_shape[1], self.freq_shape[0])]

and

Halide('fft2_r2c.cpp', compile_flags=hflags).

If this is a new and unknown error and my solution is correct I am happy to send a PR.

Tests seem to assume Halide is installed

When running the tests without Halide installed several tests fail with messages similar to this:

g++.exe: error: ${HALIDE_PATH}/tools/GenGen.cpp: No such file or directory
g++.exe: error: ${HALIDE_PATH}/bin/libHalide.so: No such file or directory
'D:\Programming\ProxImaL\proximal\halide\build\gengen.XXXX' is not recognized as an internal or external command,
operable program or batch file.
Error genererator compilation:

Platform used is windows 10 with python 2.7.

test_prox_fn tests cvxpy components

Currently in test_prox_fn the following line is run (among others):

x_var = cvx.Variable(10)

I assume that this is a copy-paste error and that the test should be for proximal.Variable? Otherwise these need to be import guarded since cvxpy is not a required dependency of proximal and not having it currently causes the tests to crash.

Version breaking changes of Numexpr 2.8.5

Github CI reported python failure since ~2 weeks ago. Mitigation: refactor the code to use the new Numexpr APIs.

Error message:

test_prox_fn.py:240: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../prox_fns/prox_fn.py:102: in prox
    rho_hat = ne.evaluate('(rho + 2 * gamma) / (alpha * beta**2)', global_dict=symbols)
../../sandbox/lib/python3.8/site-packages/numexpr/necompiler.py:941: in evaluate
    return re_evaluate(local_dict=local_dict, _frame_depth=_frame_depth)
../../sandbox/lib/python3.8/site-packages/numexpr/necompiler.py:969: in re_evaluate
    args = getArguments(argnames, local_dict, _frame_depth=_frame_depth)
E                   KeyError: 'alpha'

../../sandbox/lib/python3.8/site-packages/numexpr/necompiler.py:755: KeyError

Python 3 support

ProxImalL currently has a few python2 only statements, mostly print x. Is there a plan to start supporting Python3 as well?

Unable to extract background field "w"; modified Horn-Shunck optical flow with norm1

Hi,

Using proximal, with an odl operator, I was able to implement robust horn-shunck optical flow in just a few lines of code. Amazing!

laplacian = odl.Laplacian(space)

# Convert laplacian to ProxImaL operator
proximal_lang_laplacian = odl.as_proximal_lang_operator(laplacian)

fx = np.gradient(image1)[1]
fy = np.gradient(image1)[0]
ft = image1 - image2

# Set up optimization problem
u = proximal.Variable(space.shape)
v = proximal.Variable(space.shape)
alpha = .07
funcs = [alpha * proximal.norm1(proximal_lang_laplacian(u)),
         alpha * proximal.norm1(proximal_lang_laplacian(v)),
         proximal.norm1(proximal.mul_elemwise(fx,u) + proximal.mul_elemwise(fy,v) - ft)]

This works great. However, I am trying to solve a slightly different problem:

laplacian = odl.Laplacian(space)

# Convert laplacian to ProxImaL operator
proximal_lang_laplacian = odl.as_proximal_lang_operator(laplacian)

fx = np.gradient(image1)[1]
fy = np.gradient(image1)[0]
ft = image1 - image2

# Set up optimization problem
u = proximal.Variable(space.shape)
v = proximal.Variable(space.shape)
w = proximal.Variable(space.shape)
alpha = .07
funcs = [alpha * proximal.norm1(proximal_lang_laplacian(u)),
         alpha * proximal.norm1(proximal_lang_laplacian(v)),
         alpha * proximal.norm1(proximal_lang_laplacian(w)),
         proximal.norm1(proximal.mul_elemwise(fx,u) + proximal.mul_elemwise(fy,v) + w - ft)]

In short I have added the free variable w. After doing this, the results don't make sense. The regularization parameter alpha makes no difference. 0 to 1e40 all give the same results. And without regularization, the problem is ill-posed. My first thought was that the solver is unhappy that u and v are scaled, while w is not, but performing a proximal.mul_elemwise(np.ones_like(fy),w) does not improve things. Any ideas?

Support for several variables

Currently when trying to use several variables at once:

>>> x = proximal.Variable(3)
>>> y = proximal.Variable(6)
>>> rhs = np.array([1, 2, 3])
>>> prob = proximal.Problem([proximal.sum_squares(x - rhs),
                             proximal.sum_squares(proximal.subsample(y, [2]) - x)])
>>> prob.solve()

errors are encountered. Is this type of problem intended to be supported in ProxImaL? If not, perhaps a check should be added to disallow it.

Linear-ADMM: the z[k]-update step in Halide cannot find z[k-1] in MacOS+clang14

The Linear-ADMM Halide code can compile and generate baremetal code in Linux and Windows build environments. But the same code fails in MacOS+clang14 environment.

Error report:

[4/6] Generating src/user-problem/ladmm_iter.[ah] with a custom command (wrapped by meson to set env)
FAILED: src/user-problem/ladmm_iter.a src/user-problem/ladmm_iter.h 
env LD_LIBRARY_PATH=/Users/runner/work/ProxImaL/ProxImaL/proximal/halide/subprojects/Halide-10.0.0-x86-64-osx/lib /Users/runner/work/ProxImaL/ProxImaL/proximal/halide/build/src/user-problem/solver-generator -o /Users/runner/work/ProxImaL/ProxImaL/proximal/halide/build/src/user-problem -g ladmm_iter -e static_library,h,stmt_html machine_params=12,6291000,40 target=host auto_schedule=true -s Mullapudi2016 -p autoschedule_mullapudi2016 n_iter=1 mu=0.333 lmb=3.0
Assertion failed: (_z.defined() && "FuncTuple z_new is not defined."), function iterate, file linearized-admm.h, line 92.

The assertion that failed:

// src/algorithm/linearlized-admm.h
// Update z_i for i = 0..N .
const FuncTuple<N> Kv2 = K.forward(v_new);
FuncTuple<N> z_new;
{
    for (auto&& [_z_new, _Kv2, _u, prox] : zip_view{z_new, Kv2, u, psi_fns}) {
        Func Kv_u{"Kv_u"};
        const auto vars = (prox.n_dim == 4) ? Vars{x, y, c, k} : Vars{x, y, c};

        Kv_u(vars) = _Kv2(vars) + _u(vars);

        _z_new = prox(Kv_u, 1.0f / lmb);
        assert(_z_new.defined() && "FuncTuple z_new is not defined.");
    }
}

Build environment:

C++ compiler for the host machine: c++ (clang 14.0.0 "Apple clang version 14.0.0 (clang-1400.0.29.202)")
C++ linker for the host machine: c++ ld64 820.1
Host machine cpu family: x86_64
Host machine cpu: x86_64

Possible root cause: In gcc and msvc, the variable _z_new is treated as C++ l-value (Func&), but in clang-14, it is treated as r-value Func&&. Thus, the z-update step appears to be immediately discarded, causing the ADMM iteration to fail during the codegen step.

Likely solution: Upgrade from Halide 10.0 to Halide >14.0, so as to match the MacOS+clang14 build environment.

Generating halide-optimized routine from K.fwd and K.adj

Fork from other discussion:
Component level specification

We could achieve the same pattern with ProxImaL. In ideal world that would be like:

  1. Describe the Problem [ProxImaL]
  2. Compile to have the solver as Halide Kernel (C++ or Python). [ProxImaL ->Halide]
  3. Use Halide to build a scheduler or auto_schedule for {CUDA, OpenCL, x86, ...} [Halide]

I suggest that we fork out a separate Github issue to discuss this. @jrk and @SteveDiamond can chime in as well.

My first thought is that ProxImaL, just like FlexISP, generates a cyclic compute graph. The lack of compute cycles in Halide is a fundamental strength to customize the compute schedule (or weakness in your use-case?).

As the authors suggested in the original article, I think the ProxImaL project can still grow by

  1. fusing more proximal.linops.* nodes in the proximal.CompGraph into a single Halide pipeline; and
  2. fusing the individual proximal update steps in ADMM into Halide pipeline.

But eventually the Halide-generate code will have to hand back control to the ADMM while-loop to complete the "cycle". Whether the while-loop has to be coded in C++ or to remain in Python, I do not know.

Originally posted by @antonysigma in #57 (comment)

Simplified version of the main example raises Exception

If we remove the regularizer and nonnegativity condition from the example in the README, we get:

from proximal import *
import numpy as np
import scipy.misc
import matplotlib.pyplot as plt

# Generate data.
I = scipy.misc.ascent()
np.random.seed(1)
b = I + 10*np.random.randn(*I.shape)

# Construct and solve problem.
x = Variable( I.shape )
prob = Problem(sum_squares(x - b/255))  #  REMOVED: + .1*norm1( grad(x) ) + nonneg(x)
prob.solve()

# Plot the original, noisy, and denoised images.
plt.figure(figsize=(15,8))
plt.subplot(131)
plt.gray()
plt.imshow(I)
plt.title('Original image')

plt.subplot(132)
plt.gray()
plt.imshow(b)
plt.title('Noisy image')

plt.subplot(133)
plt.gray()
plt.imshow(x.value*255) # x.value is the optimal value of x.
plt.title('Denoising results')
plt.show()

I get an error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "e:\github\proximal\proximal\algorithms\problem.py", line 96, in solve
    prox_fns = absorb.absorb_all_lin_ops(prox_fns)
  File "e:\github\proximal\proximal\algorithms\absorb.py", line 21, in absorb_all_lin_ops
    ready = prox_funcs[:]
TypeError: 'sum_squares' object has no attribute '__getitem__'

The problem can be partially fixed by adding square brackets ([ ]) around the argument to proximal.Problem, but then another issue appears:

from proximal import *
import numpy as np
import scipy.misc
import matplotlib.pyplot as plt

# Generate data.
I = scipy.misc.ascent()
np.random.seed(1)
b = I + 10*np.random.randn(*I.shape)

# Construct and solve problem.
x = Variable( I.shape )
prob = Problem( [ sum_squares(x - b/255) ] )  #  ADDED [  ]
prob.solve()

# Plot the original, noisy, and denoised images.
plt.figure(figsize=(15,8))
plt.subplot(131)
plt.gray()
plt.imshow(I)
plt.title('Original image')

plt.subplot(132)
plt.gray()
plt.imshow(b)
plt.title('Noisy image')

plt.subplot(133)
plt.gray()
plt.imshow(x.value*255) # x.value is the optimal value of x.
plt.title('Denoising results')
plt.show()

I get an error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "e:\github\proximal\proximal\algorithms\problem.py", line 123, in solve
    Knorm = est_CompGraph_norm(K, try_fast_norm=self.try_fast_norm)
  File "e:\github\proximal\proximal\lin_ops\comp_graph.py", line 273, in est_CompGraph_norm
    Knorm = np.sqrt(eigs(A, k=1, M=None, sigma=None, which='LM', tol=tol)[0].real)
  File "C:\Anaconda\lib\site-packages\scipy\sparse\linalg\eigen\arpack\arpack.py", line 1224, in eigs
    % (k, n - 1))
ValueError: k=1 must be between 1 and ndim(A)-1=-1

Tried on windows 7 with python 2.7 and the latest version of proximal from master.

Reasoning behind the Problem class

When writing some examples I have come to realize that we pretty much always write:

prob = proximal.Problem(...)
prob.solve()

Looking through the proximal code base, the only place I see a divergence from this pattern is where the set_ methods are tested, never in use.

Is there a reason that the Problem class exists? Why could the above not simply be written in a functional manner:

proximal.solve(...)

Halide/C++ code failed to generate algorithms in Windows CI over the weekend

The same revision e0bbeba passes the Windows CI on July 14, but the same code fails since July 19.

CI success on July 14: https://github.com/comp-imaging/ProxImaL/actions/runs/5564437916
CI failure today: https://github.com/antonysigma/ProxImaL/actions/runs/5557095504/job/15213363734

Error message:

Run ninja -C proximal/halide/build ladmm-runtime
ninja: Entering directory `proximal/halide/build'
[1/6] Compiling C++ object src/user-problem/solver-generator.exe.p/.._.._subprojects_Halide-14.0.0-x86-64-windows_share_Halide_tools_GenGen.cpp.obj
cl : Command line warning D9002 : ignoring unknown option '-fno-rtti'
[2/6] Compiling C++ object src/user-problem/solver-generator.exe.p/linearized-admm-gen.cpp.obj
cl : Command line warning D9002 : ignoring unknown option '-fno-rtti'
[3/6] Linking target src/user-problem/solver-generator.exe
[4/6] Generating src/user-problem/ladmm_iter.[ah] with a custom command (wrapped by meson to set PATH, to set env)
FAILED: src/user-problem/ladmm_iter.lib src/user-problem/ladmm_iter.h 
"C:\hostedtoolcache\windows\Python\3.8.10\x64\Scripts\meson" "--internal" "exe" "--unpickle" "D:\a\ProxImaL\ProxImaL\proximal\halide\build\meson-private\meson_exe_solver-generator_13344a9f4d4ac864c6273976ca7dedc4382aeada.dat"
Traceback (most recent call last):
  File "C:\hostedtoolcache\windows\Python\3.8.10\x64\lib\runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\hostedtoolcache\windows\Python\3.8.10\x64\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\hostedtoolcache\windows\Python\3.8.10\x64\Scripts\meson.exe\__main__.py", line 7, in <module>
  File "C:\hostedtoolcache\windows\Python\3.8.10\x64\lib\site-packages\mesonbuild\mesonmain.py", line 294, in main
    return run(sys.argv[1:], launcher)
  File "C:\hostedtoolcache\windows\Python\3.8.10\x64\lib\site-packages\mesonbuild\mesonmain.py", line 282, in run
    return run_script_command(args[1], args[2:])
  File "C:\hostedtoolcache\windows\Python\3.8.10\x64\lib\site-packages\mesonbuild\mesonmain.py", line 223, in run_script_command
    return module.run(script_args)
  File "C:\hostedtoolcache\windows\Python\3.8.10\x64\lib\site-packages\mesonbuild\scripts\meson_exe.py", line 122, in run
    return run_exe(exe)
  File "C:\hostedtoolcache\windows\Python\3.8.10\x64\lib\site-packages\mesonbuild\scripts\meson_exe.py", line 76, in run_exe
    raise FileNotFoundError(p.returncode, strerror, cmd_args)
FileNotFoundError: [Errno 322122[57](https://github.com/antonysigma/ProxImaL/actions/runs/5557095504/job/15213363734#step:8:58)81] Failed to run due to missing DLLs, with path: D:\a\ProxImaL\ProxImaL\proximal\halide\subprojects\Halide-14.0.0-x86-64-windows\lib\Release;D:\a\ProxImaL\ProxImaL\proximal\halide\build\src/user-problem;D:/a/ProxImaL/ProxImaL/proximal/halide/subprojects/Halide-14.0.0-x86-64-windows/lib/Release: ['D:\\a\\ProxImaL\\ProxImaL\\proximal\\halide\\build\\src/user-problem\\solver-generator.exe', '-o', 'D:/a/ProxImaL/ProxImaL/proximal/halide/build/src/user-problem', '-g', 'ladmm_iter', '-e', 'static_library,h,stmt_html', 'machine_params=12,[62](https://github.com/antonysigma/ProxImaL/actions/runs/5557095504/job/15213363734#step:8:63)91000,40', 'target=host', 'auto_schedule=true', '-s', 'Mullapudi2016', '-p', 'autoschedule_mullapudi2016', 'n_iter=1', 'mu=0.333', 'lmb=3.0']

Data folder missing

Several examples seem to be referring a data folder, this is however missing in the repository. See for example here.

Scaled problem and x0 solver initialisation

Creating a Problem with scale=True causes a scaling of the prox functions with the operator norm Knorm. This usually works fine, but when a problem is solved with an x0 initialisation other than None (i.e. all zeros in x0) the scaling of the parameters and the input do not match. From my understanding the initialisation x0 has to be scaled as well. For example with:

x0 = x0.copy() * np.sqrt(Knorm)

In which case the operator norm has to be passed to the solve function. Without this scaling my results were considerably worse. This effect is of course only observable if Knorm != 1.0.

Optimize the direct FFT method in `least_square` algorithm with Halide

Note to self: The algorithm least_square(x, b) has a direct frequency domain inversion method, utilizing the Halide-accelerated FFT interface. However, the current implementation requires context switch between Halide/C++ domain and Numpy/Python domain, introducing overhead.

The internal buffer lifetime, namely self.ftmp_halide, could have been managed in the Halide/C++ domain to reduce code bloat.

Roadmap:

  1. Implement Halide-accelerated pipeline least_squares_direct(input, b, freq_diag, output)
  2. Expose the algorithm to Python with Pybind11.
  3. Eliminate the code related to temporary buffer management, namely self.ftmp_halide.
  4. Sanity check the new feature with proximal/examples/test_deconv.py.

# Frequency inversion
if self.implementation == Impl['halide'] and \
(len(self.freq_shape) == 2 or
(len(self.freq_shape) == 2 and self.freq_dims == 2)):
Halide('fft2_r2c').fft2_r2c(Ktb.reshape(self.freq_shape), 0, 0,
self.ftmp_halide)
if rho is None:
ne.evaluate('F_Ktb / d', {
'F_Ktb': self.ftmp_halide,
'd': self.freq_diag,
},
out=self.ftmp_halide,
casting='unsafe')
else:
F_Ktb = self.ftmp_halide.copy()
Halide('fft2_r2c').fft2_r2c(np.reshape(v, self.freq_shape),
0, 0, self.ftmp_halide)
ne.evaluate('(F_Ktb / rho + x) / (d / rho + 1.0)', {
'F_Ktb': F_Ktb,
'x': self.ftmp_halide,
'rho': rho,
'd': self.freq_diag,
},
out=self.ftmp_halide,
casting='unsafe')
# Do inverse tranform
Halide('ifft2_c2r').ifft2_c2r(self.ftmp_halide,
self.ftmp_halide_out)
return self.ftmp_halide_out.ravel()

comp_graph.py: np.float(Knorm) is deprecated

Issue reported by @shnaqvi :

Traceback (most recent call last):
  File "examples/test_deconv_sv_psf.py", line 75, in <module>
    prob.solve(solver='pc', max_iters=2, verbose=True, x0=im.copy())
  File "../../../../../.pyenv/versions/3.10.1/lib/python3.10/site-packages/proximal/algorithms/problem.py", line 156, in solve
    Knorm = est_CompGraph_norm(K, try_fast_norm=self.try_fast_norm)
  File "../../../../../.pyenv/versions/3.10.1/lib/python3.10/site-packages/proximal/lin_ops/comp_graph.py", line 433, in est_CompGraph_norm
    return np.float(Knorm)
  File "../../../../../.pyenv/versions/3.10.1/lib/python3.10/site-packages/numpy/__init__.py", line 305, in __getattr__
    raise AttributeError(__former_attrs__[attr])
AttributeError: module 'numpy' has no attribute 'float'.
`np.float` was a deprecated alias for the builtin `float`. To avoid this error in existing code, use `float` by itself. Doing this will not modify any behavior and is safe. If you specifically wanted the numpy scalar type, use `np.float64` here.
The aliases was originally deprecated in NumPy 1.20; for more details and guidance see the original release note at:
    https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations

However, the master branch indicates the bug is already resolved:

return float(Knorm)

Deep failure when using patch_NLM

Steps to reproduce:

>>> x = proximal.Variable((10, 10))
>>> funcs = [proximal.sum_squares(x), proximal.patch_NLM(x)]
>>> prob = proximal.Problem(funcs)
>>> prob.solve()
cv2.error: ..\..\..\modules\photo\src\denoising.cpp:91: error: (-5) Type of input image should be CV_8UC3! in function cv::fastNlMeansDenoisingColored

Python 2.7.12
Windows 10
cv2 2.4.11

Edit: Title changed, problem seems to be deeper.

Cuda version

Hi,

before creating a pull request for this with the necessary clean-up actions, I'd like to hear the opinion of the authors about this. I created a port using pycuda to improve performance. Currently a subset of the linear operations, the group_norm1 prox function and the Pock Chambolle algorithm is supported. I observe a nice speedup of a factor 10 compared to the native python implementation (even using only a mobile graphics card). On my forked repository https://github.com/wiedemannc/ProxImaL, it is currently implemented on the branch 'matlab_code_generation' (I have to remove the matlab stuff before creating the pull request for it).

If there is interest for integration, I'd be up for cleaning things up and create a pull request for this.

Kind Regards
Christoph

Baremetal only version?

As some core is based on C++ & Halide.
Is there a way to reproduce the results of the paper using only C++?

Problem class and the implementation parameter

From my understanding the implem parameter of the Problem class should work as a global implementation flag for the entire computation graph. One either specifies the implementation modus for each component individually or with the implem parameter of the Problem class.

Currently this is not the case if the problem is not scaled. Additionally the implementation modus is not handled very consistently. For example copying a ProxFn object does not include the implementation modus.

Is the current state intentionally or does it make sense to send a PR with change suggestions?

Extending Lin_Op

Hello everyone,

I am currently extending the 'Lin_Op' class by creating a new class 'matrix_nonsquared_mult2'. This operator should perform the following operation:

C * i - h

where:

  • "i" is the variable 442x19800 matrix
  • "h" is some data 442x19800 matrix
  • "C" is a 442x442 matrix operator
  • "*" denotes a common matrix-matrix multiplication

As can be noted, unlike "mul_elemwise", the dimensions of my objects are all different, so creating this new class by just modifying the forward and adjoint methods of "mul_elemwise" wont be sufficient as some reshaping must be done.

I have defined the constructor so that shapes of both, operator "C" and variable "i" match during the execution of the "forward" method. By the point where the bug occurs, the "adjoint" method hasn't even been referenced yet.

The bug occurs during the execution of the "get_diag" method within my class, during the "partition/split" phase. Specifically, in the line:

self_diag = np.reshape(self.kernel, self.size)

The reason for the bug is that "self.kernel" contains, well, the 442x442 operator; but "self.size" contains the size of the 442x19800 variable. In the cases of "conv" and "mul_elemwise" modules such conflict never exists: In the first case the kernel is reshaped within the operator's constructor to match the variable size and then the operator acting on the input is a element-wise multiplication; while in the second case, both, kernel and input variable must have same dimensions from the beginning.

At the moment, I can't figure out how to make this to match. I have tried to store different shapes within the constructor of my class but then immediately the program breaks during the "absorption" stage at the "forward" method execution, since shapes do not match during the matrix-matrix multiplication. So, where should I do the reshaping and what are the correct shapes/sizes to store?? I think I don't really understand what is each shape or size for.

I would appreciate any suggestions or ideas. I attach the code below
Thank you in advance.
Javier

`class matrix_nonsquared_mult2(LinOp):

def __init__(self, kernel, arg, implem = None):
    #assert arg.shape == kernel.shape     #Now we must admit different dimensions
    self.kernel = kernel
    self.forward_kernel = kernel
    shape = arg.shape

    super(matrix_nonsquared_mult2, self).__init__([arg], shape, implem)

def init_kernel(self):
    print('Kernel Initialization: matrix_nonsquared_mult2')

def forward(self, inputs, outputs):
    """The forward operator.

    Reads from inputs and writes to outputs.
    """
    self.forward_kernel
    np.copyto(outputs[0], np.dot(self.kernel,inputs[0])) 


def adjoint(self, inputs, outputs):
    """The adjoint operator.

    Reads from inputs and writes to outputs.
    """
    print('To be implemented...')
    self.adjoint_kernel = self.forward_kernel.conj()


def is_diag(self, freq=False):

    return not freq and self.input_nodes[0].is_diag(freq)

def get_diag(self, freq=False):
    """Returns the diagonal representation (A^TA)^(1/2).

    Parameters
    ----------
    freq : bool
        Is the diagonal representation in the frequency domain?
    Returns
    -------
    dict of variable to ndarray
        The diagonal operator acting on each variable.
    """
    assert not freq

    var_diags = self.input_nodes[0].get_diag(freq)
    self_diag = np.reshape(self.kernel, self.size)
    for var in var_diags.keys():
        var_diags[var] = var_diags[var]*self_diag
    return var_diags


def norm_bound(self, input_mags):
    """Gives an upper bound on the magnitudes of the outputs given inputs.

    Parameters
    ----------
    input_mags : list
        List of magnitudes of inputs.

    Returns
    -------
    float
        Magnitude of outputs.
    """
    return np.max(np.abs(self.kernel))*input_mags[0]`

Needing Halide support for MacOS with ARM64 processors

Error message:

% cd proximal/halide/
% meson setup build/
The Meson build system
Version: 1.2.0
Source dir: /Users/antony/Projects/ProxImaL/proximal/halide
Build dir: /Users/antony/Projects/ProxImaL/proximal/halide/build
Build type: native build
Project name: proximal-halide
Project version: undefined
C++ compiler for the host machine: c++ (clang 15.0.0 "Apple clang version 15.0.0 (clang-1500.0.40.1)")
C++ linker for the host machine: c++ ld64 1015.7
Host machine cpu family: aarch64
Host machine cpu: aarch64

meson.build:8:19: ERROR: Neither a subproject directory nor a halide-aarch64-darwin.wrap file was found.

A full log can be found at /Users/antony/Projects/ProxImaL/proximal/halide/build/meson-logs/meson-log.txt

Version of Halide

Hello, I am recently trying to use ProxImaL library and wondering which version of Halide did you guys build on? The code corresponding to halide seems to not work with the current version of Halide. Thanks!

Example of using patch_NLM with a solver

I've been trying to use patch_NLM with a nontrivial data discrepancy term, but my results seem to always diverge. The call is basically, using this ODL branch:

import numpy as np
import odl
import proximal

# Create space, a square from [0, 0] to [100, 100] with (100 x 100) points
space = odl.uniform_discr([0, 0], [100, 100], [100, 100])

# Create odl operator for laplacian
laplacian = odl.Laplacian(space)

# Create right hand side
rhs = laplacian(odl.phantom.shepp_logan(space, modified=True))
rhs += odl.phantom.white_noise(space) * np.std(rhs) * 0.0  # disable noise
rhs.show('noisy data')

# Convert laplacian to cvx operator
norm_bound = odl.power_method_opnorm(laplacian, 10, rhs)
cvx_laplacian = odl.operator.oputils.as_cvx_operator(laplacian,
                                                     norm_bound=norm_bound)

# Convert to array
rhs_arr = rhs.asarray()

# Set up optimization problem
x = proximal.Variable(space.shape)
funcs = [proximal.sum_squares(cvx_laplacian(x) - rhs_arr),
         0.01 * proximal.patch_NLM(x, sigma_fixed=0)]
prob = proximal.Problem(funcs)

# Solve the problem
prob.solve(verbose=True, max_iters=2000)

# Convert back to odl and display result
result_odl = space.element(x.value)
result_odl.show('result')

Which gives utter nonsense as a result, and it does not seem to converge when max_iters is increased, nor does overestimating the norm_bound help. Changing the scaling term 0.01´ in front ofpatch_NLM` seems to have only minor impact.

It seems I am missing something, so adding an example of using this regularizer would be great!

installation instructions need overhaul

http://www.proximal-lang.org/en/latest/install/index.html
Tested Miniconda3 (Python 3.5) on Win7.

  • installation for all users does not work
  • misleading dependency conflicts: conda/conda#2791 (comment)
  • mentioned pil dependency is neither available for python3 nor needed it seems
  • opencv install as described did not work
  • but was installed automatically with pip install proximal just like pillow

It might be better to recommend a normal python installation.

Also I wonder how https://github.com/comp-imaging/ProxImaL/blob/master/continuous_integration/install.sh is supposed to work for 3.5 if miniconda2 is downloaded.

Major revamp to Halide 16.0 with Anderson2021 GPU autoscheduler

(Adding the task dependencies for my own reminder.)

  1. Wait for the Halide 16.0 release.
  2. Refactor the Halide::BoundaryConditions calls to use the new APIs;
  3. Similarly, refactor Generator::* related code to use Halide 16.0 APIs;
  4. In algorithms/ladmm.py, ensure all Numpy matrices are Fortran order by default; this avoids the frequent C-order to F-order typecasting overhead in the (L-)ADMM iterations;
  5. Similarly, ensure Halide-accelerated linear operators, e.g. A_mask.cpython.so writes to the output buffers in F-order, not some orphan buffers that are immediately destroyed. This should solve the convergence failure bugs whenever implem='Halide' is defined.
  6. Wait until Anderson2021 algorithm optimizer is ready for production (halide/Halide#7606).
  7. (Optional) Compile the Halide generators with C++20; this should cut the compile time in half thanks to new C++ Concepts feature;
  8. (Optional) reduce code bloat of ladmm-iter-gen.cpp with the broadcast operator Halide::_.
  9. Replace Li2018 autoscheduler with Anderson2021: the latter utilizes the GPU cache and shared memory in the SM far better.

References:
halide/Halide#6856
halide/Halide#7459

OpenCV dependency missing

When running pip install proximal you get an error:

>>> import proximal
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "proximal/__init__.py", line 3, in <module>
    from .prox_fns import *
  File "proximal/prox_fns/__init__.py", line 1, in <module>
    from .prox_fn import ProxFn
  File "proximal/prox_fns/prox_fn.py", line 4, in <module>
    from proximal.utils import Impl
  File "proximal/utils/__init__.py", line 1, in <module>
    from .utils import Impl
  File "proximal/utils/utils.py", line 6, in <module>
    import cv2
ImportError: No module named cv2

It seems some cv2 binding has to be added to the list of dependencies.

Edit:

I installed opencv-python via pip install opencv-python and it works great for me. So that binding can be added.

Multiple issues with halide.py

While working with ProxImaL in Halide implementation modus I encountered multiple problems in halide.py:

  1. e.message is not correctly transpiled to Python 3. The message attribute is not removed even though it does not exist in Python 3 and therefore throws an error. I suggest to remove the messsage attribute at all. "{0}".format(e) should work in both Python versions.

  2. From NumPy >= 1.10.0 the result of np.isfortran may wary. See the documentation in the link. I therefore suggest to replace np.isfortran(arg) with arg.flags.f_contiguous.

  3. If an error occurs in the try statement of the gengen function before header_file and object_file are initialized the function will throw an error in the finally statement. I suggest to initialize the two variables like the launcher_file before the try statement:

...
header_file = object_file = launcher_file = '' 
try:
...
  1. The second compilation commented with Run generator fails on OSX if the correct environment variables aren't set in the subprocess. I therefore added the following lines which are probably not the best solution:
        # Run generator
        env = os.environ.copy()
        if sys.platform == "linux" or sys.platform == "linux2":
            cmd = '{0} {1} {2} -e o,h -o {3} {4}'.format(
            generator, generator_flag, function_flag, builddir, target_flags)
        elif sys.platform == "darwin":
            cmd = 'export DYLD_LIBRARY_PATH={5} && {0} {1} {2} -e o,h -o {3} {4}'.format(
            generator, generator_flag, function_flag, builddir, target_flags, env['HALIDE_PATH'] + '/bin/')

        if verbose:
            print('Calling generator')
            print('\t' + cmd)
        subprocess.call(cmd, shell=True)

0.1.5 release

It was a while since the last release and some bugfixes has been done since. How about a new release so users can get the newest version from pip?

Anderson2021 autoscheduler triggers "producer_store_instances > 0"

Working draft for debugging purpose: https://github.com/antonysigma/proximal/tree/debug-producer-error

Observations: when we define the Halide Func and then return them as std::tuple, the generator can capture the algorithm pipeline and schedule it with Mullapudi2016 autoscheduler. But not Anderson2021. The autoscheduler reports:

Unhandled exception: Internal Error at .../autoschedulers/anderson2021/LoopNest.cpp:2747
triggered by user code at :
Condition failed: producer_store_instances > 0:

The same assertion failure happens with C++ structured bindings, as well as passing return values as function reference.

The offending line is shown below:

using Halide::Func
template<size_t N> using FuncTuple = std::array<Func, N>;
std::vector<Func> v_list(n_iter);
std::vector<FuncTuple<psi_size>> z_list(n_iter);
std::vector<FuncTuple<psi_size>> u_list(n_iter);

for (size_t i = 0; i < n_iter; i++) {
    std::tie(v_list[i], z_list[i], u_list[i]) = algorithm::linearized_admm::iterate(
        v, z_prev, u_prev, K, omega_fn, psi_fns, lmb, mu, input);
}

See also: #67 .

Feature suggestion for mul_elemwise class

I suggest the following changes for the linear operation mul_elemwise:

  1. Check if the two input variables are broadcastable and if so allow a broadcasted multiplication.
  2. Multiply not only with a fixed constant but also with an arbitrary variable (e.g. scalar or matrix).

Is the current state intentionally or does it make sense to send a PR with change suggestions?

Patch_NLM CUDA availability and missing Halide compilation flags

If implementation modus Halide is activated the patch_NLM.py prox function uses an OpenCV CUDA implementation of the NLM denoiser. Besides checking for the correct dimensions I think the if statement should also check if CUDA is actually available. For this the cuda_available variable from cuda_codegen.py could be exported as a flag which is package-wide available.

Furthermore the compilation of the prox_NLM.cpp throws multiple undefinied symbol errors e.g.

...
OSError: XXX/python3.6/site-packages/proximal/halide/build/prox_NLM.so: undefined symbol: NLM_extern

which I resolved by adding the following compilation flags to patch_NLM.py:

ext_libs = '-lopencv_core', '-lopencv_imgproc', '-lopencv_cudaarithm', '-lopencv_cudev', '-lopencv_photo', '-lm'
ext_srcs = ['external/external_NLM.cpp']
Halide('prox_NLM.cpp', external_source=ext_srcs, external_libs=ext_libs).prox_NLM(tmpin, 1. / rho, self.paramsh, self.tmpout)

Is this a known error?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.