Esempio n. 1
0
    def __solve__(self,
                  opt_problem,
                  sens_type='FD',
                  store_sol=True,
                  store_hst=False,
                  hot_start=False,
                  disp_opts=False,
                  sens_mode='',
                  sens_step={},
                  *args,
                  **kwargs):
        """Run Optimizer (Optimize Routine)

        **Keyword arguments:**

        - opt_problem -> INST: Optimization instance
        - sens_type -> STR/FUNC: Gradient type, *Default* = 'FD' 
        - store_sol -> BOOL: Store solution in Optimization class flag,
                       *Default* = True 
        - disp_opts -> BOOL: Flag to display options in solution text,
                       *Default* = False
        - store_hst -> BOOL/STR: Flag/filename to store optimization history,
                       *Default* = False
        - hot_start -> BOOL/STR: Flag/filename to read optimization history,
                       *Default* = False
        - sens_mode -> STR: Flag for parallel gradient calculation,
                       *Default* = ''
        - sens_step -> FLOAT: Sensitivity setp size,
                       *Default* = {} [corresponds to 1e-6 (FD), 1e-20(CS)]

        Additional arguments and keyword arguments are passed to the
        objective function call.

        Documentation last updated:  February. 2, 2011 - Ruben E. Perez

        """
        if self.poa and (sens_mode.lower() == 'pgc'):
            raise NotImplementedError(
                "pyKSOPT - Current implementation only allows single level"
                " parallelization, either 'POA' or 'pgc'")

        if self.poa or (sens_mode.lower() == 'pgc'):
            try:
                import mpi4py
                from mpi4py import MPI
            except ImportError:
                print('pyKSOPT: Parallel objective Function Analysis '
                      'requires mpi4py')

            comm = MPI.COMM_WORLD
            nproc = comm.Get_size()
            if mpi4py.__version__[0] == '0':
                Bcast = comm.Bcast
            # elif mpi4py.__version__[0] == '1':
            else:  # version can be 1, 2, 3 .... or more
                Bcast = comm.bcast

            self.pll = True
            self.myrank = comm.Get_rank()
        else:
            self.pll = False
            self.myrank = 0

        myrank = self.myrank

        def_fname = self.options['IFILE'][1].split('.')[0]
        hos_file, log_file, tmp_file = self._setHistory(
            opt_problem.name, store_hst, hot_start, def_fname)

        gradient = Gradient(opt_problem, sens_type, sens_mode, sens_step)

        # ======================================================================
        # KSOPT - Objective/Constraint Values Function
        # ======================================================================
        def ksobj(nv, no, nc, x, f, g):

            # Variables Groups Handling
            if opt_problem.use_groups:
                xg = {}
                for group in group_ids.keys():
                    if group_ids[group][1] - group_ids[group][0] == 1:
                        xg[group] = x[group_ids[group][0]]
                    else:
                        xg[group] = x[group_ids[group][0]:group_ids[group][1]]
                xn = xg
            else:
                xn = x

            # Flush Output Files
            self.flushFiles()

            # Evaluate User Function
            fail = 0
            ff = []
            gg = []
            if myrank == 0:
                if self.h_start:
                    [vals,
                     hist_end] = hos_file.read(ident=['obj', 'con', 'fail'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        [ff, gg, fail] = [
                            vals['obj'][0][0], vals['con'][0],
                            int(vals['fail'][0][0])
                        ]

            if self.pll:
                self.h_start = Bcast(self.h_start, root=0)

            if self.h_start and self.pll:
                [ff, gg, fail] = Bcast([ff, gg, fail], root=0)
            elif not self.h_start:
                [ff, gg, fail] = opt_problem.obj_fun(xn, *args, **kwargs)

            # Store History
            if myrank == 0:
                if self.sto_hst:
                    log_file.write(x, 'x')
                    log_file.write(ff, 'obj')
                    log_file.write(gg, 'con')
                    log_file.write(fail, 'fail')

            # Objective Assignment
            if isinstance(ff, float):
                ff = [ff]

            for i in range(len(opt_problem.objectives.keys())):
                if isinstance(ff[i], complex):
                    f[i] = ff[i].astype(float)
                else:
                    f[i] = ff[i]

            # Constraints Assigment
            for i in range(len(opt_problem.constraints.keys())):
                if isinstance(gg[i], complex):
                    g[i] = gg[i].astype(float)
                else:
                    g[i] = gg[i]

            return f, g

        # ======================================================================
        # KSOPT - Objective/Constraint Gradients Function
        # ======================================================================
        def ksgrd(nv, no, nc, x, f, g, df, dg):

            if self.h_start:
                dff = []
                dgg = []
                if myrank == 0:
                    [vals,
                     hist_end] = hos_file.read(ident=['grad_obj', 'grad_con'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        dff = vals['grad_obj'][0].reshape(
                            (len(opt_problem.objectives.keys()),
                             len(opt_problem.variables.keys())))
                        dgg = vals['grad_con'][0].reshape(
                            (len(opt_problem.constraints.keys()),
                             len(opt_problem.variables.keys())))

                if self.pll:
                    self.h_start = Bcast(self.h_start, root=0)

                if self.h_start and self.pll:
                    [dff, dgg] = Bcast([dff, dgg], root=0)

            if not self.h_start:
                dff, dgg = gradient.getGrad(x, group_ids, f, g, *args,
                                            **kwargs)

            # Store History
            if self.sto_hst and (myrank == 0):
                log_file.write(dff, 'grad_obj')
                log_file.write(dgg, 'grad_con')

            # Gradient Assignment
            for i in range(len(opt_problem.variables.keys())):
                for j in range(len(opt_problem.objectives.keys())):
                    df[j, i] = dff[j, i]

                for j in range(len(opt_problem.constraints.keys())):
                    dg[j, i] = dgg[j, i]

            return df, dg

        # Variables Handling
        nvar = len(opt_problem.variables.keys())
        xl = []
        xu = []
        xx = []
        for key in opt_problem.variables.keys():
            if opt_problem.variables[key].type == 'c':
                xl.append(opt_problem.variables[key].lower)
                xu.append(opt_problem.variables[key].upper)
                xx.append(opt_problem.variables[key].value)
            elif opt_problem.variables[key].type == 'i':
                raise IOError('KSOPT cannot handle integer design variables')
            elif opt_problem.variables[key].type == 'd':
                raise IOError('KSOPT cannot handle discrete design variables')

        xl = numpy.array(xl)
        xu = numpy.array(xu)
        xx = numpy.array(xx)

        # Variables Groups Handling
        group_ids = {}
        if opt_problem.use_groups:
            k = 0
            for key in opt_problem.vargroups.keys():
                group_len = len(opt_problem.vargroups[key]['ids'])
                group_ids[opt_problem.vargroups[key]['name']] = [
                    k, k + group_len
                ]
                k += group_len

        # Constraints Handling
        ncon = len(opt_problem.constraints.keys())
        gg = []
        if ncon > 0:
            for key in opt_problem.constraints.keys():
                if opt_problem.constraints[key].type == 'e':
                    raise IOError('KSOPT cannot handle equality constraints')
                gg.append(opt_problem.constraints[key].value)
            gg = numpy.array(gg, numpy.float)
        else:
            ncon = 1
            gg = numpy.array([0], numpy.float)

        # Objective Handling
        objfunc = opt_problem.obj_fun
        nobj = len(opt_problem.objectives.keys())
        ff = []
        for key in opt_problem.objectives.keys():
            ff.append(opt_problem.objectives[key].value)

        ff = numpy.array(ff, numpy.float)

        # Setup argument list values
        ndv = numpy.array([nvar], numpy.int)
        nob = numpy.array([nobj], numpy.int)
        ncn = numpy.array([ncon], numpy.int)
        nwork0 = 63
        nwork1 = 3 * nobj + ncon + 12 * nvar + nvar * (nvar + 1)
        nwork2 = nobj * nvar + ncon * nvar
        nwork3 = 2 * max(2 * nvar, nobj + ncon)
        nworkS = nwork0 + nwork1 + nwork2 + nwork3
        nwork = numpy.array([nworkS], numpy.int)

        # work = numpy.zeros([nwork], numpy.float)
        # VisibleDeprecationWarning: converting an array with ndim > 0 to an
        # index will result in an error in the future
        work = numpy.zeros(nwork, numpy.float)

        itmax = numpy.array([self.options['ITMAX'][1]], numpy.int)
        rdfun = numpy.array([self.options['RDFUN'][1]], numpy.float)
        rhomin = numpy.array([self.options['RHOMIN'][1]], numpy.float)
        rhomax = numpy.array([self.options['RHOMAX'][1]], numpy.float)
        iout = numpy.array([self.options['IOUT'][1]], numpy.int)
        if myrank == 0:
            if 0 <= self.options['IPRINT'][1] <= 3:
                iprint = numpy.array([self.options['IPRINT'][1]], numpy.int)
            else:
                raise IOError('Incorrect Output Level Setting')
        else:
            iprint = numpy.array([0], numpy.int)

        ifile = self.options['IFILE'][1]
        if iprint > 0:
            if os.path.isfile(ifile):
                os.remove(ifile)

        nfun = numpy.array([0], numpy.int)
        ngrd = numpy.array([0], numpy.int)

        # Run KSOPT
        t0 = time.time()
        ksopt.ksmain(ndv, nob, ncn, xx, xl, xu, ff, gg, work, nwork, itmax,
                     rdfun, rhomin, rhomax, iout, iprint, ifile, nfun, ngrd,
                     ksobj, ksgrd)
        sol_time = time.time() - t0

        if myrank == 0:
            if self.sto_hst:
                log_file.close()
                if tmp_file:
                    hos_file.close()
                    name = hos_file.filename
                    os.remove(name + '.cue')
                    os.remove(name + '.bin')
                    os.rename(name + '_tmp.cue', name + '.cue')
                    os.rename(name + '_tmp.bin', name + '.bin')

        if iprint > 0:
            ksopt.closeunit(self.options['IOUT'][1])

        # Store Results
        sol_inform = {}
        sol_inform['value'] = []
        sol_inform['text'] = {}

        if store_sol:
            sol_name = 'KSOPT Solution to ' + opt_problem.name

            sol_options = copy.copy(self.options)
            # if sol_options.has_key('defaults'):
            if 'defaults' in sol_options:
                del sol_options['defaults']

            sol_evals = nfun[0] + ngrd[0] * nvar

            sol_vars = copy.deepcopy(opt_problem.variables)
            i = 0
            for key in sol_vars.keys():
                sol_vars[key].value = xx[i]
                i += 1

            sol_objs = copy.deepcopy(opt_problem.objectives)
            i = 0
            for key in sol_objs.keys():
                sol_objs[key].value = ff[i]
                i += 1

            if ncon > 0:
                sol_cons = copy.deepcopy(opt_problem.constraints)
                i = 0
                for key in sol_cons.keys():
                    sol_cons[key].value = gg[i]
                    i += 1
            else:
                sol_cons = {}

            sol_lambda = {}

            opt_problem.addSol(self.__class__.__name__,
                               sol_name,
                               objfunc,
                               sol_time,
                               sol_evals,
                               sol_inform,
                               sol_vars,
                               sol_objs,
                               sol_cons,
                               sol_options,
                               display_opts=disp_opts,
                               Lambda=sol_lambda,
                               Sensitivities=sens_type,
                               myrank=myrank,
                               arguments=args,
                               **kwargs)

        return ff, xx, sol_inform
Esempio n. 2
0
    def __solve__(self,
                  opt_problem,
                  sens_type='FD',
                  store_sol=True,
                  store_hst=False,
                  hot_start=False,
                  disp_opts=False,
                  sens_mode='',
                  sens_step={},
                  *args,
                  **kwargs):
        """Run Optimizer (Optimize Routine)

        **Keyword arguments:**

        - opt_problem -> INST: Optimization instance
        - sens_type -> STR/FUNC: Gradient type, *Default* = 'FD' 
        - store_sol -> BOOL: Store solution in Optimization class flag,
                       *Default* = True 
        - disp_opts -> BOOL: Flag to display options in solution text,
                       *Default* = False
        - store_hst -> BOOL/STR: Flag/filename to store optimization history,
                       *Default* = False
        - hot_start -> BOOL/STR: Flag/filename to read optimization history,
                       *Default* = False
        - sens_mode -> STR: Flag for parallel gradient calculation,
                       *Default* = ''
        - sens_step -> FLOAT: Sensitivity setp size,
                       *Default* = {} [corresponds to 1e-6 (FD), 1e-20(CS)]

        Additional arguments and keyword arguments are passed to the objective
        function call.

        Documentation last updated:  February. 2, 2011 - Ruben E. Perez

        """
        nec = 0
        nic = 0
        for key in opt_problem.constraints.keys():
            if opt_problem.constraints[key].type == 'e':
                nec += 1
            if opt_problem.constraints[key].type == 'i':
                nic += 1

        if self.poa and (sens_mode.lower() == 'pgc'):
            raise NotImplementedError("pyFSQP - Current implementation only "
                                      "allows single level parallelization, "
                                      "either 'POA' or 'pgc'")

        if self.poa or (sens_mode.lower() == 'pgc'):
            try:
                import mpi4py
                from mpi4py import MPI
            except ImportError:
                print('pyFSQP: Parallel objective Function Analysis '
                      'requires mpi4py')

            comm = MPI.COMM_WORLD
            nproc = comm.Get_size()
            if mpi4py.__version__[0] == '0':
                Bcast = comm.Bcast
            # elif mpi4py.__version__[0] == '1':
            else:  # version can be 1, 2, 3 .... or more
                Bcast = comm.bcast

            self.pll = True
            self.myrank = comm.Get_rank()
        else:
            self.pll = False
            self.myrank = 0

        myrank = self.myrank

        def_fname = self.options['ifile'][1].split('.')[0]
        hos_file, log_file, tmp_file = self._setHistory(
            opt_problem.name, store_hst, hot_start, def_fname)

        gradient = Gradient(opt_problem, sens_type, sens_mode, sens_step,
                            *args, **kwargs)

        # ======================================================================
        # FSQP - Objective/Constraint Values Storage
        # ======================================================================
        def eval(x):
            # Variables Groups Handling
            if opt_problem.use_groups:
                xg = {}
                for group in group_ids.keys():
                    if group_ids[group][1] - group_ids[group][0] == 1:
                        xg[group] = x[group_ids[group][0]]
                    else:
                        xg[group] = x[group_ids[group][0]:group_ids[group][1]]
                xn = xg
            else:
                xn = x

            # Flush Output Files
            self.flushFiles()

            # Evaluate User Function (Real Valued)
            fail = 0
            f = []
            g = []
            if myrank == 0:
                if self.h_start:
                    [vals,
                     hist_end] = hos_file.read(ident=['obj', 'con', 'fail'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        [f, g, fail] = [
                            vals['obj'][0][0], vals['con'][0],
                            int(vals['fail'][0][0])
                        ]

            if self.pll:
                self.h_start = Bcast(self.h_start, root=0)
            # end
            if self.h_start and self.pll:
                [f, g, fail] = Bcast([f, g, fail], root=0)
            elif not self.h_start:
                [f, g, fail] = opt_problem.obj_fun(xn, *args, **kwargs)

            # Store History
            if myrank == 0:
                if self.sto_hst:
                    log_file.write(x, 'x')
                    log_file.write(f, 'obj')
                    log_file.write(g, 'con')
                    log_file.write(fail, 'fail')

            # Objective Assignment
            if isinstance(f, float):
                f = [f]

            for i in range(len(opt_problem.objectives.keys())):
                if isinstance(f[i], complex):
                    ff[i] = f[i].astype(float)
                else:
                    ff[i] = f[i]

            # Constraints Assignment
            i = 0
            for j in range(len(opt_problem.constraints.keys())):
                if isinstance(g[j], complex):
                    gg[i] = g[j].astype(float)
                else:
                    gg[i] = g[j]
                i += 1

            # Gradients
            if self.h_start:
                dff = []
                dgg = []
                if myrank == 0:
                    [vals,
                     hist_end] = hos_file.read(ident=['grad_obj', 'grad_con'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        dff = vals['grad_obj'][0].reshape(
                            (len(opt_problem.objectives.keys()),
                             len(opt_problem.variables.keys())))
                        dgg = vals['grad_con'][0].reshape(
                            (len(opt_problem.constraints.keys()),
                             len(opt_problem.variables.keys())))

                if self.pll:
                    self.h_start = Bcast(self.h_start, root=0)

                if self.h_start and self.pll:
                    [dff, dgg] = Bcast([dff, dgg], root=0)

            if not self.h_start:
                dff, dgg = gradient.getGrad(x, group_ids, f, g, *args,
                                            **kwargs)

            # Store History
            if self.sto_hst and (myrank == 0):
                log_file.write(dff, 'grad_obj')
                log_file.write(dgg, 'grad_con')

            # Store
            self.stored_data['x'] = copy.copy(x)
            self.stored_data['f'] = copy.copy(ff)
            self.stored_data['g'] = copy.copy(gg)
            self.stored_data['df'] = copy.copy(dff)
            self.stored_data['dg'] = copy.copy(dgg)

            return

        # ======================================================================
        # FSQP - Objective Values Function
        # ======================================================================
        def obj(nparam, j, x, fj):

            if (self.stored_data['x'] != x).any():
                eval(x)

            ff = self.stored_data['f']
            if nobj == 1:
                fj = ff
            else:
                if isinstance(ff, list):
                    ff = numpy.array(ff)
                fj = ff[j - 1]

            return fj

        # ======================================================================
        # FSQP - Constraint Values Function
        # ======================================================================
        def cntr(nparam, j, x, gj):

            # for given j, assign to gj the value of the jth constraint
            # evaluated at x

            if (self.stored_data['x'] != x).any():
                eval(x)

            gg = self.stored_data['g']
            if j <= nic:
                jg = nec + (j - 1)
            else:
                jg = (j - 1) - nic

            gj = gg[jg]

            return gj

        # ======================================================================
        # FSQP - Objective Gradients Function
        # ======================================================================
        def gradobj(nparam, j, x, gradfj, obj):

            # assign to gradfj the gradient of the jth objective
            # function evaluated at x

            if (self.stored_data['x'] != x).any():
                eval(x)

            df = self.stored_data['df']
            for i in range(len(opt_problem.variables.keys())):
                gradfj[i] = df[j - 1, i]

            return gradfj

        # ======================================================================
        # FSQP - Constraint Gradients Function
        # ======================================================================
        def gradcntr(nparam, j, x, gradgj, obj):

            # assign to gradgj the gradient of the jth constraint evaluated at x

            if (self.stored_data['x'] != x).any():
                eval(x)

            dg = self.stored_data['dg']
            if j <= nic:
                jg = nec + (j - 1)
            else:
                jg = (j - 1) - nic
            gradgj = dg[jg]

            return gradgj

        # Variables Handling
        nvar = len(opt_problem.variables.keys())
        xl = []
        xu = []
        xx = []
        for key in opt_problem.variables.keys():
            xl.append(opt_problem.variables[key].lower)
            xu.append(opt_problem.variables[key].upper)
            xx.append(opt_problem.variables[key].value)

        xl = numpy.array(xl)
        xu = numpy.array(xu)
        xx = numpy.array(xx)

        # Variables Groups Handling
        group_ids = {}
        if opt_problem.use_groups:
            k = 0
            for key in opt_problem.vargroups.keys():
                group_len = len(opt_problem.vargroups[key]['ids'])
                group_ids[opt_problem.vargroups[key]['name']] = [
                    k, k + group_len
                ]
                k += group_len

        # Constraints Handling
        ncon = len(opt_problem.constraints.keys())
        neqc = 0
        gg = []
        if ncon > 0:
            for key in opt_problem.constraints.keys():
                if opt_problem.constraints[key].type == 'e':
                    neqc += 1
                gg.append(opt_problem.constraints[key].value)
            gg = numpy.array(gg, numpy.float)
        else:
            gg = numpy.array([0], numpy.float)

        # Objective Handling
        objfunc = opt_problem.obj_fun
        nobj = len(opt_problem.objectives.keys())
        ff = []
        for key in opt_problem.objectives.keys():
            ff.append(opt_problem.objectives[key].value)
        ff = numpy.array(ff, numpy.float)

        # Setup argument list values
        nparam = numpy.array([nvar], numpy.int)
        nf = numpy.array([nobj], numpy.int)
        nineqn = numpy.array([ncon - neqc], numpy.int)
        nineq = nineqn
        neqn = numpy.array([neqc], numpy.int)
        neq = neqn
        mode = numpy.array([self.options['mode'][1]], numpy.int)
        if myrank == 0:
            if self.options['iprint'][1] >= 0:
                iprint = numpy.array([self.options['iprint'][1]], numpy.int)
            else:
                raise IOError('Incorrect Output Level Setting')
        else:
            iprint = numpy.array([0], numpy.int)

        iout = numpy.array([self.options['iout'][1]], numpy.int)
        ifile = self.options['ifile'][1]
        if iprint > 0:
            if os.path.isfile(ifile):
                os.remove(ifile)

        miter = numpy.array([self.options['miter'][1]], numpy.int)
        inform = numpy.array([0], numpy.int)
        bigbnd = numpy.array([self.options['bigbnd'][1]], numpy.float)
        epstol = numpy.array([self.options['epstol'][1]], numpy.float)
        epsneq = numpy.array([self.options['epseqn'][1]], numpy.float)
        udelta = numpy.array([0], numpy.float)
        iwsizeM = 6 * nvar + 8 * max([1, ncon]) + 7 * max([1, nobj]) + 30
        iwsize = numpy.array([iwsizeM], numpy.int)
        iw = numpy.zeros([iwsize], numpy.float)
        nwsizeM = 4 * nvar**2 + 5 * max([1, ncon]) * nvar + 3 * max([
            1, nobj
        ]) * nvar + 26 * (nvar + max([1, nobj])) + 45 * max([1, ncon]) + 100
        nwsize = numpy.array([nwsizeM], numpy.int)
        w = numpy.zeros([nwsize], numpy.float)

        # Storage Arrays
        self.stored_data = {}
        self.stored_data['x'] = {}  # numpy.zeros([nvar],float)
        self.stored_data['f'] = {}  # numpy.zeros([nobj],float)
        self.stored_data['g'] = {}  # numpy.zeros([ncon],float)
        self.stored_data['df'] = {}  # numpy.zeros([nvar],float)
        self.stored_data['dg'] = {}  # numpy.zeros([ncon,nvar],float)

        # Run FSQP
        t0 = time.time()
        ffsqp.ffsqp(nparam, nf, nineqn, nineq, neqn, neq, mode, iprint, miter,
                    inform, bigbnd, epstol, epsneq, udelta, xl, xu, xx, ff, gg,
                    iw, iwsize, w, nwsize, obj, cntr, gradobj, gradcntr, iout,
                    ifile)
        sol_time = time.time() - t0

        if myrank == 0:
            if self.sto_hst:
                log_file.close()
                if tmp_file:
                    hos_file.close()
                    name = hos_file.filename
                    os.remove(name + '.cue')
                    os.remove(name + '.bin')
                    os.rename(name + '_tmp.cue', name + '.cue')
                    os.rename(name + '_tmp.bin', name + '.bin')

        if iprint > 0:
            ffsqp.closeunit(self.options['iout'][1])

        # Store Results
        sol_inform = {}
        sol_inform['value'] = inform[0]
        sol_inform['text'] = self.getInform(inform[0])

        if store_sol:

            sol_name = 'FSQP Solution to ' + opt_problem.name

            sol_options = copy.copy(self.options)
            # if sol_options.has_key('defaults'):
            if 'defaults' in sol_options:
                del sol_options['defaults']

            sol_evals = 0

            sol_vars = copy.deepcopy(opt_problem.variables)
            i = 0
            for key in sol_vars.keys():
                sol_vars[key].value = xx[i]
                i += 1

            sol_objs = copy.deepcopy(opt_problem.objectives)
            i = 0
            for key in sol_objs.keys():
                sol_objs[key].value = ff[i]
                i += 1

            if ncon > 0:
                sol_cons = copy.deepcopy(opt_problem.constraints)
                i = 0
                for key in sol_cons.keys():
                    sol_cons[key].value = gg[i]
                    i += 1
            else:
                sol_cons = {}

            if ncon > 0:
                sol_lambda = numpy.zeros(ncon, float)
                for i in range(ncon):
                    sol_lambda[i] = w[nvar + i]
            else:
                sol_lambda = {}

            opt_problem.addSol(self.__class__.__name__,
                               sol_name,
                               objfunc,
                               sol_time,
                               sol_evals,
                               sol_inform,
                               sol_vars,
                               sol_objs,
                               sol_cons,
                               sol_options,
                               display_opts=disp_opts,
                               Lambda=sol_lambda,
                               Sensitivities=sens_type,
                               myrank=myrank,
                               arguments=args,
                               **kwargs)

        return ff, xx, sol_inform
Esempio n. 3
0
    def __solve__(self,
                  opt_problem,
                  sens_type='FD',
                  store_sol=True,
                  disp_opts=False,
                  store_hst=False,
                  hot_start=False,
                  sens_mode='',
                  sens_step={},
                  *args,
                  **kwargs):
        """Run Optimizer (Optimize Routine)
        
        **Keyword arguments:**
        
        - opt_problem -> INST: Optimization instance
        - sens_type -> STR/FUNC: Gradient type, *Default* = 'FD' 
        - store_sol -> BOOL: Store solution in Optimization class flag,
                       *Default* = True 
        - disp_opts -> BOOL: Flag to display options in solution text,
                       *Default* = False
        - store_hst -> BOOL/STR: Flag/filename to store optimization history,
                       *Default* = False
        - hot_start -> BOOL/STR: Flag/filename to read optimization history,
                       *Default* = False
        - sens_mode -> STR: Flag for parallel gradient calculation,
                       *Default* = ''
        - sens_step -> FLOAT: Sensitivity step size,
                       *Default* = {} [corresponds to 1e-6 (FD), 1e-20(CS)]
        
        Additional arguments and keyword arguments are passed to the objective
        function call.
        
        Documentation last updated:  February. 2, 2011 - Peter W. Jansen

        """
        if self.poa and (sens_mode.lower() == 'pgc'):
            raise NotImplementedError("pySLSQP - Current implementation only "
                                      "allows single level parallelization, "
                                      "either 'POA' or 'pgc'")

        if self.poa or (sens_mode.lower() == 'pgc'):
            try:
                import mpi4py
                from mpi4py import MPI
            except ImportError:
                print("pySLSQP: Parallel objective Function Analysis "
                      "requires mpi4py")

            comm = MPI.COMM_WORLD
            nproc = comm.Get_size()
            if mpi4py.__version__[0] == '0':
                Bcast = comm.Bcast
            # elif mpi4py.__version__[0] == '1':
            else:  # version can be 1, 2, 3 .... or more
                Bcast = comm.bcast
            self.pll = True
            self.myrank = comm.Get_rank()
        else:
            self.pll = False
            self.myrank = 0

        myrank = self.myrank

        def_fname = self.options['IFILE'][1].split('.')[0]
        hos_file, log_file, tmp_file = self._setHistory(
            opt_problem.name, store_hst, hot_start, def_fname)

        gradient = Gradient(opt_problem, sens_type, sens_mode, sens_step)

        # ======================================================================
        # SLSQP - Objective/Constraint Values Function
        # ======================================================================
        def slfunc(m, me, la, n, f, g, x):

            # Variables Groups Handling
            if opt_problem.use_groups:
                xg = {}
                for group in group_ids.keys():
                    if group_ids[group][1] - group_ids[group][0] == 1:
                        xg[group] = x[group_ids[group][0]]
                    else:
                        xg[group] = x[group_ids[group][0]:group_ids[group][1]]
                xn = xg
            else:
                xn = x

            # Flush Output Files
            self.flushFiles()

            # Evaluate User Function
            fail = 0
            ff = []
            gg = []
            if myrank == 0:
                if self.h_start:
                    [vals,
                     hist_end] = hos_file.read(ident=['obj', 'con', 'fail'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        [ff, gg, fail] = [
                            vals['obj'][0][0], vals['con'][0],
                            int(vals['fail'][0][0])
                        ]

            if self.pll:
                self.h_start = Bcast(self.h_start, root=0)

            if self.h_start and self.pll:
                [ff, gg, fail] = Bcast([ff, gg, fail], root=0)
            elif not self.h_start:
                [ff, gg, fail] = opt_problem.obj_fun(xn, *args, **kwargs)

            # Store History
            if myrank == 0:
                if self.sto_hst:
                    log_file.write(x, 'x')
                    log_file.write(ff, 'obj')
                    log_file.write(gg, 'con')
                    log_file.write(fail, 'fail')

            # Objective Assignment
            if isinstance(ff, complex):
                f = ff.astype(float)
            else:
                f = ff

            # Constraints Assignment (negative gg as slsqp uses g(x) >= 0)
            for i in range(len(opt_problem.constraints.keys())):
                if isinstance(gg[i], complex):
                    g[i] = -gg[i].astype(float)
                else:
                    g[i] = -gg[i]

            return f, g

        # ======================================================================
        # SLSQP - Objective/Constraint Gradients Function
        # ======================================================================
        def slgrad(m, me, la, n, f, g, df, dg, x):

            if self.h_start:
                dff = []
                dgg = []
                if myrank == 0:
                    [vals,
                     hist_end] = hos_file.read(ident=['grad_obj', 'grad_con'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        dff = vals['grad_obj'][0].reshape(
                            (len(opt_problem.objectives.keys()),
                             len(opt_problem.variables.keys())))
                        dgg = vals['grad_con'][0].reshape(
                            (len(opt_problem.constraints.keys()),
                             len(opt_problem.variables.keys())))

                if self.pll:
                    self.h_start = Bcast(self.h_start, root=0)

                if self.h_start and self.pll:
                    [dff, dgg] = Bcast([dff, dgg], root=0)

            if not self.h_start:
                dff, dgg = gradient.getGrad(x, group_ids, [f], -g, *args,
                                            **kwargs)

            # Store History
            if self.sto_hst and (myrank == 0):
                log_file.write(dff, 'grad_obj')
                log_file.write(dgg, 'grad_con')

            # Gradient Assignment
            for i in range(len(opt_problem.variables.keys())):
                df[i] = dff[0, i]
                for jj in range(len(opt_problem.constraints.keys())):
                    dg[jj, i] = -dgg[jj, i]

            return df, dg

        # Variables Handling
        n = len(opt_problem.variables.keys())
        xl = []
        xu = []
        xx = []
        for key in opt_problem.variables.keys():
            if opt_problem.variables[key].type == 'c':
                xl.append(opt_problem.variables[key].lower)
                xu.append(opt_problem.variables[key].upper)
                xx.append(opt_problem.variables[key].value)
            elif opt_problem.variables[key].type == 'i':
                raise IOError('SLSQP cannot handle integer design variables')
            elif opt_problem.variables[key].type == 'd':
                raise IOError('SLSQP cannot handle discrete design variables')

        xl = numpy.array(xl)
        xu = numpy.array(xu)
        xx = numpy.array(xx)

        # Variables Groups Handling
        group_ids = {}
        if opt_problem.use_groups:
            k = 0
            for key in opt_problem.vargroups.keys():
                group_len = len(opt_problem.vargroups[key]['ids'])
                group_ids[opt_problem.vargroups[key]['name']] = [
                    k, k + group_len
                ]
                k += group_len

        # Constraints Handling
        m = len(opt_problem.constraints.keys())
        meq = 0
        # gg = []
        if m > 0:
            for key in opt_problem.constraints.keys():
                if opt_problem.constraints[key].type == 'e':
                    meq += 1
                # gg.append(opt_problem.constraints[key].value)
        # gg = numpy.array(gg,numpy.float)

        # Objective Handling
        objfunc = opt_problem.obj_fun
        nobj = len(opt_problem.objectives.keys())
        ff = []
        for key in opt_problem.objectives.keys():
            ff.append(opt_problem.objectives[key].value)
        ff = numpy.array(ff, numpy.float)

        # Setup argument list values
        # la = numpy.array([max(m, 1)], numpy.int)
        la = max(m, 1)

        # gg = numpy.zeros([la], numpy.float)
        # VisibleDeprecationWarning: converting an array with ndim > 0 to an
        # index will result in an error in the future
        gg = numpy.zeros(la, numpy.float)

        n1 = numpy.array([n + 1], numpy.int)
        df = numpy.zeros([n + 1], numpy.float)

        # VisibleDeprecationWarning: converting an array with ndim > 0
        # to an index will result in an error in the future
        # Corrected by the modification of la some lines above
        dg = numpy.zeros([la, n + 1], numpy.float)

        acc = numpy.array([self.options['ACC'][1]], numpy.float)
        maxit = numpy.array([self.options['MAXIT'][1]], numpy.int)
        iprint = numpy.array([self.options['IPRINT'][1]], numpy.int)
        if myrank != 0:
            iprint = -1
        else:
            iprint = self.options['IPRINT'][1]
        # end
        iout = numpy.array([self.options['IOUT'][1]], numpy.int)
        ifile = self.options['IFILE'][1]
        if iprint >= 0:
            if os.path.isfile(ifile):
                os.remove(ifile)

        mode = numpy.array([0], numpy.int)
        mineq = m - meq + 2 * (n + 1)
        lsq = (n + 1) * ((n + 1) + 1) + meq * ((n + 1) + 1) + mineq * (
            (n + 1) + 1)
        lsi = ((n + 1) - meq + 1) * (mineq + 2) + 2 * mineq
        lsei = ((n + 1) + mineq) * ((n + 1) - meq) + 2 * meq + (n + 1)
        slsqpb = (n + 1) * (n / 2) + 2 * m + 3 * n + 3 * (n + 1) + 1
        lwM = lsq + lsi + lsei + slsqpb + n + m
        lw = numpy.array([lwM], numpy.int)

        # w = numpy.zeros([lw], numpy.float)
        # VisibleDeprecationWarning: converting an array with ndim > 0 to an
        # index will result in an error in the future
        w = numpy.zeros(lw, numpy.float)

        ljwM = max(mineq, (n + 1) - meq)
        ljw = numpy.array([ljwM], numpy.int)

        # jw = numpy.zeros([ljw], numpy.intc)
        # VisibleDeprecationWarning: converting an array with ndim > 0 to an
        # index will result in an error in the future
        jw = numpy.zeros(ljw, numpy.intc)

        nfunc = numpy.array([0], numpy.int)
        ngrad = numpy.array([0], numpy.int)

        # Run SLSQP
        t0 = time.time()
        slsqp.slsqp(m, meq, la, n, xx, xl, xu, ff, gg, df, dg, acc, maxit,
                    iprint, iout, ifile, mode, w, lw, jw, ljw, nfunc, ngrad,
                    slfunc, slgrad)
        sol_time = time.time() - t0

        if myrank == 0:
            if self.sto_hst:
                log_file.close()
                if tmp_file:
                    hos_file.close()
                    name = hos_file.filename
                    os.remove(name + '.cue')
                    os.remove(name + '.bin')
                    os.rename(name + '_tmp.cue', name + '.cue')
                    os.rename(name + '_tmp.bin', name + '.bin')

        if iprint > 0:
            slsqp.closeunit(self.options['IOUT'][1])

        # Store Results
        sol_inform = {}
        sol_inform['value'] = mode[0]
        sol_inform['text'] = self.getInform(mode[0])

        if store_sol:

            sol_name = 'SLSQP Solution to ' + opt_problem.name

            sol_options = copy.copy(self.options)
            # if sol_options.has_key('defaults'):
            if 'defaults' in sol_options:
                del sol_options['defaults']

            sol_evals = 0

            sol_vars = copy.deepcopy(opt_problem.variables)
            i = 0
            for key in sol_vars.keys():
                sol_vars[key].value = xx[i]
                i += 1

            sol_objs = copy.deepcopy(opt_problem.objectives)
            i = 0
            for key in sol_objs.keys():
                sol_objs[key].value = ff[i]
                i += 1

            if m > 0:
                sol_cons = copy.deepcopy(opt_problem.constraints)
                i = 0
                for key in sol_cons.keys():
                    sol_cons[key].value = -gg[i]
                    i += 1
            else:
                sol_cons = {}

            sol_lambda = {}

            opt_problem.addSol(self.__class__.__name__,
                               sol_name,
                               objfunc,
                               sol_time,
                               sol_evals,
                               sol_inform,
                               sol_vars,
                               sol_objs,
                               sol_cons,
                               sol_options,
                               display_opts=disp_opts,
                               Lambda=sol_lambda,
                               Sensitivities=sens_type,
                               myrank=myrank,
                               arguments=args,
                               **kwargs)

        return ff, xx, sol_inform
Esempio n. 4
0
    def __solve__(self,
                  opt_problem,
                  sens_type='FD',
                  store_sol=True,
                  store_hst=False,
                  hot_start=False,
                  disp_opts=False,
                  sens_mode='',
                  sens_step={},
                  *args,
                  **kwargs):
        """Run Optimizer (Optimize Routine)

        **Keyword arguments:**

        - opt_problem -> INST: Optimization instance
        - sens_type -> STR/FUNC: Gradient type, *Default* = 'FD' 
        - store_sol -> BOOL: Store solution in Optimization class flag,
                       *Default* = True 
        - disp_opts -> BOOL: Flag to display options in solution text,
                       *Default* = False
        - store_hst -> BOOL/STR: Flag/filename to store optimization history,
                       *Default* = False
        - hot_start -> BOOL/STR: Flag/filename to read optimization history,
                       *Default* = False
        - sens_mode -> STR: Flag for parallel gradient calculation,
                       *Default* = ''
        - sens_step -> FLOAT: Sensitivity step size,
                       *Default* = {} [corresponds to 1e-6 (FD), 1e-20(CS)]

        Additional arguments and keyword arguments are passed to the objective
        function call.

        Documentation last updated:  February. 2, 2013 - Ruben E. Perez

        """
        if self.poa and (sens_mode.lower() == 'pgc'):
            raise NotImplementedError("pyFILTERSD - Current implementation "
                                      "only allows single level "
                                      "parallelization, either 'POA' or 'pgc'")

        if self.poa or (sens_mode.lower() == 'pgc'):
            try:
                import mpi4py
                from mpi4py import MPI
            except ImportError:
                print('pyFILTERSD: Parallel objective Function Analysis '
                      'requires mpi4py')

            comm = MPI.COMM_WORLD
            nproc = comm.Get_size()
            if mpi4py.__version__[0] == '0':
                Bcast = comm.Bcast
            # elif mpi4py.__version__[0] == '1':
            else:  # version can be 1, 2, 3 .... or more
                Bcast = comm.bcast

            self.pll = True
            self.myrank = comm.Get_rank()
        else:
            self.pll = False
            self.myrank = 0

        myrank = self.myrank

        def_fname = self.options['ifile'][1].split('.')[0]
        hos_file, log_file, tmp_file = self._setHistory(
            opt_problem.name, store_hst, hot_start, def_fname)

        gradient = Gradient(opt_problem, sens_type, sens_mode, sens_step,
                            *args, **kwargs)

        # ======================================================================
        # filterSD - Objective/Constraint Values Function (Real Valued)
        # ======================================================================
        def functions(n, m, x, f, g, user, iuser):

            # Variables Groups Handling
            if opt_problem.use_groups:
                xg = {}
                for group in group_ids.keys():
                    if group_ids[group][1] - group_ids[group][0] == 1:
                        xg[group] = x[group_ids[group][0]]
                    else:
                        xg[group] = x[group_ids[group][0]:group_ids[group][1]]
                xn = xg
            else:
                xn = x

            # Flush Output Files
            self.flushFiles()

            # Evaluate User Function
            fail = 0
            ff = []
            gg = []
            if myrank == 0:
                if self.h_start:
                    [vals,
                     hist_end] = hos_file.read(ident=['obj', 'con', 'fail'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        [ff, gg, fail] = [
                            vals['obj'][0][0], vals['con'][0],
                            int(vals['fail'][0][0])
                        ]

            if self.pll:
                self.h_start = Bcast(self.h_start, root=0)

            if self.h_start and self.pll:
                [ff, gg, fail] = Bcast([ff, gg, fail], root=0)
            elif not self.h_start:
                [ff, gg, fail] = opt_problem.obj_fun(xn, *args, **kwargs)

            # Store History
            if myrank == 0:
                if self.sto_hst:
                    log_file.write(x, 'x')
                    log_file.write(ff, 'obj')
                    log_file.write(gg, 'con')
                    log_file.write(fail, 'fail')

            # Store
            self.stored_data['x'] = copy.copy(x)
            self.stored_data['f'] = copy.copy(ff)
            self.stored_data['g'] = copy.copy(gg)

            # Objective Assigment
            if isinstance(ff, complex):
                f = ff.astype(float)
            else:
                f = ff

            # Constraints Assigment
            for i in range(len(opt_problem.constraints.keys())):
                if isinstance(gg[i], complex):
                    g[i] = gg[i].astype(float)
                else:
                    g[i] = gg[i]

            return f, g

        # ======================================================================
        # filterSD - Objective/Constraint Gradients Function
        # ======================================================================
        def gradients(n, m, x, a, user, iuser):

            if (self.stored_data['x'] != x).any():
                f, g = functions(n, m, x, [], [], [], [])
            else:
                f = self.stored_data['f']
                g = self.stored_data['g']

            if self.h_start:
                dff = []
                dgg = []
                if myrank == 0:
                    [vals,
                     hist_end] = hos_file.read(ident=['grad_obj', 'grad_con'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        dff = vals['grad_obj'][0].reshape(
                            (len(opt_problem.objectives.keys()),
                             len(opt_problem.variables.keys())))
                        dgg = vals['grad_con'][0].reshape(
                            (len(opt_problem.constraints.keys()),
                             len(opt_problem.variables.keys())))

                if self.pll:
                    self.h_start = Bcast(self.h_start, root=0)

                if self.h_start and self.pll:
                    [dff, dgg] = Bcast([dff, dgg], root=0)

            if not self.h_start:
                #
                dff, dgg = gradient.getGrad(
                    x, group_ids, [f],
                    g[0:len(opt_problem.constraints.keys())], *args, **kwargs)

            # Store History
            if self.sto_hst and (myrank == 0):
                log_file.write(dff, 'grad_obj')
                log_file.write(dgg, 'grad_con')

            # Gradient Assignment
            for i in range(len(opt_problem.variables.keys())):
                a[i, 0] = dff[0, i]

            for i in range(len(opt_problem.variables.keys())):
                for j in range(len(opt_problem.constraints.keys())):
                    a[i, j + 1] = dgg[j, i]

            return a

        # Variables Handling
        nvar = len(opt_problem.variables.keys())
        xl = []
        xu = []
        xx = []
        for key in opt_problem.variables.keys():
            xl.append(opt_problem.variables[key].lower)
            xu.append(opt_problem.variables[key].upper)
            xx.append(opt_problem.variables[key].value)

        xl = numpy.array(xl)
        xu = numpy.array(xu)
        xx = numpy.array(xx)

        # Variables Groups Handling
        group_ids = {}
        if opt_problem.use_groups:
            k = 0
            for key in opt_problem.vargroups.keys():
                group_len = len(opt_problem.vargroups[key]['ids'])
                group_ids[opt_problem.vargroups[key]['name']] = [
                    k, k + group_len
                ]
                k += group_len

        # Constraints Handling
        ncon = len(opt_problem.constraints.keys())
        gg = []
        if ncon > 0:
            for key in opt_problem.constraints.keys():
                if opt_problem.constraints[key].type == 'e':
                    raise IOError(
                        'FILTERSD cannot handle equality constraints')

                gg.append(opt_problem.constraints[key].value)

            gg = numpy.array(gg, numpy.float)
        else:
            ncon = 1
            gg = numpy.array([0], numpy.float)

        # Objective Handling
        objfunc = opt_problem.obj_fun
        nobj = len(opt_problem.objectives.keys())
        ff = []
        for key in opt_problem.objectives.keys():
            ff.append(opt_problem.objectives[key].value)

        ff = numpy.array(ff, numpy.float)

        # Setup argument list values
        nn = numpy.array([nvar], numpy.int)

        mm = numpy.array([ncon], numpy.int)
        # al = numpy.zeros([mm], numpy.float)
        # VisibleDeprecationWarning: converting an array with ndim > 0 to an
        # index will result in an error in the future
        al = numpy.zeros(mm, numpy.float)

        ubd = numpy.array([self.options['ubd'][1]], numpy.float)
        rho = numpy.array([self.options['rho'][1]], numpy.float)
        htol = numpy.array([self.options['htol'][1]], numpy.float)
        rgtol = numpy.array([self.options['rgtol'][1]], numpy.float)
        maxit = numpy.array([self.options['maxit'][1]], numpy.int)
        maxgr = numpy.array([self.options['maxgr'][1]], numpy.int)
        dchk = numpy.array([self.options['dchk'][1]], numpy.int)
        dtol = numpy.array([self.options['dtol'][1]], numpy.float)
        if myrank == 0:
            if self.options['iprint'][1] >= 0:
                iprint = numpy.array([self.options['iprint'][1]], numpy.int)
            else:
                raise IOError('Incorrect Output Level Setting')
        else:
            iprint = numpy.array([0], numpy.int)

        iout = numpy.array([self.options['iout'][1]], numpy.int)
        ifile = self.options['ifile'][1]
        if iprint > 0:
            if os.path.isfile(ifile):
                os.remove(ifile)

        ifail = numpy.array([0], numpy.int)
        nfevs = numpy.array([0], numpy.int)
        ngevs = numpy.array([0], numpy.int)

        # Storage Arrays
        self.stored_data = {}
        self.stored_data['x'] = {}
        self.stored_data['f'] = {}
        self.stored_data['g'] = {}

        # Run filterSD
        t0 = time.time()
        filtersd.filtersd_wrap(nn, mm, xx, xl, xu, al, ff, gg, inf, ubd, rho,
                               htol, rgtol, maxit, maxgr, dchk, dtol, iprint,
                               iout, ifile, ifail, nfevs, ngevs, functions,
                               gradients)
        sol_time = time.time() - t0

        if myrank == 0:
            if self.sto_hst:
                log_file.close()
                if tmp_file:
                    hos_file.close()
                    name = hos_file.filename
                    os.remove(name + '.cue')
                    os.remove(name + '.bin')
                    os.rename(name + '_tmp.cue', name + '.cue')
                    os.rename(name + '_tmp.bin', name + '.bin')

        if iprint > 0:
            filtersd.closeunit(self.options['iout'][1])

        # Store Results
        sol_inform = {}
        sol_inform['value'] = ifail[0]
        sol_inform['text'] = self.getInform(ifail[0])

        if store_sol:

            sol_name = 'FILTERSD Solution to ' + opt_problem.name

            sol_options = copy.copy(self.options)
            # if sol_options.has_key('defaults'):
            if 'defaults' in sol_options:
                del sol_options['defaults']

            sol_evals = nfevs[0] + ngevs[0] * nvar

            sol_vars = copy.deepcopy(opt_problem.variables)
            i = 0
            for key in sol_vars.keys():
                sol_vars[key].value = xx[i]
                i += 1

            sol_objs = copy.deepcopy(opt_problem.objectives)
            i = 0
            for key in sol_objs.keys():
                sol_objs[key].value = ff[i]
                i += 1

            if ncon > 0:
                sol_cons = copy.deepcopy(opt_problem.constraints)
                i = 0
                for key in sol_cons.keys():
                    sol_cons[key].value = gg[i]
                    i += 1
            else:
                sol_cons = {}

            if ncon > 0:
                sol_lambda = numpy.zeros(ncon, float)
                for i in range(ncon):
                    sol_lambda[i] = al[i]
            else:
                sol_lambda = {}

            opt_problem.addSol(self.__class__.__name__,
                               sol_name,
                               objfunc,
                               sol_time,
                               sol_evals,
                               sol_inform,
                               sol_vars,
                               sol_objs,
                               sol_cons,
                               sol_options,
                               display_opts=disp_opts,
                               Lambda=sol_lambda,
                               Sensitivities=sens_type,
                               myrank=myrank,
                               arguments=args,
                               **kwargs)

            time.sleep(0)

        return ff, xx, sol_inform
Esempio n. 5
0
    def __solve__(self,
                  opt_problem,
                  sens_type='FD',
                  store_sol=True,
                  disp_opts=False,
                  store_hst=False,
                  hot_start=False,
                  sens_mode='',
                  sens_step={},
                  *args,
                  **kwargs):
        """Run Optimizer (Optimize Routine)
        
        **Keyword arguments:**
        
        - opt_problem -> INST: Optimization instance
        - sens_type -> STR/FUNC: Gradient type, *Default* = 'FD' 
        - store_sol -> BOOL: Store solution in Optimization class flag,
                       *Default* = True 
        - disp_opts -> BOOL: Flag to display options in solution text,
                       *Default* = False
        - store_hst -> BOOL/STR: Flag/filename to store optimization history,
                       *Default* = False
        - hot_start -> BOOL/STR: Flag/filename to read optimization history,
                       *Default* = False
        - sens_mode -> STR: Flag for parallel gradient calculation,
                       *Default* = ''
        - sens_step -> FLOAT: Sensitivity setp size,
                       *Default* = {} [corresponds to 1e-6 (FD), 1e-20(CS)]
        
        Additional arguments and keyword arguments are passed to the
        objective function call,
        
        Documentation last updated:  February. 2, 2011 - Peter W. Jansen

        """
        if self.poa and (sens_mode.lower() == 'pgc'):
            raise NotImplementedError(
                "pyGCMMA - Current implementation only allows single level "
                "parallelization, either 'POA' or 'pgc'")

        if self.poa or (sens_mode.lower() == 'pgc'):
            try:
                import mpi4py
                from mpi4py import MPI
            except ImportError:
                print('pyGCMMA: Parallel objective Function Analysis'
                      'requires mpi4py')

            comm = MPI.COMM_WORLD
            nproc = comm.Get_size()
            if mpi4py.__version__[0] == '0':
                Bcast = comm.Bcast
            # elif mpi4py.__version__[0] == '1':
            else:  # version can be 1, 2, 3 .... or more
                Bcast = comm.bcast

            self.pll = True
            self.myrank = comm.Get_rank()
        else:
            self.pll = False
            self.myrank = 0

        myrank = self.myrank

        def_fname = self.options['IFILE'][1].split('.')[0]
        hos_file, log_file, tmp_file = self._setHistory(
            opt_problem.name, store_hst, hot_start, def_fname)

        gradient = Gradient(opt_problem, sens_type, sens_mode, sens_step)

        # ======================================================================
        # GCMMA - Objective/Constraint Values Function
        # ======================================================================
        def func1(m, n, xmma, f0new, fnew):
            # Variables Groups Handling
            if opt_problem.use_groups:
                xg = {}
                for group in group_ids.keys():
                    if group_ids[group][1] - group_ids[group][0] == 1:
                        xg[group] = xmma[group_ids[group][0]]
                    else:
                        xg[group] = xmma[
                            group_ids[group][0]:group_ids[group][1]]
                xn = xg
            else:
                xn = xmma

            # Flush Output Files
            self.flushFiles()

            # Evaluate User Function (Real Valued)
            fail = 0
            f = []
            g = []
            if myrank == 0:
                if self.h_start:
                    [vals,
                     hist_end] = hos_file.read(ident=['obj', 'con', 'fail'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        [f, g, fail] = [
                            vals['obj'][0][0], vals['con'][0],
                            int(vals['fail'][0][0])
                        ]

            if self.pll:
                self.h_start = Bcast(self.h_start, root=0)

            if self.h_start and self.pll:
                [f, g, fail] = Bcast([f, g, fail], root=0)
            elif not self.h_start:
                [f, g, fail] = opt_problem.obj_fun(xn, *args, **kwargs)

            # Store History
            if myrank == 0:
                if self.sto_hst:
                    log_file.write(xmma, 'x')
                    log_file.write(f, 'obj')
                    log_file.write(g, 'con')
                    log_file.write(fail, 'fail')

            # Objective Assigment
            if isinstance(f, complex):
                f0new = f.astype(float)
            else:
                f0new = f

            # Constraints Assigment
            for i in range(len(opt_problem.constraints.keys())):
                if isinstance(g[i], complex):
                    fnew[i] = g[i].astype(float)
                else:
                    fnew[i] = g[i]

            return f0new, fnew

        # ======================================================================
        # GCMMA - Objective/Constraint Values and Gradients Function
        # ======================================================================
        def func2(m, n, xval, f0val, df0dx, fval, dfdx):

            # Variables Groups Handling
            if opt_problem.use_groups:
                xg = {}
                for group in group_ids.keys():
                    if group_ids[group][1] - group_ids[group][0] == 1:
                        xg[group] = xval[group_ids[group][0]]
                    else:
                        xg[group] = xval[
                            group_ids[group][0]:group_ids[group][1]]
                xn = xg
            else:
                xn = xval

            # Flush Output Files
            self.flushFiles()

            # Evaluate User Function (Real Valued)
            fail = 0
            f = []
            g = []
            if myrank == 0:
                if self.h_start:
                    [vals,
                     hist_end] = hos_file.read(ident=['obj', 'con', 'fail'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        [f, g, fail] = [
                            vals['obj'][0][0], vals['con'][0],
                            int(vals['fail'][0][0])
                        ]

            if self.pll:
                self.h_start = Bcast(self.h_start, root=0)

            if self.h_start and self.pll:
                [f, g, fail] = Bcast([f, g, fail], root=0)
            elif not self.h_start:
                [f, g, fail] = opt_problem.obj_fun(xn, *args, **kwargs)

            # Store History
            if myrank == 0:
                if self.sto_hst:
                    log_file.write(xval, 'x')
                    log_file.write(f, 'obj')
                    log_file.write(g, 'con')
                    log_file.write(fail, 'fail')

            # Gradients
            if self.h_start:
                df = []
                dg = []
                if myrank == 0:
                    [vals,
                     hist_end] = hos_file.read(ident=['grad_obj', 'grad_con'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        df = vals['grad_obj'][0].reshape(
                            (len(opt_problem.objectives.keys()),
                             len(opt_problem.variables.keys())))
                        dg = vals['grad_con'][0].reshape(
                            (len(opt_problem.constraints.keys()),
                             len(opt_problem.variables.keys())))

                if self.pll:
                    self.h_start = Bcast(self.h_start, root=0)

                if self.h_start and self.pll:
                    [df, dg] = Bcast([df, dg], root=0)

            if not self.h_start:
                df, dg = gradient.getGrad(xval, group_ids, [f], g, *args,
                                          **kwargs)

            # Store History
            if self.sto_hst and (myrank == 0):
                log_file.write(df, 'grad_obj')
                log_file.write(dg, 'grad_con')

            # Objective Assignment
            if isinstance(f, complex):
                f0val = f.astype(float)
            else:
                f0val = f

            # Constraints Assignment
            for i in range(len(opt_problem.constraints.keys())):
                if isinstance(g[i], complex):
                    fval[i] = g[i].astype(float)
                else:
                    fval[i] = g[i]

            # Gradients Assigment
            k = 0
            for i in range(len(opt_problem.variables.keys())):
                if isinstance(df[0, i], complex):
                    df0dx[i] = df[0, i].astype(float)
                else:
                    df0dx[i] = df[0, i]
                for jj in range(len(opt_problem.constraints.keys())):
                    if isinstance(dg[jj, i], complex):
                        dfdx[k] = dg[jj, i].astype(float)
                    else:
                        dfdx[k] = dg[jj, i]
                    k += 1

            return f0val, df0dx, fval, dfdx

        # Variables Handling
        n = len(opt_problem.variables.keys())
        xmin = []
        xmax = []
        xval = []
        for key in opt_problem.variables.keys():
            if opt_problem.variables[key].type == 'c':
                xmin.append(opt_problem.variables[key].lower)
                xmax.append(opt_problem.variables[key].upper)
                xval.append(opt_problem.variables[key].value)
            elif opt_problem.variables[key].type == 'i':
                raise IOError('GCMMA cannot handle integer design variables')
            elif opt_problem.variables[key].type == 'd':
                raise IOError('GCMMA cannot handle discrete design variables')

        xmin = numpy.array(xmin)
        xmax = numpy.array(xmax)
        xval = numpy.array(xval)

        # Variables Groups Handling
        group_ids = {}
        if opt_problem.use_groups:
            k = 0
            for key in opt_problem.vargroups.keys():
                group_len = len(opt_problem.vargroups[key]['ids'])
                group_ids[opt_problem.vargroups[key]['name']] = [
                    k, k + group_len
                ]
                k += group_len

        # Constraints Handling
        m = len(opt_problem.constraints.keys())
        neqc = 0
        # fval = []
        fmax = []
        if m > 0:
            for key in opt_problem.constraints.keys():
                if opt_problem.constraints[key].type == 'e':
                    raise IOError('GCMMA cannot handle equality constraints')
                # neqc += 1

                # fval.append(opt_problem.constraints[key].value)
                fmax.append(opt_problem.constraints[key].upper)
        else:
            m = 1
            fmax.append(inf)

        # fval = numpy.array(fval)
        fmax = numpy.array(fmax)

        # Objective Handling
        objfunc = opt_problem.obj_fun
        nobj = len(opt_problem.objectives.keys())
        f0val = []
        for key in opt_problem.objectives.keys():
            f0val.append(opt_problem.objectives[key].value)

        f0val = numpy.array(f0val)

        # Setup argument list values

        xmma = numpy.zeros([n], numpy.float)

        # Space used internally by the program
        # for the asymptotes (xlow and xupp) and
        # computed bounds on x (alpha and beta)
        xlow = numpy.zeros([n], numpy.float)
        xupp = numpy.zeros([n], numpy.float)
        alfa = numpy.zeros([n], numpy.float)
        beta = numpy.zeros([n], numpy.float)

        # The objective and constraint function
        # values and space for the gradients
        fval = numpy.zeros([m], numpy.float)
        df0dx = numpy.zeros([n], numpy.float)
        dfdx = numpy.zeros([m * n], numpy.float)

        # Space for the coefficients and artificial
        # variables to be computed (set to default values)
        p = numpy.zeros([m * n], numpy.float)
        q = numpy.zeros([m * n], numpy.float)
        p0 = numpy.zeros([n], numpy.float)
        q0 = numpy.zeros([n], numpy.float)
        b = numpy.zeros([m], numpy.float)
        y = numpy.zeros([m], numpy.float)
        z = numpy.array([0.], numpy.float)
        a = numpy.zeros([m], numpy.float)
        c = 10000 * numpy.ones([m], numpy.float)

        # Space for evaluating the convex approximation of
        # the objective and constraint functions
        f0app = numpy.array([0.], numpy.float)
        fapp = numpy.zeros([m], numpy.float)

        # Space for the parameter rho for the objective and
        # constraint functions (used in evaluating p and q)
        raa0 = numpy.array([0.], numpy.float)
        raa = numpy.zeros([m], numpy.float)

        # Space for the Lagrange multipliers (ulam)
        # the gradient of the dual objective function,
        # search direction, and Hessian of the dual objective
        ulam = numpy.ones([m], numpy.float)
        gradf = numpy.zeros([m], numpy.float)
        dsrch = numpy.zeros([m], numpy.float)
        hessf = numpy.zeros([m * (m + 1) / 2], numpy.float)

        # Specify that all variables are free to move
        iyfree = numpy.ones([m], numpy.int)

        iter = numpy.array([0], numpy.int)
        inntot = numpy.array([0], numpy.int)
        maxit = numpy.array([self.options['MAXIT'][1]], numpy.int)
        innmax = numpy.array([self.options['INNMAX'][1]], numpy.int)
        geps = numpy.array([self.options['GEPS'][1]], numpy.float)
        dabobj = numpy.array([self.options['DABOBJ'][1]], numpy.float)
        delobj = numpy.array([self.options['DELOBJ'][1]], numpy.float)
        itrm = numpy.array([self.options['ITRM'][1]], numpy.int)
        inform = numpy.array([0], numpy.int)
        if myrank == 0:
            iprint = numpy.array([self.options['IPRINT'][1]], numpy.int)
        else:
            iprint = numpy.array([0], numpy.int)

        iout = numpy.array([self.options['IOUT'][1]], numpy.int)
        ifile = self.options['IFILE'][1]
        if myrank == 0:
            if iprint >= 0:
                if os.path.isfile(ifile):
                    os.remove(ifile)

        nfunc1 = numpy.array([0], numpy.int)
        nfunc2 = numpy.array([0], numpy.int)

        # Run GCMMA
        t0 = time.time()
        gcmma.gcmma(n, m, innmax, iter, maxit, inntot, geps, dabobj, delobj,
                    itrm, inform, xval, xmma, xmin, xmax, xlow, xupp, alfa,
                    beta, f0val, fval, fmax, df0dx, dfdx, p, q, p0, q0, b,
                    f0app, fapp, raa0, raa, y, z, a, c, ulam, gradf, dsrch,
                    hessf, iyfree, iprint, iout, ifile, nfunc1, nfunc2, func1,
                    func2)
        sol_time = time.time() - t0

        if myrank == 0:
            if self.sto_hst:
                log_file.close()
                if tmp_file:
                    hos_file.close()
                    name = hos_file.filename
                    os.remove(name + '.cue')
                    os.remove(name + '.bin')
                    os.rename(name + '_tmp.cue', name + '.cue')
                    os.rename(name + '_tmp.bin', name + '.bin')

        if iprint > 0:
            gcmma.closeunit(self.options['IOUT'][1])

        # Store Results
        sol_inform = {}
        sol_inform['value'] = inform[0]
        sol_inform['text'] = self.getInform(inform[0])

        if store_sol:

            sol_name = 'GCMMA Solution to ' + opt_problem.name

            sol_options = copy.copy(self.options)
            # if sol_options.has_key('defaults'):
            if 'display_opts' in sol_options:
                del sol_options['defaults']

            sol_evals = iter

            sol_vars = copy.deepcopy(opt_problem.variables)
            i = 0
            for key in sol_vars.keys():
                sol_vars[key].value = xmma[i]
                i += 1

            sol_objs = copy.deepcopy(opt_problem.objectives)
            i = 0
            for key in sol_objs.keys():
                sol_objs[key].value = f0val[i]
                i += 1

            if m > 0:
                sol_cons = copy.deepcopy(opt_problem.constraints)
                i = 0
                for key in sol_cons.keys():
                    sol_cons[key].value = fval[i]
                    i += 1
            else:
                sol_cons = {}

            sol_lambda = {}

            opt_problem.addSol(self.__class__.__name__,
                               sol_name,
                               objfunc,
                               sol_time,
                               sol_evals,
                               sol_inform,
                               sol_vars,
                               sol_objs,
                               sol_cons,
                               sol_options,
                               display_opts=disp_opts,
                               Lambda=sol_lambda,
                               Sensitivities=sens_type,
                               myrank=myrank,
                               arguments=args,
                               **kwargs)

        return f0val, xmma, sol_inform
Esempio n. 6
0
    def __solve__(self, opt_problem, sens_type='FD', store_sol=True,
                  store_hst=False, hot_start=False, disp_opts=False,
                  sens_mode='', sens_step={}, *args, **kwargs):
        """Run Optimizer (Optimize Routine)
        
        **Keyword arguments:**
        
        - opt_problem -> INST: Optimization instance
        - sens_type -> STR/FUNC: Gradient type, *Default* = 'FD' 
        - store_sol -> BOOL: Store solution in Optimization class flag,
                       *Default* = True 
        - disp_opts -> BOOL: Flag to display options in solution text,
                       *Default* = False
        - store_hst -> BOOL/STR: Flag/filename to store optimization history,
                       *Default* = False
        - hot_start -> BOOL/STR: Flag/filename to read optimization history,
                       *Default* = False
        - sens_mode -> STR: Flag for parallel gradient calculation,
                       *Default* = ''
        - sens_step -> FLOAT: Sensitivity step size,
                       *Default* = {} [corresponds to 1e-6 (FD), 1e-20(CS)]
        
        Additional arguments and keyword arguments are passed to the objective
        function call.
        
        Documentation last updated:  February. 2, 2011 - Peter W. Jansen

        """
        if self.poa and (sens_mode.lower() == 'pgc'):
            raise NotImplementedError("pySOLVOPT - Current implementation only "
                                      "allows single level parallelization, "
                                      "either 'POA' or 'pgc'")

        if self.poa or (sens_mode.lower() == 'pgc'):
            try:
                import mpi4py
                from mpi4py import MPI
            except ImportError:
                print('pySOLVOPT: Parallel objective Function Analysis '
                      'requires mpi4py')

            comm = MPI.COMM_WORLD
            nproc = comm.Get_size()
            if mpi4py.__version__[0] == '0':
                Bcast = comm.Bcast
            # elif mpi4py.__version__[0] == '1':
            else:  # version can be 1, 2, 3 .... or more
                Bcast = comm.bcast

            self.pll = True
            self.myrank = comm.Get_rank()
        else:
            self.pll = False
            self.myrank = 0

        myrank = self.myrank

        def_fname = self.options['ifile'][1].split('.')[0]
        hos_file, log_file, tmp_file = self._setHistory(opt_problem.name,
                                                        store_hst, hot_start,
                                                        def_fname)

        gradient = Gradient(opt_problem, sens_type, sens_mode, sens_step)

        # ======================================================================
        # SOLVOPT - Objective/Constraint Values Storage
        # ======================================================================
        def soeval(x):
            # Variables Groups Handling
            if opt_problem.use_groups:
                xg = {}
                for group in group_ids.keys():
                    if group_ids[group][1] - group_ids[group][0] == 1:
                        xg[group] = x[group_ids[group][0]]
                    else:
                        xg[group] = x[group_ids[group][0]:group_ids[group][1]]
                xn = xg
            else:
                xn = x

            # Flush Output Files
            self.flushFiles()

            # Evaluate User Function
            fail = 0
            f = []
            g = []
            if myrank == 0:
                if self.h_start:
                    [vals, hist_end] = hos_file.read(
                        ident=['obj', 'con', 'fail'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        [f, g, fail] = [vals['obj'][0][0], vals['con'][0],
                                        int(vals['fail'][0][0])]

            if self.pll:
                self.h_start = Bcast(self.h_start, root=0)

            if self.h_start and self.pll:
                [f, g, fail] = Bcast([f, g, fail], root=0)
            elif not self.h_start:
                [f, g, fail] = opt_problem.obj_fun(xn, *args, **kwargs)

            # Store History
            if myrank == 0:
                if self.sto_hst:
                    log_file.write(x, 'x')
                    log_file.write(f, 'obj')
                    log_file.write(g, 'con')
                    log_file.write(fail, 'fail')

            # Gradients
            if self.h_start:
                df = []
                dg = []
                if myrank == 0:
                    [vals, hist_end] = hos_file.read(
                        ident=['grad_obj', 'grad_con'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        df = vals['grad_obj'][0].reshape(
                            (len(opt_problem.objectives.keys()),
                             len(opt_problem.variables.keys())))
                        dg = vals['grad_con'][0].reshape(
                            (len(opt_problem.constraints.keys()),
                             len(opt_problem.variables.keys())))

                if self.pll:
                    self.h_start = Bcast(self.h_start, root=0)

                if self.h_start and self.pll:
                    [df, dg] = Bcast([df, dg], root=0)

            if not self.h_start:
                df, dg = gradient.getGrad(x, group_ids, [f], g, *args, **kwargs)

            # Store History
            if myrank == 0:
                if self.sto_hst:
                    log_file.write(df, 'grad_obj')
                    log_file.write(dg, 'grad_con')

            # Objective Assignment
            if isinstance(f, complex):
                ff = f.astype(float)
            else:
                ff = f

            # Constraints Assignment
            i = 0
            j = 0
            for j in range(len(opt_problem.constraints.keys())):
                if isinstance(g[j], complex):
                    gg[i] = g[j].astype(float)
                else:
                    gg[i] = g[j]
                i += 1

            for key in opt_problem.variables.keys():
                if opt_problem.variables[key].lower != -inf:
                    gg[i] = xl[j] - x[j]
                    i += 1

                if opt_problem.variables[key].upper != inf:
                    gg[i] = x[j] - xu[j]
                    i += 1

            # Gradient Assignment
            df = df[0]
            dgg = numpy.zeros([len(opt_problem.variables.keys()) * 2,
                               len(opt_problem.variables.keys())], 'd')
            i = len(opt_problem.constraints.keys())
            j = 0
            for key in opt_problem.variables.keys():
                if opt_problem.variables[key].lower != -inf:
                    if gg[i] > 0:
                        dgg[j, j] = -1
                    i += 1

                if opt_problem.variables[key].upper != inf:
                    if gg[i] > 0:
                        dgg[j, j] = 1
                    i += 1
                j += 1

            dg = numpy.concatenate((dg, dgg), axis=0)

            # Store
            self.stored_data['x'] = copy.copy(x)
            self.stored_data['f'] = copy.copy(ff)
            self.stored_data['g'] = copy.copy(gg)
            self.stored_data['df'] = copy.copy(df)
            self.stored_data['dg'] = copy.copy(dg)

            return

        # ======================================================================
        # SOLVOPT - Objective Value Function
        # ======================================================================
        def soobjf(n, x, f):

            if (self.stored_data['x'] != x).any():
                soeval(x)

            f = self.stored_data['f']

            return f

        # ======================================================================
        # SOLVOPT - Constraint Values Function
        # ======================================================================
        def soobjg(n, x, g):

            if (self.stored_data['x'] != x).any():
                soeval(x)

            # Constraints Maximal Residual
            maxg = numpy.zeros([len(self.stored_data['g'])], float)
            i = 0
            for key in opt_problem.constraints.keys():
                if opt_problem.constraints[key].type == 'e':
                    maxg[i] = abs(self.stored_data['g'][i])
                    i += 1
                elif opt_problem.constraints[key].type == 'i':
                    maxg[i] = max(0, self.stored_data['g'][i])
                    i += 1

            for j in range(len(opt_problem.constraints),
                            len(self.stored_data['g'])):
                maxg[i] = max(0, self.stored_data['g'][i])
                i += 1

            g = max(maxg)

            return g

        # ======================================================================
        # SOLVOPT - Objective Gradients Function
        # ======================================================================
        def sogrdf(n, x, df):

            if (self.stored_data['x'] != x).any():
                soeval(x)

            df = self.stored_data['df']

            return df

        # ======================================================================
        # SOLVOPT - Constraint Gradients Function
        # ======================================================================
        def sogrdg(n, x, dg):

            if (self.stored_data['x'] != x).any():
                soeval(x)

            # Constraints Maximal Residual
            maxg = numpy.zeros([len(self.stored_data['g'])], float)
            i = 0
            for key in opt_problem.constraints.keys():
                if opt_problem.constraints[key].type == 'e':
                    maxg[i] = abs(self.stored_data['g'][i])
                    i += 1
                elif opt_problem.constraints[key].type == 'i':
                    maxg[i] = max(0, self.stored_data['g'][i])
                    i += 1

            for j in range(len(opt_problem.constraints),
                            len(self.stored_data['g'])):
                maxg[i] = max(0, self.stored_data['g'][i])
                i += 1

            id = min(numpy.nonzero(maxg == max(maxg))[0])

            dg = self.stored_data['dg'][id]

            return dg

        # Variables Handling
        nvar = len(opt_problem.variables.keys())
        xl = []
        xu = []
        xx = []
        for key in opt_problem.variables.keys():
            if opt_problem.variables[key].type == 'c':
                xl.append(opt_problem.variables[key].lower)
                xu.append(opt_problem.variables[key].upper)
                xx.append(opt_problem.variables[key].value)
            elif opt_problem.variables[key].type == 'i':
                raise IOError('SOLVOPT cannot handle integer design variables')
            elif opt_problem.variables[key].type == 'd':
                raise IOError('SOLVOPT cannot handle discrete design variables')

        xl = numpy.array(xl)
        xu = numpy.array(xu)
        xx = numpy.array(xx)

        # Variables Groups Handling
        group_ids = {}
        if opt_problem.use_groups:
            k = 0
            for key in opt_problem.vargroups.keys():
                group_len = len(opt_problem.vargroups[key]['ids'])
                group_ids[opt_problem.vargroups[key]['name']] = [k,
                                                                  k + group_len]
                k += group_len

        # Constraints Handling
        ncon = len(opt_problem.constraints.keys())
        neqc = 0
        gg = []
        if ncon > 0:
            for key in opt_problem.constraints.keys():
                if opt_problem.constraints[key].type == 'e':
                    neqc += 1

                # gg.append(opt_problem.constraints[key].value)
                gg.append(opt_problem.constraints[key].upper)

        nadd = 0
        for key in opt_problem.variables.keys():
            if opt_problem.variables[key].lower != -inf:
                gg.append(0)
                nadd += 1

            if opt_problem.variables[key].upper != inf:
                gg.append(0)
                nadd += 1

        gg = numpy.array(gg, numpy.float)

        # Objective Handling
        objfunc = opt_problem.obj_fun
        nobj = len(opt_problem.objectives.keys())
        ff = []
        for key in opt_problem.objectives.keys():
            ff.append(opt_problem.objectives[key].value)

        ff = numpy.array(ff, numpy.float)

        # Setup argument list values
        n = numpy.array([nvar], numpy.int)
        flg = numpy.array([True], numpy.bool)
        iprint = self.options['iprint'][1]
        if myrank != 0:
            iprint = -1
        else:
            iprint = self.options['iprint'][1]

        options = numpy.zeros([13], numpy.float)
        options[0] = -1  # Minimize
        options[1] = self.options['xtol'][1]  # Variables Tolerance
        options[2] = self.options['ftol'][1]  # Objective Tolerance
        options[3] = self.options['maxit'][1]  # Maximum Number of Iterations
        options[4] = iprint  # Output Level
        options[5] = self.options['gtol'][1]  # Constraints Tolerance
        options[6] = self.options['spcdil'][1]  # Space Dilation
        options[
            7] = 1e-11  # LB FD Stepsize (NA as we provide our own sensitivities)
        flfc = numpy.array([True], numpy.bool)
        flgc = numpy.array([True], numpy.bool)
        iout = numpy.array([self.options['iout'][1]], numpy.int)
        ifile = self.options['ifile'][1]

        if iprint >= 0:
            if os.path.isfile(ifile):
                os.remove(ifile)

        wb = numpy.zeros([nvar, nvar], numpy.float)
        wg = numpy.zeros([nvar], numpy.float)
        wg0 = numpy.zeros([nvar], numpy.float)
        wg1 = numpy.zeros([nvar], numpy.float)
        wgt = numpy.zeros([nvar], numpy.float)
        wgc = numpy.zeros([nvar], numpy.float)
        wz = numpy.zeros([nvar], numpy.float)
        wx1 = numpy.zeros([nvar], numpy.float)
        wxopt = numpy.zeros([nvar], numpy.float)
        wxrec = numpy.zeros([nvar], numpy.float)
        wgrec = numpy.zeros([nvar], numpy.float)
        wxx = numpy.zeros([nvar], numpy.float)
        wdeltax = numpy.zeros([nvar], numpy.float)
        widx = numpy.zeros([nvar], numpy.int)

        # Storage Arrays
        self.stored_data = {}
        self.stored_data['x'] = {}  # numpy.zeros([nvar],float)
        self.stored_data['f'] = {}  # numpy.zeros([nobj],float)
        self.stored_data['g'] = {}  # numpy.zeros([ncon+nadd],float)
        self.stored_data['df'] = {}  # numpy.zeros([nvar],float)
        self.stored_data['dg'] = {}  # numpy.zeros([ncon+nadd,nvar],float)

        # Run SOLVOPT
        t0 = time.time()
        solvopt.solvopt(n, xx, ff, soobjf, flg, sogrdf, options, flfc, soobjg,
                        flgc, sogrdg, wb, wg, wg0, wg1, wgt, wgc, wz, wx1,
                        wxopt, wxrec, wgrec, wxx, wdeltax, widx, iout, ifile)
        sol_time = time.time() - t0

        if myrank == 0:
            if self.sto_hst:
                log_file.close()
                if tmp_file:
                    hos_file.close()
                    name = hos_file.filename
                    os.remove(name + '.cue')
                    os.remove(name + '.bin')
                    os.rename(name + '_tmp.cue', name + '.cue')
                    os.rename(name + '_tmp.bin', name + '.bin')

        if iprint > 0:
            solvopt.closeunit(self.options['iout'][1])

        # Store Results
        sol_inform = {}
        sol_inform['value'] = options[8]
        sol_inform['text'] = self.getInform(options[8])

        if store_sol:

            sol_name = 'SOLVOPT Solution to ' + opt_problem.name

            sol_options = copy.copy(self.options)
            # if sol_options.has_key('defaults'):
            if 'defaults' in sol_options:
                del sol_options['defaults']

            # assumes cnst fevals and gevals are included in feval & geval
            sol_evals = options[9] + options[10]

            sol_vars = copy.deepcopy(opt_problem.variables)
            i = 0
            for key in sol_vars.keys():
                sol_vars[key].value = xx[i]
                i += 1

            sol_objs = copy.deepcopy(opt_problem.objectives)
            i = 0
            for key in sol_objs.keys():
                sol_objs[key].value = ff[i]
                i += 1

            if ncon > 0:
                sol_cons = copy.deepcopy(opt_problem.constraints)
                i = 0
                for key in sol_cons.keys():
                    sol_cons[key].value = gg[i]
                    i += 1
                    if i >= ncon:
                        break
            else:
                sol_cons = {}

            sol_lambda = {}

            opt_problem.addSol(self.__class__.__name__, sol_name, objfunc,
                               sol_time,
                               sol_evals, sol_inform, sol_vars, sol_objs,
                               sol_cons, sol_options,
                               display_opts=disp_opts, Lambda=sol_lambda,
                               Sensitivities=sens_type,
                               myrank=myrank, arguments=args, **kwargs)

        return ff, xx, sol_inform
Esempio n. 7
0
    def __solve__(self,
                  opt_problem,
                  sens_type='FD',
                  store_sol=True,
                  store_hst=False,
                  hot_start=False,
                  disp_opts=False,
                  sens_mode='',
                  sens_step={},
                  *args,
                  **kwargs):
        """Run Optimizer (Optimize Routine)
        
        **Keyword arguments:**
        
        - opt_problem -> INST: Optimization instance
        - sens_type -> STR/FUNC: Gradient type, *Default* = 'FD' 
        - store_sol -> BOOL: Store solution in Optimization class flag,
                       *Default* = True 
        - disp_opts -> BOOL: Flag to display options in solution text,
                       *Default* = False
        - store_hst -> BOOL/STR: Flag/filename to store optimization history,
                       *Default* = False
        - hot_start -> BOOL/STR: Flag/filename to read optimization history,
                       *Default* = False
        - sens_mode -> STR: Flag for parallel gradient calculation,
                       *Default* = ''
        - sens_step -> FLOAT: Sensitivity setp size,
                       *Default* = {} [corresponds to 1e-6 (FD), 1e-20(CS)]
        
        Additional arguments and keyword arguments are passed to the
        objective function call.
        
        Documentation last updated:  February. 2, 2011 - Ruben E. Perez

        """
        if self.poa and (sens_mode.lower() == 'pgc'):
            raise NotImplementedError("pyPSQP - Current implementation only "
                                      "allows single level parallelization, "
                                      "either 'POA' or 'pgc'")

        if self.poa or (sens_mode.lower() == 'pgc'):
            try:
                import mpi4py
                from mpi4py import MPI
            except ImportError:
                print('pyPSQP: Parallel objective Function Analysis '
                      'requires mpi4py')

            comm = MPI.COMM_WORLD
            nproc = comm.Get_size()
            if mpi4py.__version__[0] == '0':
                Bcast = comm.Bcast
            # elif mpi4py.__version__[0] == '1':
            else:  # version can be 1, 2, 3 .... or more
                Bcast = comm.bcast

            self.pll = True
            self.myrank = comm.Get_rank()
        else:
            self.pll = False
            self.myrank = 0

        myrank = self.myrank

        def_fname = self.options['IFILE'][1].split('.')[0]
        hos_file, log_file, tmp_file = self._setHistory(
            opt_problem.name, store_hst, hot_start, def_fname)

        gradient = Gradient(opt_problem, sens_type, sens_mode, sens_step)

        # ======================================================================
        # PSQP - Objective/Constraint Values Storage
        # ======================================================================
        def eval(x):

            # Variables Groups Handling
            if opt_problem.use_groups:
                xg = {}
                for group in group_ids.keys():
                    if group_ids[group][1] - group_ids[group][0] == 1:
                        xg[group] = x[group_ids[group][0]]
                    else:
                        xg[group] = x[group_ids[group][0]:group_ids[group][1]]
                xn = xg
            else:
                xn = x

            # Flush Output Files
            self.flushFiles()

            # Evaluate User Function (Real Valued)
            fail = 0
            f = []
            g = []
            if myrank == 0:
                if self.h_start:
                    [vals,
                     hist_end] = hos_file.read(ident=['obj', 'con', 'fail'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        [f, g, fail] = [
                            vals['obj'][0][0], vals['con'][0],
                            int(vals['fail'][0][0])
                        ]

            if self.pll:
                self.h_start = Bcast(self.h_start, root=0)

            if self.h_start and self.pll:
                [f, g, fail] = Bcast([f, g, fail], root=0)
            elif not self.h_start:
                [f, g, fail] = opt_problem.obj_fun(xn, *args, **kwargs)

            # Store History
            if myrank == 0:
                if self.sto_hst:
                    log_file.write(x, 'x')
                    log_file.write(f, 'obj')
                    log_file.write(g, 'con')
                    log_file.write(fail, 'fail')

            # Objective Assignment
            if isinstance(f, float):
                f = [f]

            for i in range(len(opt_problem.objectives.keys())):
                if isinstance(f[i], complex):
                    ff[i] = f[i].astype(float)
                else:
                    ff[i] = f[i]

            # Constraints Assignment
            i = 0
            for j in range(len(opt_problem.constraints.keys())):
                if isinstance(g[j], complex):
                    gg[i] = g[j].astype(float)
                else:
                    gg[i] = g[j]
                i += 1

            # Gradients
            if self.h_start:
                dff = []
                dgg = []
                if myrank == 0:
                    [vals,
                     hist_end] = hos_file.read(ident=['grad_obj', 'grad_con'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        dff = vals['grad_obj'][0].reshape(
                            (len(opt_problem.objectives.keys()),
                             len(opt_problem.variables.keys())))
                        dgg = vals['grad_con'][0].reshape(
                            (len(opt_problem.constraints.keys()),
                             len(opt_problem.variables.keys())))
                if self.pll:
                    self.h_start = Bcast(self.h_start, root=0)

                if self.h_start and self.pll:
                    [dff, dgg] = Bcast([dff, dgg], root=0)

            if not self.h_start:
                dff, dgg = gradient.getGrad(x, group_ids, f, g, *args,
                                            **kwargs)

            # Store History
            if self.sto_hst and (myrank == 0):
                log_file.write(dff, 'grad_obj')
                log_file.write(dgg, 'grad_con')

            # Store
            self.stored_data['x'] = copy.copy(x)
            self.stored_data['f'] = copy.copy(ff)
            self.stored_data['g'] = copy.copy(gg)
            self.stored_data['df'] = copy.copy(dff)
            self.stored_data['dg'] = copy.copy(dgg)

            return

        # ======================================================================
        # PSQP - Objective Values Function
        # ======================================================================
        def pobj(n, x, f):

            if (self.stored_data['x'] != x).any():
                eval(x)

            ff = self.stored_data['f']

            return ff[0]

        # ======================================================================
        # PSQP - Constraint Values Function
        # ======================================================================
        def pcon(n, k, x, g):

            if (self.stored_data['x'] != x).any():
                eval(x)

            gg = self.stored_data['g']

            return gg[k - 1]

        # ======================================================================
        # PSQP - Objective Gradients Function
        # ======================================================================
        def pdobj(n, x, df):

            if (self.stored_data['x'] != x).any():
                eval(x)

            df = self.stored_data['df']

            return df[0]

        # ======================================================================
        # PSQP - Constraint Gradients Function
        # ======================================================================
        def pdcon(n, k, x, dg):

            if (self.stored_data['x'] != x).any():
                eval(x)

            dg = self.stored_data['dg']

            return dg[k - 1]

        # Variables Handling
        nvar = len(opt_problem.variables.keys())
        xl = []
        xu = []
        xi = []
        xx = []
        for key in opt_problem.variables.keys():
            xl.append(opt_problem.variables[key].lower)
            xu.append(opt_problem.variables[key].upper)
            xi.append(3)
            xx.append(opt_problem.variables[key].value)

        xl = numpy.array(xl)
        xu = numpy.array(xu)
        xi = numpy.array(xi)
        xx = numpy.array(xx)

        # Variables Groups Handling
        group_ids = {}
        if opt_problem.use_groups:
            k = 0
            for key in opt_problem.vargroups.keys():
                group_len = len(opt_problem.vargroups[key]['ids'])
                group_ids[opt_problem.vargroups[key]['name']] = [
                    k, k + group_len
                ]
                k += group_len

        # Constraints Handling
        ncon = len(opt_problem.constraints.keys())
        if ncon > 0:
            gi = []
            gg = []
            for key in opt_problem.constraints.keys():
                if opt_problem.constraints[key].type == 'e':
                    gi.append(5)
                elif opt_problem.constraints[key].type == 'i':
                    gi.append(2)

                gg.append(opt_problem.constraints[key].value)

            gg.append(0.0)
            gl = numpy.zeros([ncon], numpy.float)
            gu = numpy.zeros([ncon], numpy.float)
            gi = numpy.array(gi, numpy.float)
            gg = numpy.array(gg, numpy.float)
        else:
            gl = numpy.array([0], numpy.float)
            gu = numpy.array([0], numpy.float)
            gi = numpy.array([0], numpy.float)
            gg = numpy.array([0], numpy.float)

        # Objective Handling
        objfunc = opt_problem.obj_fun
        nobj = len(opt_problem.objectives.keys())
        ff = []
        for key in opt_problem.objectives.keys():
            ff.append(opt_problem.objectives[key].value)

        ff = numpy.array(ff, numpy.float)

        # Setup argument list values
        nf = numpy.array([nvar], numpy.int)
        nc = numpy.array([ncon], numpy.int)
        mit = numpy.array([self.options['MIT'][1]], numpy.int)
        mfv = numpy.array([self.options['MFV'][1]], numpy.int)
        met = numpy.array([self.options['MET'][1]], numpy.int)
        mec = numpy.array([self.options['MEC'][1]], numpy.int)
        xmax = numpy.array([self.options['XMAX'][1]], numpy.float)
        tolx = numpy.array([self.options['TOLX'][1]], numpy.float)
        tolc = numpy.array([self.options['TOLC'][1]], numpy.float)
        tolg = numpy.array([self.options['TOLG'][1]], numpy.float)
        rpf = numpy.array([self.options['RPF'][1]], numpy.float)
        gmax = numpy.array([0], numpy.float)
        cmax = numpy.array([0], numpy.float)
        if myrank == 0:
            if self.options['IPRINT'][1] <= 2:
                iprint = numpy.array([self.options['IPRINT'][1]], numpy.int)
            else:
                raise IOError('Incorrect Output Level Setting')
        else:
            iprint = numpy.array([0], numpy.int)
        iout = numpy.array([self.options['IOUT'][1]], numpy.int)
        ifile = self.options['IFILE'][1]
        if myrank == 0:
            if iprint != 0:
                if os.path.isfile(ifile):
                    os.remove(ifile)

        iterm = numpy.array([0], numpy.int)

        # Storage Arrays
        self.stored_data = {}
        self.stored_data['x'] = {}  # numpy.zeros([nvar],float)
        self.stored_data['f'] = {}  # numpy.zeros([nobj],float)
        self.stored_data['g'] = {}  # numpy.zeros([ncon],float)
        self.stored_data['df'] = {}  # numpy.zeros([nvar],float)
        self.stored_data['dg'] = {}  # numpy.zeros([ncon,nvar],float)

        # Run PSQP
        t0 = time.time()
        psqp.psqp_wrap(nf, nc, xx, xi, xl, xu, gg, gi, gl, gu, mit, mfv, met,
                       mec, xmax, tolx, tolc, tolg, rpf, ff, gmax, cmax,
                       iprint, iout, ifile, iterm, pobj, pdobj, pcon, pdcon)
        sol_time = time.time() - t0

        if myrank == 0:
            if self.sto_hst:
                log_file.close()
                if tmp_file:
                    hos_file.close()
                    name = hos_file.filename
                    os.remove(name + '.cue')
                    os.remove(name + '.bin')
                    os.rename(name + '_tmp.cue', name + '.cue')
                    os.rename(name + '_tmp.bin', name + '.bin')

        # Store Results
        sol_inform = {}
        sol_inform['value'] = iterm[0]
        sol_inform['text'] = self.getInform(iterm[0])

        if store_sol:

            sol_name = 'PSQP Solution to ' + opt_problem.name

            sol_options = copy.copy(self.options)
            # if sol_options.has_key('defaults'):
            if 'defaults' in sol_options:
                del sol_options['defaults']

            sol_evals = psqp.stat.nfv + psqp.stat.nfg * nvar

            sol_vars = copy.deepcopy(opt_problem.variables)
            i = 0
            for key in sol_vars.keys():
                sol_vars[key].value = xx[i]
                i += 1

            sol_objs = copy.deepcopy(opt_problem.objectives)
            i = 0
            for key in sol_objs.keys():
                sol_objs[key].value = ff[i]
                i += 1

            if ncon > 0:
                sol_cons = copy.deepcopy(opt_problem.constraints)
                i = 0
                for key in sol_cons.keys():
                    sol_cons[key].value = gg[i]
                    i += 1
            else:
                sol_cons = {}

            sol_lambda = {}

            opt_problem.addSol(self.__class__.__name__,
                               sol_name,
                               objfunc,
                               sol_time,
                               sol_evals,
                               sol_inform,
                               sol_vars,
                               sol_objs,
                               sol_cons,
                               sol_options,
                               display_opts=disp_opts,
                               Lambda=sol_lambda,
                               Sensitivities=sens_type,
                               myrank=myrank,
                               arguments=args,
                               **kwargs)

        return ff, xx, sol_inform
Esempio n. 8
0
    def __solve__(self,
                  opt_problem,
                  sens_type='FD',
                  store_sol=True,
                  disp_opts=False,
                  store_hst=False,
                  hot_start=False,
                  sens_mode='',
                  sens_step={},
                  *args,
                  **kwargs):
        """Run Optimizer (Optimize Routine)

        **Keyword arguments:**

        - opt_problem -> INST: Optimization instance
        - sens_type -> STR/FUNC: Gradient type, *Default* = 'FD' 
        - store_sol -> BOOL: Store solution in Optimization class flag,
                       *Default* = True 
        - disp_opts -> BOOL: Flag to display options in solution text,
                       *Default* = False
        - store_hst -> BOOL/STR: Flag/filename to store optimization history,
                       *Default* = False
        - hot_start -> BOOL/STR: Flag/filename to read optimization history,
                       *Default* = False
        - sens_mode -> STR: Flag for parallel gradient calculation,
                       *Default* = ''
        - sens_step -> FLOAT: Sensitivity setp size, *Default* = {}
                       [corresponds to 1e-6 (FD), 1e-20(CS)]

        Additional arguments and keyword arguments are passed to the
        objective function call.

        Documentation last updated:  February. 2, 2011 - Peter W. Jansen

        """
        if self.poa and (sens_mode.lower() == 'pgc'):
            raise NotImplementedError("pyALGENCAN - Current implementation "
                                      "only allows single level "
                                      "parallelization, either 'POA' or 'pgc'")

        if self.poa or (sens_mode.lower() == 'pgc'):
            try:
                import mpi4py
                from mpi4py import MPI
            except ImportError:
                print('pyALGENCAN: Parallel objective Function Analysis '
                      'requires mpi4py')

            comm = MPI.COMM_WORLD
            nproc = comm.Get_size()
            if mpi4py.__version__[0] == '0':
                Bcast = comm.Bcast
            # elif mpi4py.__version__[0] == '1':
            else:  # version can be 1, 2, 3 .... or more
                Bcast = comm.bcast

            self.pll = True
            self.myrank = comm.Get_rank()
        else:
            self.pll = False
            self.myrank = 0

        myrank = self.myrank

        def_fname = self.options['ifile'][1].split('.')[0]
        hos_file, log_file, tmp_file = \
            self._setHistory(opt_problem.name, store_hst, hot_start, def_fname)

        gradient = Gradient(opt_problem, sens_type, sens_mode, sens_step)

        def evalf(n, x, f, flag):
            """
            
            Parameters
            ----------
            n
            x
            f
            flag

            Returns
            -------

            """
            flag = -1
            return f, flag

        def evalg(n, x, g, flag):
            """
            
            Parameters
            ----------
            n
            x
            g
            flag

            Returns
            -------

            """
            flag = -1
            return g, flag

        def evalh(n, x, hlin, hcol, hval, hnnz, flag):
            """
            
            Parameters
            ----------
            n
            x
            hlin
            hcol
            hval
            hnnz
            flag

            Returns
            -------

            """
            flag = -1
            return hlin, hcol, hval, hnnz, flag

        def evalc(n, x, ind, c, flag):
            """
            
            Parameters
            ----------
            n
            x
            ind
            c
            flag

            Returns
            -------

            """
            flag = -1
            return c, flag

        def evaljac(n, x, ind, jcvar, jcval, jcnnz, flag):
            """
            
            Parameters
            ----------
            n
            x
            ind
            jcvar
            jcval
            jcnnz
            flag

            Returns
            -------

            """
            flag = -1
            return jcvar, jcval, jcnnz, flag

        def evalgjacp(n, x, g, m, p, q, work, gotj, flag):
            """
            
            Parameters
            ----------
            n
            x
            g
            m
            p
            q
            work
            gotj
            flag

            Returns
            -------

            """
            flag = -1
            return g, p, q, gotj, flag

        def evalhc(n, x, ind, hclin, hccol, hcval, hcnnz, flag):
            """
            
            Parameters
            ----------
            n
            x
            ind
            hclin
            hccol
            hcval
            hcnnz
            flag

            Returns
            -------

            """
            flag = -1
            return hclin, hccol, hcval, hcnnz, flag

        def evalhl(n, x, m, lmbda, scalef, scalec, hllin, hlcol, hlval, hlnnz,
                   flag):
            """
            
            Parameters
            ----------
            n
            x
            m
            lmbda
            scalef
            scalec
            hllin
            hlcol
            hlval
            hlnnz
            flag

            Returns
            -------

            """
            flag = -1
            return hllin, hlcol, hlval, hlnnz, flag

        def evalhlp(n, x, m, lmbda, sf, sc, p, hp, goth, flag):
            """
            
            Parameters
            ----------
            n
            x
            m
            lmbda
            sf
            sc
            p
            hp
            goth
            flag

            Returns
            -------

            """
            flag = -1
            return hp, goth, flag

        # ======================================================================
        # ALGENCAN - Objective/Constraint Values Function
        # ======================================================================
        def evalfc(n, x, f, m, g, flag):
            """
            
            Parameters
            ----------
            n
            x
            f
            m
            g
            flag

            Returns
            -------

            """
            # Variables Groups Handling
            if opt_problem.use_groups:
                xg = {}
                for group in group_ids.keys():
                    if group_ids[group][1] - group_ids[group][0] == 1:
                        xg[group] = x[group_ids[group][0]]
                    else:
                        xg[group] = x[group_ids[group][0]:group_ids[group][1]]
                xn = xg
            else:
                xn = x

            # Flush Output Files
            self.flushFiles()

            # Evaluate User Function
            flag = 0
            if myrank == 0:
                if self.h_start:
                    [vals,
                     hist_end] = hos_file.read(ident=['obj', 'con', 'fail'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        [ff, gg, flag] = \
                            [vals['obj'][0][0],vals['con'][0],
                             int(vals['fail'][0][0])]

            if self.pll:
                self.h_start = Bcast(self.h_start, root=0)

            if self.h_start and self.pll:
                [ff, gg, fail] = Bcast([ff, gg, fail], root=0)
            elif not self.h_start:
                [ff, gg, fail] = opt_problem.obj_fun(xn, *args, **kwargs)

            # Store History
            if myrank == 0:
                if self.sto_hst:
                    log_file.write(x, 'x')
                    log_file.write(ff, 'obj')
                    log_file.write(gg, 'con')
                    log_file.write(fail, 'fail')

            # Objective Assigment
            if isinstance(ff, complex):
                f = ff.astype(float)
            else:
                f = ff

            # Constraints Assigment
            for i in range(len(opt_problem.constraints.keys())):
                if isinstance(gg[i], complex):
                    g[i] = gg[i].astype(float)
                else:
                    g[i] = gg[i]

            return f, g, fail

        # ======================================================================
        # ALGENCAN - Objective/Constraint Gradients Function
        # ======================================================================
        def evalgjac(n, x, jfval, m, jcfun, jcvar, jcval, jcnnz, flag):
            """
            
            Parameters
            ----------
            n
            x
            jfval
            m
            jcfun
            jcvar
            jcval
            jcnnz
            flag

            Returns
            -------

            """
            if self.h_start:
                if myrank == 0:
                    [vals,
                     hist_end] = hos_file.read(ident=['grad_obj', 'grad_con'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        dff = vals['grad_obj'][0].reshape(
                            (len(opt_problem.objectives.keys()),
                             len(opt_problem.variables.keys())))
                        dgg = vals['grad_con'][0].reshape(
                            (len(opt_problem.constraints.keys()),
                             len(opt_problem.variables.keys())))

                if self.pll:
                    self.h_start = Bcast(self.h_start, root=0)

                if self.h_start and self.pll:
                    [dff, dgg] = Bcast([dff, dgg], root=0)

            if not self.h_start:
                [ff, gg, fail] = opt_problem.obj_fun(x, *args, **kwargs)
                dff, dgg = gradient.getGrad(x, group_ids, [ff], gg, *args,
                                            **kwargs)

            # Store History
            if self.sto_hst and (myrank == 0):
                log_file.write(dff, 'grad_obj')
                log_file.write(dgg, 'grad_con')

            # Objective Gradient Assignment
            for i in range(len(opt_problem.variables.keys())):
                jfval[i] = dff[0, i]

            # Constraint Gradient Assignment
            jcnnz = 0
            for jj in range(len(opt_problem.constraints.keys())):
                for ii in range(len(opt_problem.variables.keys())):
                    jcfun[jcnnz] = jj + 1
                    jcvar[jcnnz] = ii + 1
                    jcval[jcnnz] = dgg[jj, ii]
                    jcnnz += 1

            return jfval, jcfun, jcvar, jcval, jcnnz, fail

        # Variables Handling
        n = len(opt_problem._variables.keys())
        xl = []
        xu = []
        xx = []
        for key in opt_problem.variables.keys():
            if opt_problem.variables[key].type == 'c':
                xl.append(opt_problem.variables[key].lower)
                xu.append(opt_problem.variables[key].upper)
                xx.append(opt_problem.variables[key].value)
            elif opt_problem.variables[key].type == 'i':
                raise IOError('NLPQL cannot handle integer design variables')
            elif opt_problem.variables[key].type == 'd':
                raise IOError('NLPQL cannot handle discrete design variables')

        xl = numpy.array(xl)
        xu = numpy.array(xu)
        xx = numpy.array(xx)

        # Variables Groups Handling
        group_ids = {}
        if opt_problem.use_groups:
            k = 0
            for key in opt_problem.vargroups.keys():
                group_len = len(opt_problem.vargroups[key]['ids'])
                group_ids[opt_problem.vargroups[key]['name']] = \
                    [k, k+group_len]
                k += group_len

        # Constraints Handling
        m = len(opt_problem.constraints.keys())
        equatn = []
        linear = []
        if m > 0:
            for key in opt_problem.constraints.keys():
                if opt_problem.constraints[key].type == 'e':
                    equatn.append(True)
                elif opt_problem.constraints[key].type == 'i':
                    equatn.append(False)

                linear.append(False)
        else:
            raise IOError('ALGENCAN support for unconstrained problems '
                          'not implemented yet')

        equatn = numpy.array(equatn)
        linear = numpy.array(linear)

        # Objective Handling
        objfunc = opt_problem.obj_fun
        nobj = len(opt_problem.objectives.keys())
        ff = []
        for key in opt_problem.objectives.keys():
            ff.append(opt_problem.objectives[key].value)

        ff = numpy.array(ff)

        # Setup argument list values
        nn = numpy.array([n], numpy.int)
        mm = numpy.array([m], numpy.int)
        lm = numpy.zeros([m], numpy.float)
        coded = numpy.array([
            False, False, False, False, False, False, True, True, False, False
        ], numpy.bool)
        epsfeas = numpy.array([self.options['epsfeas'][1]], numpy.float)
        epsopt = numpy.array([self.options['epsopt'][1]], numpy.float)
        efacc = numpy.array([self.options['efacc'][1]], numpy.float)
        eoacc = numpy.array([self.options['eoacc'][1]], numpy.float)
        checkder = numpy.array([self.options['checkder'][1]], numpy.bool)
        iprint = numpy.array([self.options['iprint'][1]], numpy.int)
        if myrank != 0:
            iprint = 0
        else:
            iprint = self.options['iprint'][1]

        ncomp = numpy.array([self.options['ncomp'][1]], numpy.int)

        ifile = self.options['ifile'][1]
        if iprint >= 0:
            if os.path.isfile(ifile):
                os.remove(ifile)

        cnormu = numpy.array([0], numpy.float)
        snorm = numpy.array([0], numpy.float)
        nlpsupn = numpy.array([0], numpy.float)
        inform = numpy.array([0], numpy.int)

        # Run ALGENCAN
        t0 = time.time()
        algencan.algencan(epsfeas, epsopt, efacc, eoacc, iprint, ncomp, nn, xx,
                          xl, xu, mm, lm, equatn, linear, coded, checkder, ff,
                          cnormu, snorm, nlpsupn, inform, ifile, evalf, evalg,
                          evalh, evalc, evaljac, evalhc, evalfc, evalgjac,
                          evalgjacp, evalhl, evalhlp)
        sol_time = time.time() - t0

        if myrank == 0:
            if self.sto_hst:
                log_file.close()
                if tmp_file:
                    hos_file.close()
                    name = hos_file.filename
                    os.remove(name + '.cue')
                    os.remove(name + '.bin')
                    os.rename(name + '_tmp.cue', name + '.cue')
                    os.rename(name + '_tmp.bin', name + '.bin')

        if iprint > 0:
            algencan.closeunit(10)

        [fs, gg, fail] = opt_problem.obj_fun(xx, *args, **kwargs)

        # Store Results
        sol_inform = {}
        sol_inform['value'] = inform[0]
        sol_inform['text'] = self.getInform(inform[0])

        if store_sol:
            sol_name = 'ALGENCAN Solution to ' + opt_problem.name

            sol_options = copy.copy(self.options)
            # if sol_options.has_key('defaults'):
            if 'defaults' in sol_options:
                del sol_options['defaults']

            sol_evals = 0

            sol_vars = copy.deepcopy(opt_problem.variables)
            i = 0
            for key in sol_vars.keys():
                sol_vars[key].value = xx[i]
                i += 1

            sol_objs = copy.deepcopy(opt_problem.objectives)
            i = 0
            for key in sol_objs.keys():
                sol_objs[key].value = ff[i]
                i += 1

            if m > 0:
                sol_cons = copy.deepcopy(opt_problem.constraints)
                i = 0
                for key in sol_cons.keys():
                    sol_cons[key].value = gg[i]
                    i += 1
            else:
                sol_cons = {}

            sol_lambda = lm

            opt_problem.addSol(self.__class__.__name__,
                               sol_name,
                               objfunc,
                               sol_time,
                               sol_evals,
                               sol_inform,
                               sol_vars,
                               sol_objs,
                               sol_cons,
                               sol_options,
                               display_opts=disp_opts,
                               Lambda=sol_lambda,
                               Sensitivities=sens_type,
                               myrank=myrank,
                               arguments=args,
                               **kwargs)

        return ff, xx, sol_inform
Esempio n. 9
0
    def __solve__(self,
                  opt_problem,
                  sens_type='FD',
                  store_sol=True,
                  store_hst=False,
                  hot_start=False,
                  disp_opts=False,
                  sens_mode='',
                  sens_step={},
                  *args,
                  **kwargs):
        """Run Optimizer (Optimize Routine)
        
        **Keyword arguments:**
        
        - opt_problem -> INST: Optimization instance
        - sens_type -> STR/FUNC: Gradient type, *Default* = 'FD' 
        - store_sol -> BOOL: Store solution in Optimization class flag,
                       *Default* = True 
        - disp_opts -> BOOL: Flag to display options in solution text,
                       *Default* = False
        - store_hst -> BOOL/STR: Flag/filename to store optimization history,
                       *Default* = False
        - hot_start -> BOOL/STR: Flag/filename to read optimization history,
                       *Default* = False
        - sens_mode -> STR: Flag for parallel gradient calculation,
                       *Default* = ''
        - sens_step -> FLOAT: Sensitivity setp size,
                       *Default* = {} [corresponds to 1e-6 (FD), 1e-20(CS)]
        
        Additional arguments and keyword arguments are passed to the
        objective function call.
        
        Documentation last updated:  February. 2, 2013 - Peter W. Jansen

        """
        if self.pll_type is not None and (sens_mode.lower() == 'pgc'):
            raise NotImplementedError("pyNLPQLP - Current implementation only "
                                      "allows single level parallelization, "
                                      "either 'POA', 'SMP', 'DPM' or 'pgc'")

        if self.pll_type is not None or (sens_mode.lower() == 'pgc'):
            try:
                import mpi4py
                from mpi4py import MPI
            except ImportError:
                print('pyNLPQLP: Parallel objective Function Analysis or '
                      'gradient calculation requires mpi4py')

            comm = MPI.COMM_WORLD
            if mpi4py.__version__[0] == '0':
                Bcast = comm.Bcast
                Barrier = comm.Barrier
                Send = comm.Send
                Recv = comm.Recv
            # elif mpi4py.__version__[0] == '1':
            else:  # version can be 1, 2, 3 .... or more
                Bcast = comm.bcast
                Barrier = comm.barrier
                Send = comm.send
                Recv = comm.recv

            self.pll = True
            if self.pll_type == 'SPM':
                nproc = comm.Get_size()
            else:
                nproc = 1
            self.myrank = comm.Get_rank()
        else:
            self.pll = False
            nproc = 1
            self.myrank = 0

        myrank = self.myrank

        def_fname = self.options['IFILE'][1].split('.')[0]
        hos_file, log_file, tmp_file = self._setHistory(
            opt_problem.name, store_hst, hot_start, def_fname)

        gradient = Gradient(opt_problem, sens_type, sens_mode, sens_step,
                            *args, **kwargs)

        # ======================================================================
        # NLPQLP - Objective/Constraint Values Function
        # ======================================================================
        def nlfunc(l, nmax, mmax, x, lactive, active, f, g):

            if self.pll_type == 'SPM':
                mxi = myrank
            else:
                mxi = 0

            # Variables Groups Handling
            if opt_problem.use_groups:
                xg = {}
                for group in group_ids.keys():
                    if group_ids[group][1] - group_ids[group][0] == 1:
                        xg[group] = x[group_ids[group][0], mxi]
                    else:
                        xg[group] = x[group_ids[group][0]:group_ids[group][1],
                                      mxi]
                xn = xg
            else:
                xn = x[:-1, mxi]

            # Flush Output Files
            self.flushFiles()

            # Evaluate User Function
            fail = 0
            ff = []
            gg = []
            if myrank == 0:
                if self.h_start:
                    for proc in range(l):
                        [vals, hist_end
                         ] = hos_file.read(ident=['obj', 'con', 'fail'])
                        if hist_end:
                            self.h_start = False
                            hos_file.close()
                        else:
                            [ff, gg, fail] = [
                                vals['obj'][0][0], vals['con'][0],
                                int(vals['fail'][0][0])
                            ]
                            f[proc] = ff
                            g[:, proc] = gg

            if self.pll:
                self.h_start = Bcast(self.h_start, root=0)

            if self.h_start and self.pll:
                [f, g] = Bcast([f, g], root=0)
            elif not self.h_start:
                [ff, gg, fail] = opt_problem.obj_fun(xn, *args, **kwargs)

                # Objective Assignment
                if isinstance(ff, complex):
                    f[mxi] = ff.astype(float)
                else:
                    f[mxi] = ff

                # Constraints Assignment (negative gg as nlpqlp uses g(x) >= 0)
                for i in range(len(opt_problem.constraints.keys())):
                    if isinstance(gg[i], complex):
                        g[i, mxi] = -gg[i].astype(float)
                    else:
                        g[i, mxi] = -gg[i]

                if self.pll_type == 'SPM':
                    send_buf = {}
                    send_buf[myrank] = {'fi': f[mxi], 'gi': g[:, mxi]}
                    if myrank != 0:
                        Send(send_buf, dest=0)
                    else:
                        p_results = []
                        for proc in range(1, nproc):
                            p_results.append(Recv(source=proc))

                    if myrank == 0:
                        for proc in range(nproc - 1):
                            for i in p_results[proc].keys():
                                f[i] = p_results[proc][i]['fi']
                                g[:, i] = p_results[proc][i]['gi']
                    [f, g] = Bcast([f, g], root=0)

            # Store History
            if myrank == 0:
                if self.sto_hst:
                    for proc in range(l):
                        log_file.write(x[:-1, proc], 'x')
                        log_file.write(f[proc], 'obj')
                        log_file.write(g[:, proc], 'con')
                        log_file.write(fail, 'fail')

            return f, g

        # ======================================================================
        # NLPQLP - Objective/Constraint Gradients Function
        # ======================================================================
        def nlgrad(l, nmax, mmax, x, lactive, active, f, g, df, dg):

            if self.h_start:
                dff = []
                dgg = []
                if myrank == 0:
                    [vals,
                     hist_end] = hos_file.read(ident=['grad_obj', 'grad_con'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        dff = vals['grad_obj'][0].reshape(
                            (len(opt_problem.objectives.keys()),
                             len(opt_problem.variables.keys())))
                        dgg = vals['grad_con'][0].reshape(
                            (len(opt_problem.constraints.keys()),
                             len(opt_problem.variables.keys())))

                if self.pll:
                    self.h_start = Bcast(self.h_start, root=0)

                if self.h_start and self.pll:
                    [dff, dgg] = Bcast([dff, dgg], root=0)

            if not self.h_start:
                dff, dgg = gradient.getGrad(
                    x[:-1, 0], group_ids, [f[0]],
                    -g[0:len(opt_problem.constraints.keys()), 0], *args,
                    **kwargs)

            # Store History
            if self.sto_hst and (myrank == 0):
                log_file.write(dff, 'grad_obj')
                log_file.write(dgg, 'grad_con')

            # Gradient Assignment
            for i in range(len(opt_problem.variables.keys())):
                df[i] = dff[0, i]
                for j in range(len(opt_problem.constraints.keys())):
                    dg[j, i] = -dgg[j, i]

            return df, dg

        # Variables Handling
        nvar = len(opt_problem.variables.keys())
        xl = numpy.zeros([max(2, nvar + 1)], numpy.float)
        xu = numpy.zeros([max(2, nvar + 1)], numpy.float)
        xx = numpy.zeros([max(2, nvar + 1), nproc], numpy.float)
        i = 0
        for key in opt_problem.variables.keys():
            if opt_problem.variables[key].type == 'c':
                xl[i] = opt_problem.variables[key].lower
                xu[i] = opt_problem.variables[key].upper
                for proc in range(nproc):
                    xx[i, proc] = opt_problem.variables[key].value
            elif opt_problem.variables[key].type == 'i':
                raise IOError('NLPQLP cannot handle integer design variables')
            elif opt_problem.variables[key].type == 'd':
                raise IOError('NLPQLP cannot handle discrete design variables')
            i += 1

        # Variables Groups Handling
        group_ids = {}
        if opt_problem.use_groups:
            k = 0
            for key in opt_problem.vargroups.keys():
                group_len = len(opt_problem.vargroups[key]['ids'])
                group_ids[opt_problem.vargroups[key]['name']] = [
                    k, k + group_len
                ]
                k += group_len

        # Constraints Handling
        ncon = len(opt_problem.constraints.keys())
        neqc = 0
        gg = numpy.zeros([ncon, nproc], numpy.float)
        if ncon > 0:
            i = 0
            for key in opt_problem.constraints.keys():
                if opt_problem.constraints[key].type == 'e':
                    neqc += 1
                if self.pll is False:
                    gg[i, 0] = opt_problem.constraints[key].value
                else:
                    for proc in range(nproc):
                        gg[i, proc] = opt_problem.constraints[key].value
                i += 1

        # Objective Handling
        objfunc = opt_problem.obj_fun
        if len(opt_problem.objectives.keys()) > 1:
            raise IOError('NLPQLP cannot handle multi-objective problems')

        ff = []
        for key in opt_problem.objectives.keys():
            ff.append(opt_problem.objectives[key].value)

        ff = numpy.array(ff * nproc, numpy.float)

        # Setup argument list values
        ll = numpy.array([nproc], numpy.int)
        mm = numpy.array([ncon], numpy.int)
        me = numpy.array([neqc], numpy.int)
        mmax = numpy.array([max(1, mm)], numpy.int)
        nn = numpy.array([nvar], numpy.int)
        nmax = numpy.array([max(2, nn + 1)], numpy.int)
        mnn2 = numpy.array([mmax + nmax + nmax + 2], numpy.int)
        gg = numpy.zeros([mmax, ll], numpy.float)
        df = numpy.zeros([nmax], numpy.float)
        dg = numpy.zeros([mmax, nmax], numpy.float)
        uu = numpy.zeros([mnn2], numpy.float)
        cc = numpy.zeros([nmax, nmax], numpy.float)
        dd = numpy.zeros([nmax], numpy.float)
        acc = numpy.array([self.options['ACC'][1]], numpy.float)
        accqp = numpy.array([self.options['ACCQP'][1]], numpy.float)
        stpmin = numpy.array([self.options['STPMIN'][1]], numpy.float)
        maxfun = numpy.array([self.options['MAXFUN'][1]], numpy.int)
        maxit = numpy.array([self.options['MAXIT'][1]], numpy.int)
        if nproc != 1:
            maxnm = numpy.array([max(1, min(50, nproc))], numpy.int)
        else:
            maxnm = numpy.array([0], numpy.int)

        rhob = self.options['RHOB'][1]
        if 0 <= self.options['MODE'][1] <= 18:
            mode = self.options['MODE'][1]
        else:
            raise IOError('Incorrect Mode Setting')

        ifail = numpy.array([0], numpy.int)
        if myrank == 0:
            if 0 <= self.options['IPRINT'][1] <= 4:
                iprint = numpy.array([self.options['IPRINT'][1]], numpy.int)
            else:
                raise IOError('Incorrect Output Level Setting')
        else:
            iprint = numpy.array([0], numpy.int)

        iout = self.options['IOUT'][1]
        ifile = self.options['IFILE'][1]
        if iprint > 0:
            if os.path.isfile(ifile):
                os.remove(ifile)

        lwa = numpy.array([
            23 * nmax + 4 * mmax + 3 * mmax + 150 + 3 * nmax * nmax / 2 +
            10 * nmax + nmax + mmax + 1
        ], numpy.int)
        wa = numpy.zeros([lwa], numpy.float)
        lkwa = numpy.array([25 + nmax], numpy.int)
        kwa = numpy.zeros([lkwa], numpy.intc)
        lactiv = numpy.array([2 * mmax + 10], numpy.int)
        active = numpy.zeros([lactiv], numpy.bool)
        lql = numpy.array([self.options['LQL'][1]], numpy.bool)
        nfun = numpy.array([0], numpy.int)
        ngrd = numpy.array([0], numpy.int)

        # Run NLPQLP
        t0 = time.time()
        xx, ff, gg, uu, nfun, ngrd = nlpqlp.nlpqlp_wrap(
            ll, mm, me, mmax, nn, nmax, mnn2, xx, ff, gg, df, dg, uu, xl, xu,
            cc, dd, acc, accqp, stpmin, maxfun, maxit, maxnm, rhob, mode,
            ifail, iprint, iout, ifile, wa, lwa, kwa, lkwa, active, lactiv,
            lql, nfun, ngrd, nlfunc, nlgrad)
        sol_time = time.time() - t0

        if myrank == 0:
            if self.sto_hst:
                log_file.close()
                if tmp_file:
                    hos_file.close()
                    name = hos_file.filename
                    os.remove(name + '.cue')
                    os.remove(name + '.bin')
                    os.rename(name + '_tmp.cue', name + '.cue')
                    os.rename(name + '_tmp.bin', name + '.bin')

        if iprint > 0:
            nlpqlp.closeunit(self.options['IOUT'][1])

        # Store Results
        sol_inform = {}
        sol_inform['value'] = ifail[0]
        sol_inform['text'] = self.getInform(ifail[0])

        if store_sol:

            sol_name = 'NLPQLP Solution to ' + opt_problem.name

            sol_options = copy.copy(self.options)
            # if sol_options.has_key('defaults'):
            if 'defaults' in sol_options:
                del sol_options['defaults']

            sol_evals = nfun + ngrd * nvar

            sol_vars = copy.deepcopy(opt_problem.variables)
            i = 0
            for key in sol_vars.keys():
                sol_vars[key].value = xx[i, 0]
                i += 1

            sol_objs = copy.deepcopy(opt_problem.objectives)
            i = 0
            for key in sol_objs.keys():
                sol_objs[key].value = ff[0]
                i += 1

            if ncon > 0:
                sol_cons = copy.deepcopy(opt_problem.constraints)
                i = 0
                for key in sol_cons.keys():
                    sol_cons[key].value = -gg[i, 0]
                    i += 1
            else:
                sol_cons = {}

            if ncon > 0:
                sol_lambda = numpy.zeros(ncon, float)
                for i in range(ncon):
                    sol_lambda[i] = uu[i]
            else:
                sol_lambda = {}

            opt_problem.addSol(self.__class__.__name__,
                               sol_name,
                               objfunc,
                               sol_time,
                               sol_evals,
                               sol_inform,
                               sol_vars,
                               sol_objs,
                               sol_cons,
                               sol_options,
                               display_opts=disp_opts,
                               Lambda=sol_lambda,
                               Sensitivities=sens_type,
                               myrank=myrank,
                               arguments=args,
                               **kwargs)

        return ff, xx, sol_inform
Esempio n. 10
0
    def __solve__(self,
                  opt_problem,
                  sens_type='FD',
                  store_sol=True,
                  store_hst=False,
                  hot_start=False,
                  disp_opts=False,
                  sens_mode='',
                  sens_step={},
                  *args,
                  **kwargs):
        """Run Optimizer (Optimize Routine)
        
        **Keyword arguments:**
        
        - opt_problem -> INST: Optimization instance
        - sens_type -> STR/FUNC: Gradient type, *Default* = 'FD' 
        - store_sol -> BOOL: Store solution in Optimization class flag,
                       *Default* = True 
        - disp_opts -> BOOL: Flag to display options in solution text,
                       *Default* = False
        - store_hst -> BOOL/STR: Flag/filename to store optimization history,
                       *Default* = False
        - hot_start -> BOOL/STR: Flag/filename to read optimization history,
                       *Default* = False
        - sens_mode -> STR: Flag for parallel gradient calculation,
                       *Default* = ''
        - sens_step -> FLOAT: Sensitivity setp size,
                       *Default* = {} [corresponds to 1e-6 (FD), 1e-20(CS)]
        
        Additional arguments and keyword arguments are passed to the
        objective function call.
        
        Documentation last updated:  February. 2, 2011 - Ruben E. Perez

        """
        if self.poa and (sens_mode.lower() == 'pgc'):
            raise NotImplementedError(
                "pyMMFD - Current implementation only allows single level "
                "parallelization, either 'POA' or 'pgc'")

        if self.poa or (sens_mode.lower() == 'pgc'):
            try:
                import mpi4py
                from mpi4py import MPI
            except ImportError:
                print('pyMMFD: Parallel objective Function Analysis'
                      ' requires mpi4py')

            comm = MPI.COMM_WORLD
            nproc = comm.Get_size()
            if mpi4py.__version__[0] == '0':
                Bcast = comm.Bcast
            # elif mpi4py.__version__[0] == '1':
            else:  # version can be 1, 2, 3 .... or more
                Bcast = comm.bcast

            self.pll = True
            self.myrank = comm.Get_rank()
        else:
            self.pll = False
            self.myrank = 0

        myrank = self.myrank

        def_fname = self.options['IFILE'][1].split('.')[0]
        hos_file, log_file, tmp_file = self._setHistory(
            opt_problem.name, store_hst, hot_start, def_fname)

        gradient = Gradient(opt_problem, sens_type, sens_mode, sens_step,
                            *args, **kwargs)

        # ======================================================================
        # MMFD - Objective/Constraint Values Function
        # ======================================================================
        def mmfdfun(nv, nc, x, f, g):

            # Variables Groups Handling
            if opt_problem.use_groups:
                xg = {}
                for group in group_ids.keys():
                    if group_ids[group][1] - group_ids[group][0] == 1:
                        xg[group] = x[group_ids[group][0]]
                    else:
                        xg[group] = x[group_ids[group][0]:group_ids[group][1]]
                xn = xg
            else:
                xn = x

            # Flush Output Files
            self.flushFiles()

            # Evaluate User Function
            fail = 0
            ff = []
            gg = []
            if myrank == 0:
                if self.h_start:
                    [vals,
                     hist_end] = hos_file.read(ident=['obj', 'con', 'fail'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        [ff, gg, fail] = [
                            vals['obj'][0][0], vals['con'][0],
                            int(vals['fail'][0][0])
                        ]

            if self.pll:
                self.h_start = Bcast(self.h_start, root=0)

            if self.h_start and self.pll:
                [ff, gg, fail] = Bcast([ff, gg, fail], root=0)
            elif not self.h_start:
                [ff, gg, fail] = opt_problem.obj_fun(xn, *args, **kwargs)

            # Store History
            if myrank == 0:
                if self.sto_hst:
                    log_file.write(x, 'x')
                    log_file.write(ff, 'obj')
                    log_file.write(gg, 'con')
                    log_file.write(fail, 'fail')

            # Objective Assignment
            if isinstance(ff, complex):
                f = ff.astype(float)
            else:
                f = ff

            # Constraints Assignment
            for i in range(len(opt_problem.constraints.keys())):
                if isinstance(gg[i], complex):
                    g[i] = gg[i].astype(float)
                else:
                    g[i] = gg[i]

            return f, g

        # ======================================================================
        # MMFD - Objective/Constraint Gradients Function
        # ======================================================================
        def mmfdgrd(nv, nc, x, f, g, df, dg):

            if self.h_start:
                dff = []
                dgg = []
                if myrank == 0:
                    [vals,
                     hist_end] = hos_file.read(ident=['grad_obj', 'grad_con'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        dff = vals['grad_obj'][0].reshape(
                            (len(opt_problem.objectives.keys()),
                             len(opt_problem.variables.keys())))
                        dgg = vals['grad_con'][0].reshape(
                            (len(opt_problem.constraints.keys()),
                             len(opt_problem.variables.keys())))

                if self.pll:
                    self.h_start = Bcast(self.h_start, root=0)

                if self.h_start and self.pll:
                    [dff, dgg] = Bcast([dff, dgg], root=0)

            if not self.h_start:
                dff, dgg = gradient.getGrad(x, group_ids, [f], g, *args,
                                            **kwargs)

            # Store History
            if self.sto_hst and (myrank == 0):
                log_file.write(dff, 'grad_obj')
                log_file.write(dgg, 'grad_con')

            # Gradient Assignment
            for i in range(len(opt_problem.variables.keys())):
                df[i] = dff[0, i]
                for j in range(len(opt_problem.constraints.keys())):
                    dg[i, j] = dgg[j, i]

            return df, dg

        # Variables Handling
        nvar = len(opt_problem.variables.keys())
        xl = []
        xu = []
        xx = []
        for key in opt_problem.variables.keys():
            if opt_problem.variables[key].type == 'c':
                xl.append(opt_problem.variables[key].lower)
                xu.append(opt_problem.variables[key].upper)
                xx.append(opt_problem.variables[key].value)
            elif opt_problem.variables[key].type == 'i':
                raise IOError('MMFD cannot handle integer design variables')
            elif opt_problem.variables[key].type == 'd':
                raise IOError('MMFD cannot handle discrete design variables')

        xl = numpy.array(xl)
        xu = numpy.array(xu)
        xx = numpy.array(xx)

        # Variables Groups Handling
        group_ids = {}
        if opt_problem.use_groups:
            k = 0
            for key in opt_problem.vargroups.keys():
                group_len = len(opt_problem.vargroups[key]['ids'])
                group_ids[opt_problem.vargroups[key]['name']] = [
                    k, k + group_len
                ]
                k += group_len

        # Constraints Handling
        ncon = len(opt_problem.constraints.keys())
        neqc = 0
        gg = []
        idg = []
        if ncon > 0:
            for key in opt_problem.constraints.keys():
                if opt_problem.constraints[key].type == 'i':
                    idg.append(1)
                elif opt_problem.constraints[key].type == 'e':
                    idg.append(-1)
                gg.append(opt_problem.constraints[key].value)
        else:
            raise IOError(
                'MMFD support for unconstrained problems not implemented yet')

        gg = numpy.array(gg)
        idg = numpy.array(idg, numpy.int)

        # Objective Handling
        objfunc = opt_problem.obj_fun
        nobj = len(opt_problem.objectives.keys())
        ff = []
        for key in opt_problem.objectives.keys():
            ff.append(opt_problem.objectives[key].value)

        ff = numpy.array(ff)

        # Setup argument list values
        ndv = numpy.array([nvar], numpy.int)
        ncn = numpy.array([ncon], numpy.int)
        if 0 <= self.options['IOPT'][1] <= 1:
            iopt = numpy.array([self.options['IOPT'][1]], numpy.int)
        else:
            raise IOError('Incorrect Feasible Directions Approach')

        if 0 <= self.options['IONED'][1] <= 3:
            ioned = numpy.array([self.options['IONED'][1]], numpy.int)
        else:
            raise IOError('Incorrect One-Dimensional Search Method')

        if myrank == 0:
            if 0 <= self.options['IPRINT'][1] <= 2:
                iprint = numpy.array([self.options['IPRINT'][1]], numpy.int)
            else:
                raise IOError('Incorrect Output Level Setting')
        else:
            iprint = numpy.array([0], numpy.int)

        # iout = numpy.array([self.options['IOUT'][1]], numpy.int)
        ifile = self.options['IFILE'][1]
        if iprint > 0:
            if os.path.isfile(ifile):
                os.remove(ifile)

        ct = numpy.array([self.options['CT'][1]], numpy.float)
        ctmin = numpy.array([self.options['CTMIN'][1]], numpy.float)

        finit, ginit = mmfdfun([], [], xx, ff, gg)
        dabobj = numpy.array([self.options['DABOBJ'][1] * finit], numpy.float)

        delobj = numpy.array([self.options['DELOBJ'][1]], numpy.float)
        thetaz = numpy.array([self.options['THETAZ'][1]], numpy.float)
        pmlt = numpy.array([self.options['PMLT'][1]], numpy.float)
        itmax = numpy.array([self.options['ITMAX'][1]], numpy.int)
        itrmop = numpy.array([self.options['ITRMOP'][1]], numpy.int)
        nrwk0 = 500
        nrwk1 = 10 * (2 * nvar + ncon)
        nrwk2 = (ncon + 2 * nvar + 3)
        nrwk3 = (ncon + 2 * nvar) * ((ncon + 2 * nvar) / 2 + 1)
        nrwkS = nrwk0 + nrwk1 + nrwk2 + nrwk3
        nrwk = numpy.array([nrwkS], numpy.int)
        wk = numpy.zeros([nrwk], numpy.float)
        nriwk = numpy.array([nrwkS], numpy.int)
        iwk = numpy.zeros([nriwk], numpy.int)

        nfun = numpy.array([0], numpy.int)
        ngrd = numpy.array([0], numpy.int)

        # Run MMFD
        t0 = time.time()
        mmfd.mmfd(iopt, ioned, iprint, ndv, ncn, xx, xl, xu, ff, gg, idg, wk,
                  nrwk, iwk, nriwk, ifile, ct, ctmin, dabobj, delobj, thetaz,
                  pmlt, itmax, itrmop, nfun, ngrd, mmfdfun, mmfdgrd)
        sol_time = time.time() - t0

        if myrank == 0:
            if self.sto_hst:
                log_file.close()
                if tmp_file:
                    hos_file.close()
                    name = hos_file.filename
                    os.remove(name + '.cue')
                    os.remove(name + '.bin')
                    os.rename(name + '_tmp.cue', name + '.cue')
                    os.rename(name + '_tmp.bin', name + '.bin')

        if iprint > 0:
            #   mmfd.closeunit(self.options['IOUT'][1])
            mmfd.closeunit(6)

        # Store Results
        sol_inform = {}
        sol_inform['value'] = []
        sol_inform['text'] = {}

        if store_sol:

            sol_name = 'MMFD Solution to ' + opt_problem.name

            sol_options = copy.copy(self.options)
            # if sol_options.has_key('defaults'):
            if 'defaults' in sol_options:
                del sol_options['defaults']

            sol_evals = nfun[0] + ngrd[0] * nvar

            sol_vars = copy.deepcopy(opt_problem.variables)
            i = 0
            for key in sol_vars.keys():
                sol_vars[key].value = xx[i]
                i += 1

            sol_objs = copy.deepcopy(opt_problem.objectives)
            i = 0
            for key in sol_objs.keys():
                sol_objs[key].value = ff[i]
                i += 1

            if ncon > 0:
                sol_cons = copy.deepcopy(opt_problem.constraints)
                i = 0
                for key in sol_cons.keys():
                    sol_cons[key].value = gg[i]
                    i += 1
            else:
                sol_cons = {}

            sol_lambda = {}

            opt_problem.addSol(self.__class__.__name__,
                               sol_name,
                               objfunc,
                               sol_time,
                               sol_evals,
                               sol_inform,
                               sol_vars,
                               sol_objs,
                               sol_cons,
                               sol_options,
                               display_opts=disp_opts,
                               Lambda=sol_lambda,
                               Sensitivities=sens_type,
                               myrank=myrank,
                               arguments=args,
                               **kwargs)

        return ff, xx, sol_inform
Esempio n. 11
0
    def __solve__(self,
                  opt_problem,
                  sens_type='FD',
                  store_sol=True,
                  disp_opts=False,
                  store_hst=False,
                  hot_start=False,
                  sens_mode='',
                  sens_step={},
                  *args,
                  **kwargs):
        """Run Optimizer (Optimize Routine)
        
        **Keyword arguments:**
        
        - opt_problem -> INST: Optimization instance
        - sens_type -> STR/FUNC: Gradient type, *Default* = 'FD' 
        - store_sol -> BOOL: Store solution in Optimization class flag,
                       *Default* = True 
        - disp_opts -> BOOL: Flag to display options in solution text,
                       *Default* = False
        - store_hst -> BOOL/STR: Flag/filename to store optimization history,
                       *Default* = False
        - hot_start -> BOOL/STR: Flag/filename to read optimization history,
                       *Default* = False
        - sens_mode -> STR: Flag for parallel gradient calculation,
                       *Default* = ''
        - sens_step -> FLOAT: Sensitivity step size,
                       *Default* = {} [corresponds to 1e-6 (FD), 1e-20(CS)]
        
        Additional arguments and keyword arguments are passed to the objective
        function call.
        
        Documentation last updated:  Feb. 2, 2011 - Peter W. Jansen

        """
        if self.poa and (sens_mode.lower() == 'pgc'):
            raise NotImplementedError("pySNOPT - Current implementation only "
                                      "allows single level parallelization, "
                                      "either 'POA' or 'pgc'")

        if self.poa or (sens_mode.lower() == 'pgc'):
            try:
                import mpi4py
                from mpi4py import MPI
            except ImportError:
                print('pySNOPT: Parallel objective Function Analysis '
                      'requires mpi4py')

            comm = MPI.COMM_WORLD
            nproc = comm.Get_size()
            if mpi4py.__version__[0] == '0':
                Bcast = comm.Bcast
            # elif mpi4py.__version__[0] == '1':
            else:  # version can be 1, 2, 3 .... or more
                Bcast = comm.bcast

            self.pll = True
            self.myrank = comm.Get_rank()
        else:
            self.pll = False
            self.myrank = 0

        myrank = self.myrank

        def_fname = self.options['Print file'][1].split('.')[0]
        hos_file, log_file, tmp_file = self._setHistory(
            opt_problem.name, store_hst, hot_start, def_fname)

        gradient = Gradient(opt_problem, sens_type, sens_mode, sens_step,
                            *args, **kwargs)

        # ======================================================================
        # SNOPT-C - Objective/Constraint Values Function
        # ======================================================================
        def snfuncgrag(mode, njac, x, f_obj, g_obj, f_con, g_con):

            # Variables Groups Handling
            if opt_problem.use_groups:
                xg = {}
                for group in group_ids.keys():
                    if group_ids[group][1] - group_ids[group][0] == 1:
                        xg[group] = x[group_ids[group][0]]
                    else:
                        xg[group] = x[group_ids[group][0]:group_ids[group][1]]
                xn = xg
            else:
                xn = x

            # Flush Output Files
            self.flushFiles()

            # Evaluate User Function
            fail = 0
            if myrank == 0:
                if self.h_start:
                    [vals,
                     hist_end] = hos_file.read(ident=['obj', 'con', 'fail'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        [f_obj, f_con, fail] = [
                            vals['obj'][0][0], vals['con'][0],
                            int(vals['fail'][0][0])
                        ]

            if self.pll:
                self.h_start = Bcast(self.h_start, root=0)

            if self.h_start and self.pll:
                [f_obj, f_con, fail] = Bcast([f_obj, f_con, fail], root=0)
            elif not self.h_start:
                [f_obj, f_con, fail] = opt_problem.obj_fun(xn, *args, **kwargs)

            # Store History
            if myrank == 0:
                if self.sto_hst:
                    log_file.write(x, 'x')
                    log_file.write(f_obj, 'obj')
                    log_file.write(f_con, 'con')
                    log_file.write(fail, 'fail')

            if fail == 1:
                mode = -1
                return mode

            # Gradients
            if mode != 0 and self.h_start:
                if myrank == 0:
                    [vals,
                     hist_end] = hos_file.read(ident=['grad_obj', 'grad_con'])
                    if hist_end:
                        self.h_start = False
                        hos_file.close()
                    else:
                        g_obj = vals['grad_obj'][0]
                        g_con = vals['grad_con'][0].reshape(
                            (len(opt_problem.constraints.keys()),
                             len(opt_problem.variables.keys())))

                if self.pll:
                    self.h_start = Bcast(self.h_start, root=0)

                if self.h_start and self.pll:
                    [g_obj, g_con] = Bcast([g_obj, g_con], root=0)

            if mode != 0 and not self.h_start:
                dff, dgg = gradient.getGrad(x, group_ids, [f_obj], f_con,
                                            *args, **kwargs)

                for i in range(len(opt_problem.variables.keys())):
                    g_obj[i] = dff[0, i]
                    for j in range(len(opt_problem.constraints.keys())):
                        g_con[j, i] = dgg[j, i]

            if myrank == 0:
                if mode != 0 and self.sto_hst:
                    log_file.write(g_obj, 'grad_obj')
                    log_file.write(g_con, 'grad_con')

            # Objective Assignment
            if isinstance(f_obj, complex):
                f_obj = f_obj.astype(float)

            # Constraints Assignment
            for i in range(len(opt_problem.constraints.keys())):
                if isinstance(f_con[i], complex):
                    f_con[i] = f_con[i].astype(float)

            if not f_con:
                f_con = [0]

            return mode, f_obj, g_obj, f_con, g_con

        # Variables Handling
        nvar = len(opt_problem.variables.keys())
        blx = []
        bux = []
        xs = []
        for key in opt_problem.variables.keys():
            if opt_problem.variables[key].type == 'c':
                blx.append(opt_problem.variables[key].lower)
                bux.append(opt_problem.variables[key].upper)
                xs.append(opt_problem.variables[key].value)
            elif opt_problem.variables[key].type == 'i':
                raise IOError('SNOPT cannot handle integer design variables')
            elif opt_problem.variables[key].type == 'd':
                raise IOError('SNOPT cannot handle discrete design variables')

        blx = numpy.array(blx)
        bux = numpy.array(bux)
        xs = numpy.array(xs)

        # Variables Groups Handling
        group_ids = {}
        if opt_problem.use_groups:
            k = 0
            for key in opt_problem.vargroups.keys():
                group_len = len(opt_problem.vargroups[key]['ids'])
                group_ids[opt_problem.vargroups[key]['name']] = [
                    k, k + group_len
                ]
                k += group_len

        # Constraints Handling
        ncon = len(opt_problem.constraints.keys())
        blc = []
        buc = []
        if ncon > 0:
            for key in opt_problem.constraints.keys():
                if opt_problem.constraints[key].type == 'e':
                    blc.append(opt_problem.constraints[key].equal)
                    buc.append(opt_problem.constraints[key].equal)
                elif opt_problem.constraints[key].type == 'i':
                    blc.append(opt_problem.constraints[key].lower)
                    buc.append(opt_problem.constraints[key].upper)
        else:
            # if ((store_sol) and (myrank == 0)):
            #   print "Optimization Problem Does Not Have Constraints\n"
            #   print "Unconstrained Optimization Initiated\n"
            ncon = 1
            blc.append(-inf)
            buc.append(inf)
        blc = numpy.array(blc)
        buc = numpy.array(buc)

        # Objective Handling
        objfunc = opt_problem.obj_fun
        nobj = len(opt_problem.objectives.keys())
        ff = []
        for key in opt_problem.objectives.keys():
            ff.append(opt_problem.objectives[key].value)

        ff = numpy.array(ff, numpy.float)

        # Initialize SNOPT
        iPrint = self.options['iPrint'][1]
        if myrank != 0:
            iPrint = 0

        PrintFile = self.options['Print file'][1]
        if iPrint != 0:
            if os.path.isfile(PrintFile):
                os.remove(PrintFile)

            ierror = snopt.openunit(iPrint, numpy.array(PrintFile),
                                    numpy.array('new'),
                                    numpy.array('sequential'))
            if ierror != 0:
                raise IOError('Failed to properly open %s, ierror = %3d' %
                              (PrintFile, ierror))

        iSumm = self.options['iSumm'][1]
        if myrank != 0:
            iSumm = 0

        SummFile = self.options['Summary file'][1]
        if iSumm != 0:
            if os.path.isfile(SummFile):
                os.remove(SummFile)

            ierror = snopt.openunit(iSumm, numpy.array(SummFile),
                                    numpy.array('new'),
                                    numpy.array('sequential'))
            if ierror != 0:
                raise IOError('Failed to properly open %s, ierror = %3d' %
                              (SummFile, ierror))

        lencw = 500
        leniw = 500 + 100 * (ncon + nvar)
        lenrw = 500 + 200 * (ncon + nvar)

        self.options['Total integer workspace'][1] = leniw
        self.options['Total real workspace'][1] = lenrw

        string = []
        for i in range(lencw):
            string.append('        ')

        cw = numpy.array(string, 'c')
        iw = numpy.zeros(leniw, 'i')
        rw = numpy.zeros(lenrw, numpy.float)
        snopt.sninit(iPrint, iSumm, cw, iw, rw)

        # Memory allocation
        ne = ncon * nvar
        nnCon = numpy.array(ncon, numpy.int)
        nnObj = numpy.array(nvar, numpy.int)
        nnJac = numpy.array(nvar, numpy.int)
        neGcon = nnCon * nnJac
        iExit = 0
        mincw, miniw, minrw, cw = snopt.snmemb(iExit, ncon, nvar, ne, neGcon,
                                               nnCon, nnJac, nnObj, cw, iw, rw)
        if (minrw > lenrw) or (miniw > leniw) or (mincw > lencw):
            if mincw > lencw:
                lencw = mincw
                string = ""
                for i in range(lencw):
                    string += "        "

                cw = numpy.transpose(
                    numpy.reshape(numpy.array(string), (lencw, 8)))

            if miniw > leniw:
                leniw = miniw
                iw = numpy.zeros(leniw, 'i')

            if minrw > lenrw:
                lenrw = minrw
                rw = numpy.zeros(lenrw, numpy.float)

            snopt.sninit(iPrint, iSumm, cw, iw, rw)

        # Set Options
        inform = numpy.array([-1], numpy.int)
        for i in range(len(self.set_options)):
            name = self.set_options[i][0]
            value = self.set_options[i][1]
            if isinstance(value, str):
                if name == 'Start':
                    if value == 'Cold':
                        snopt.snset('Cold start', iPrint, iSumm, inform, cw,
                                    iw, rw)
                    elif value == 'Warm':
                        snopt.snset('Warm start', iPrint, iSumm, inform, cw,
                                    iw, rw)
                elif name == 'Problem Type':
                    if value == 'Minimize':
                        snopt.snset('Minimize', iPrint, iSumm, inform, cw, iw,
                                    rw)
                    elif value == 'Maximize':
                        snopt.snset('Maximize', iPrint, iSumm, inform, cw, iw,
                                    rw)
                    elif value == 'Feasible point':
                        snopt.snset('Feasible point', iPrint, iSumm, inform,
                                    cw, iw, rw)
                elif name == 'Print file':
                    snopt.snset(name + ' ' + '%d' % iPrint, iPrint, iSumm,
                                inform, cw, iw, rw)
                elif name == 'Summary file':
                    snopt.snset(name + ' ' + '%d' % iSumm, iPrint, iSumm,
                                inform, cw, iw, rw)
                else:
                    snopt.snset(name + ' ' + value, iPrint, iSumm, inform, cw,
                                iw, rw)
            elif isinstance(value, float):
                snopt.snsetr(name, value, iPrint, iSumm, inform, cw, iw, rw)
            elif isinstance(value, int):
                if (name == 'iPrint') and iPrint == 0:
                    pass
                elif (name == 'iSumm') and iSumm == 0:
                    pass
                else:
                    snopt.snseti(name, value, iPrint, iSumm, inform, cw, iw,
                                 rw)
            elif isinstance(value, type(None)):
                snopt.snset(name, iPrint, iSumm, inform, cw, iw, rw)

        # Setup argument list values
        start = numpy.array(self.options['Start'][1])
        nName = numpy.array([1], numpy.int)
        nnCon = numpy.array(ncon, numpy.int)
        nnObj = numpy.array(nvar, numpy.int)
        nnJac = numpy.array(nvar, numpy.int)
        iObj = numpy.array([0], numpy.int)
        ObjAdd = numpy.array([0.], numpy.float)
        ProbNm = numpy.array(self.name)
        a = numpy.zeros(ne, numpy.float)
        ha = numpy.zeros(ne, 'i')
        ine = 0
        for j in range(nvar):
            for i in range(ncon):
                ha[ine] = i + 1
                ine += 1

        ka = numpy.zeros(nvar + 1, 'i')
        ka[0] = 1
        for i in range(1, nvar + 1):
            ka[i] = ka[i - 1] + ncon

        xs = numpy.concatenate((xs, numpy.zeros(ncon, numpy.float)))
        bl = numpy.concatenate((blx, blc))
        bu = numpy.concatenate((bux, buc))
        lencu = numpy.array([1], numpy.int)
        leniu = numpy.array([1], numpy.int)
        lenru = numpy.array([1], numpy.int)
        cu = numpy.array(["        "], 'c')
        iu = numpy.zeros([leniu[0]], numpy.int)
        ru = numpy.zeros([lenru[0]], numpy.float)
        hs = numpy.zeros(nvar + ncon, 'i')
        Names = numpy.array(["        "], 'c')
        pi = numpy.zeros(ncon, numpy.float)
        rc = numpy.zeros(nvar + ncon, numpy.float)
        # inform = numpy.array([-1], numpy.int)
        mincw = numpy.array([0], numpy.int)
        miniw = numpy.array([0], numpy.int)
        minrw = numpy.array([0], numpy.int)
        nS = numpy.array([0], numpy.int)
        ninf = numpy.array([0], numpy.int)
        sinf = numpy.array([0.], numpy.float)

        # Run SNOPT
        t0 = time.time()
        snopt.snoptc(start, nnCon, nnObj, nnJac, iObj, ObjAdd, ProbNm,
                     snfuncgrag, a, ha, ka, bl, bu, Names, hs, xs, pi, rc,
                     inform, mincw, miniw, minrw, nS, ninf, sinf, ff, cu, iu,
                     ru, cw, iw, rw)
        sol_time = time.time() - t0

        if myrank == 0:
            if self.sto_hst:
                log_file.close()
                if tmp_file:
                    hos_file.close()
                    name = hos_file.filename
                    os.remove(name + '.cue')
                    os.remove(name + '.bin')
                    os.rename(name + '_tmp.cue', name + '.cue')
                    os.rename(name + '_tmp.bin', name + '.bin')

            if iPrint != 0:
                snopt.closeunit(self.options['iPrint'][1])

            if iSumm != 0:
                snopt.closeunit(self.options['iSumm'][1])

        # Store Results
        sol_inform = {}
        sol_inform['value'] = inform
        sol_inform['text'] = self.getInform(inform)

        if store_sol:

            sol_name = 'SNOPT Solution to ' + opt_problem.name

            sol_options = copy.copy(self.options)
            # if sol_options.has_key('defaults'):
            if 'defaults' in sol_options:
                del sol_options['defaults']

            sol_evals = 0

            sol_vars = copy.deepcopy(opt_problem.variables)
            i = 0
            for key in sol_vars.keys():
                sol_vars[key].value = xs[i]
                i += 1

            sol_objs = copy.deepcopy(opt_problem.objectives)
            i = 0
            for key in sol_objs.keys():
                sol_objs[key].value = ff[i]
                i += 1

            sol_cons = copy.deepcopy(opt_problem.constraints)
            i = 0
            for key in sol_cons.keys():
                sol_cons[key].value = xs[nvar + i]
                i += 1

            if ncon > 0:
                sol_lambda = numpy.zeros(ncon, float)
                for i in range(ncon):
                    sol_lambda[i] = pi[i]
            else:
                sol_lambda = {}

            opt_problem.addSol(self.__class__.__name__,
                               sol_name,
                               objfunc,
                               sol_time,
                               sol_evals,
                               sol_inform,
                               sol_vars,
                               sol_objs,
                               sol_cons,
                               sol_options,
                               display_opts=disp_opts,
                               Lambda=sol_lambda,
                               Sensitivities=sens_type,
                               myrank=myrank,
                               arguments=args,
                               **kwargs)

        return ff, xs[0:nvar], sol_inform