Hello,

I am taking a second look at the possibility of interfacing Reduce to the NLopt numerical optimization package,
http://ab-initio.mit.edu/wiki/index.php/NLopt.

First, I looked at packages/foreign/gurobi. The file gurobi.tst seems to imply that, in the end, Gurobi is called via Lisp, not Reduce.
Is that correct? Wouldn't it be desirable to be able to call Gurobi from Reduce itself?  But maybe I'm missing something.

Having looked at the C interface for Gurobi, I thought that since NLopt comes with an interface to Scheme, this might make the interfacing task easier.  (I'm making this statement without knowing much about Reduce's internals, lisp versions, etc., so I may be off the mark.) 

Anyhow, I have NLopt is installed in /opt/nlopt.  Then /opt/nlopt/lib contains the library libnlopt_guile.so, and /opt/nlopt/share/guile/site/nlopt.scm is an interface file that looks like this:




(define-module (nlopt))

(load-extension "libnlopt_guile.so" "SWIG_init")

(set! NLOPT-GN-DIRECT (NLOPT-GN-DIRECT))
(set! NLOPT-GN-DIRECT-L (NLOPT-GN-DIRECT-L))
(set! NLOPT-GN-DIRECT-L-RAND (NLOPT-GN-DIRECT-L-RAND))
(set! NLOPT-GN-DIRECT-NOSCAL (NLOPT-GN-DIRECT-NOSCAL))
(set! NLOPT-GN-DIRECT-L-NOSCAL (NLOPT-GN-DIRECT-L-NOSCAL))
(set! NLOPT-GN-DIRECT-L-RAND-NOSCAL (NLOPT-GN-DIRECT-L-RAND-NOSCAL))
(set! NLOPT-GN-ORIG-DIRECT (NLOPT-GN-ORIG-DIRECT))
(set! NLOPT-GN-ORIG-DIRECT-L (NLOPT-GN-ORIG-DIRECT-L))
...
...
(export new-nlopt-doublevector
        nlopt-doublevector-length
        nlopt-doublevector-empty?
        nlopt-doublevector-clear!
        nlopt-doublevector-push!
        nlopt-doublevector-pop!
        nlopt-doublevector-ref
        nlopt-doublevector-set!
        delete-nlopt-doublevector
        nlopt-get-initial-step
        NLOPT-GN-DIRECT
        NLOPT-GN-DIRECT-L
        NLOPT-GN-DIRECT-L-RAND
        NLOPT-GN-DIRECT-NOSCAL
        NLOPT-GN-DIRECT-L-NOSCAL
        NLOPT-GN-DIRECT-L-RAND-NOSCAL
        NLOPT-GN-ORIG-DIRECT
       ...
       ...
        NLOPT-XTOL-REACHED
        NLOPT-MAXEVAL-REACHED
        NLOPT-MAXTIME-REACHED
        new-nlopt-roundoff-limited
        delete-nlopt-roundoff-limited
        new-nlopt-forced-stop
        delete-nlopt-forced-stop
        delete-nlopt-opt
        new-nlopt-opt
        nlopt-opt-optimize
        nlopt-opt-last-optimize-result
        nlopt-opt-last-optimum-value
        nlopt-opt-get-algorithm)




And here is an example of Scheme code that solves a simple problem using NLopt.


;; To run, invoke guile as
;;       guile -L /opt/nlopt/share/guile/site
;; so it can find the module nlopt.scm.

; Simple nonlinearly-constrained minimization problem:
; \min_{x\in\mathbb{R}^2} \sqrt{x_2}
; subject to
; x_2 \geq 0, x_2 \geq (a_1 x_1 + b_1)^3, and x_2 \geq (a_2 x_1 + b_2)^3
; for parameters a1=2, b1=0, a2=-1, b2=1.


(setenv "LD_LIBRARY_PATH" "/opt/nlopt/lib")
(use-modules (nlopt))

(define (fx x grad)
  (if grad
      (begin
        (vector-set! grad 0 0.0)
        (vector-set! grad 1 (/ 0.5 (sqrt (vector-ref x 1))))))
  (sqrt (vector-ref x 1)))

(define (constr x grad a b)
  (let ((x0 (vector-ref x 0)) (x1 (vector-ref x 1)))
    (if grad
        (begin
          (vector-set! grad 0 (* 3 a (expt (+ (* a x0) b) 2)))
          (vector-set! grad 1 -1.0)))
    (- (expt (+ (* a x0) b) 3) x1)))

; Set the algorithm and dimension of problem:
(define opt (new-nlopt-opt NLOPT-LD-MMA 2))
(nlopt-opt-set-lower-bounds opt (vector (- (inf)) 0))
; Add the constraints
(nlopt-opt-add-inequality-constraint opt (lambda (x grad)
                                           (constr x grad 2 0))
                                     1e-8)
(nlopt-opt-add-inequality-constraint opt (lambda (x grad)
                                           (constr x grad -1 1))
                                     1e-8)
; Define the objective:
(nlopt-opt-set-min-objective opt fx)
(nlopt-opt-set-xtol-rel opt 1e-4)

; initial guess for x:
(define x (nlopt-opt-optimize opt (vector 1.234 5.678)))
(define minf (nlopt-opt-last-optimum-value opt))
(define result (nlopt-opt-last-optimize-result opt))

(display result)



So, after all this, what would be involved in implementing an interface to Reduce that would work just for this example code? 
Just to provide a starting point.

                                    Kostas