Exemplo n.º 1
0
 def _add_real_parameter(self, name):
     """
     Adds a real parameter to the optimization problem object.
     
     Parameters::
         name --
             The name of the new parameter.
     
     Returns::
         par --
             The parameter variable
     """
     par = mc.RealVariable(self.op, MX.sym(name), mc.Variable.INTERNAL,
                           mc.Variable.PARAMETER)
     self.op.addVariable(par)
     return par
Exemplo n.º 2
0
 def _add_real_variable(self, name):
     """
     Adds a real variable to the optimization problem object.
     
     Parameters::
         name --
             The name of the new variable. Given as a string
     
     Returns::
         var --
             The added variable
     """
     var = mc.RealVariable(self.op, MX.sym(name), mc.Variable.INTERNAL,
                           mc.Variable.CONTINUOUS)
     self.op.addVariable(var)
     return var
Exemplo n.º 3
0
 def _add_real_input(self, name):
     """
     Adds a new real input to the optimization problem object.
     
     Parameters::
         name --
             The name of the new input. Given as a string
     
     Returns::
         input --
             The added input variable 
     """
     inp = mc.RealVariable(self.op, MX.sym(name), mc.Variable.INPUT,
                           mc.Variable.CONTINUOUS)
     self.op.addVariable(inp)
     return inp
Exemplo n.º 4
0
def optimize_for_initial_values(op, x_0_guess, u_0, MHE_opts):
    """
    Solves an optimization from time zero to time zero to generate 
    initial values for the state derivatives and the algebraic 
    variables.
    
    The input 'op' is mutated. Parameters for startTime and finalTime 
    are added if they do not already exist. The values for these 
    parameters are set to zero.
    
    Parameters::
        op --
            An OptimizationProblem object.
        
        x_0_guess --
            A dict containing a guess of the initial state 
            values. Items are on the form ('name', value).
            
        u_0 --
            A dictionary on the form 
            dict([('input1', u1),...,('inputN', uN)]), 
            where 'inputX' is the name of the input and uX is the 
            value of the input at time zero. N is the number of control 
            signals and X goes from 1 to N.
        
        MHE_opts --
            A MHEOptions object. See the documentation of the 
            options object for more details.
            
    Returns::
        dx_0 --
            The initial value of the derivative of the state 
            variables. Given as a list of tuples on the form 
            (varName, value).

        c_0 --
            The initial value of the algebraic variables. 
            Given as a list of tuples on the form 
            (varName, value)
    """
    (x_0_guess, u_0, process_noise_names, undefined_input_names, MHE_opts) = \
                                _check_inputs(op, x_0_guess, u_0, MHE_opts)
    input_names = MHE_opts['input_names']
    #Check if there are parameters for start and final time, add if not
    st_var = op.getVariable('startTime')
    if st_var == None:
        par = mc.RealVariable(op, MX.sym('startTime'), mc.Variable.INTERNAL,
                              mc.Variable.PARAMETER)
        op.addVariable(par)
    ft_var = op.getVariable('finalTime')
    if ft_var == None:
        par = mc.RealVariable(op, MX.sym('finalTime'), mc.Variable.INTERNAL,
                              mc.Variable.PARAMETER)
        op.addVariable(par)
    #Set the times
    op.setStartTime(MX(0.))
    op.set('startTime', 0.)
    op.setFinalTime(MX(0.))
    op.set('finalTime', 0.)
    ##Set the options for the optimization
    opts = op.optimize_options()
    #Specifies implicit Euler
    opts['n_cp'] = 1
    #Set one element between two points
    opts['n_e'] = 1

    #REMOVE MAYBE
    opts["IPOPT_options"]["print_level"] = 0

    external_data = _get_eliminated_data_object(u_0, process_noise_names,
                                                undefined_input_names,
                                                input_names)
    opts['external_data'] = external_data

    #Find the names of the initial state value parameters
    initial_value_names = [par.getName() for par in \
                           op.getVariables(op.REAL_PARAMETER_INDEPENDENT) \
                           if par.getName().startswith('_start_')]
    #Remove the _start_ prefix
    state_names = [name[7:] for name in initial_value_names]
    #Substitute for non alias variables
    state_names = [op.getModelVariable(name).getName() for name in state_names]

    for k in range(len(initial_value_names)):
        iv_name = initial_value_names[k]
        state_name = state_names[k]
        op.set(iv_name, x_0_guess[state_name])
    res = op.optimize(options=opts)
    (dx_0, c_0) = _extract_results(op, res, state_names)
    return (dx_0, c_0)
Exemplo n.º 5
0
    def _soften_constraints(self):
        """
        Changes hard variable bounds to soft constraints for all variables for
        which the user provided a constraint violation cost when creating the
        MPC object.
        
        The softened constraint is accieved by adding a cost to the objective
        integrand corresponding to the constraint violation cost * the 1-norm 
        for each variable. 
         
        """
        # Save pathconstraints
        path_constr = []
        for constr in self.op.getPathConstraints():
            path_constr.append(constr)

        # Change bounds on variables to soft constraints
        for name in list(self.constr_viol_costs.keys()):
            var = self.op.getVariable(name)

            # Create slack variable
            slack_var = casadi.MX.sym("%s_slack" % name)
            slack = ci.RealVariable(self.op, slack_var, 0, 3)
            slack.setMin(0)
            nominal = var.getNominal()

            # Check if nominal value is symbolic and find the value
            if nominal.isSymbolic():
                nominal = self.op.get(nominal.getName())
            else:
                nominal = nominal.getValue()

            if nominal == 0:
                print("Warning: Nominal value of base variable is 0. Setting \
                                nominal for slack variable to 1.")
                slack.setNominal(1)
            else:
                slack.setNominal(0.0001 * N.abs(nominal))

            self.op.addVariable(slack)

            # Add to Objective Integrand
            oi = self.op.getObjectiveIntegrand()
            self.op.setObjectiveIntegrand(oi+\
                                        self.constr_viol_costs[name]*slack_var)

            # Obtain the bounds
            var_min = self.op.get_attr(var, "min")
            var_max = self.op.get_attr(var, "max")

            # Add constraints and change bounds
            if var_min != -N.inf:
                var.setMin(-N.inf)
                pac_rh = var_min - slack_var
                pac_soft = ci.Constraint(var.getVar(), pac_rh, 2)
                path_constr.append(pac_soft)
            if var_max != N.inf:
                var.setMax(N.inf)
                pac_rh = var_max + slack_var
                pac_soft = ci.Constraint(var.getVar(), pac_rh, 1)
                path_constr.append(pac_soft)

        self.op.setPathConstraints(path_constr)
Exemplo n.º 6
0
    def _add_u0(self):
        """
        Adds neccessary variables to make blocking factors (du_quad_pen and 
        du_bounds) valid first sample.
        """
        bf = self.options['blocking_factors']
        if bf is not None:
            for key in list(bf.du_quad_pen.keys()):
                var_par = casadi.MX.sym("%s_0" % key)
                var = ci.RealVariable(self.op, var_par, 2, 1)
                self.op.addVariable(var)
                self.op.set("%s_0" % key, 0)
                self.extra_param.append("%s_0" % key)

                # Find or create new timed variable
                var_startTime = self._getTimedVariable(key)

                if var_startTime is None:
                    var_startTime = casadi.MX.sym("%s(startTime)" % key)
                    st = self.op.getVariable('startTime').getVar()
                    variable = self.op.getVariable(key)
                    timedVar_startTime = ci.TimedVariable(
                        self.op, var_startTime, variable, st)
                    self.op.addTimedVariable(timedVar_startTime)

                # Create new variable
                du_quad_pen_par = casadi.MX.sym("%s_du_quad_pen" % key)
                du_quad_pen = ci.RealVariable(self.op, du_quad_pen_par, 2, 1)
                self.op.addVariable(du_quad_pen)
                self.op.set("%s_du_quad_pen" % key, 0)
                self.extra_param.append("%s_du_quad_pen" % key)

                extra_obj = du_quad_pen_par*(var_startTime-var_par)*\
                                                        (var_startTime-var_par)
                self.op.setObjective(self.op.getObjective() + extra_obj)

            # Save all pointconstraints
            pc = []
            for constr in self.op.getPointConstraints():
                pc.append(constr)

            for key in list(bf.du_bounds.keys()):
                # Find or create new _0 parameter
                var_par = self.op.getVariable("%s_0" % key)
                if var_par is None:
                    var_par = casadi.MX.sym("%s_0" % key)
                    var = ci.RealVariable(self.op, var_par, 2, 1)
                    self.op.addVariable(var)
                    self.op.set("%s_0" % key, 0)
                    self.extra_param.append("%s_0" % key)
                else:
                    var_par = var_par.getVar()

                # Find or create new timed variable
                var_startTime = self._getTimedVariable(key)

                if var_startTime is None:
                    var_startTime = casadi.MX.sym("%s(startTime)" % key)
                    st = self.op.getVariable('startTime').getVar()
                    variable = self.op.getVariable(key)
                    timedVar_startTime = ci.TimedVariable(
                        self.op, var_startTime, variable, st)
                    self.op.addTimedVariable(timedVar_startTime)

                # Create new parameter for pointconstraint bound
                du_bounds_par = casadi.MX.sym("%s_du_bounds" % key)
                du_bounds = ci.RealVariable(self.op, du_bounds_par, 2, 1)
                self.op.addVariable(du_bounds)
                self.op.set("%s_du_bounds" % key, 1e10)
                self.extra_param.append("%s_du_bounds" % key)

                # Create new pointconstraints
                bf_constr = var_startTime - var_par
                poc1 = ci.Constraint(bf_constr, du_bounds_par, 1)
                poc2 = ci.Constraint(bf_constr, -du_bounds_par, 2)

                # Append new pointconstraints to list
                pc.append(poc1)
                pc.append(poc2)

            # Set new pointconstraints
            self.op.setPointConstraints(pc)
Exemplo n.º 7
0
    def augment_sensitivities(self, parameters):
        """
        Adds forward sensitivity variables and equations for all model variables with respect to given parameters.

        Parameters::

            parameters --
                List of parameter names for which to compute sensitivities.
        """
        ###################################################################
        ###           This code does not exploit DAE sparsity!          ###
        ### Although this will probably not affect online computations. ###
        ###################################################################

        # Get residuals and variables
        dae = self.getDaeResidual()
        init = self.getInitialResidual()
        var_kinds = {'dx': self.DERIVATIVE,
                     'x': self.DIFFERENTIATED,
                     'w': self.REAL_ALGEBRAIC}
        mvar_vectors = {'dx': N.array([var for var in self.getVariables(var_kinds['dx'])
                                       if (not var.isAlias() and not var.wasEliminated())]),
                        'x': N.array([var for var in self.getVariables(var_kinds['x'])
                                      if (not var.isAlias() and not var.wasEliminated())]),
                        'w': N.array([var for var in self.getVariables(var_kinds['w'])
                                      if (not var.isAlias() and not var.wasEliminated())])}
        mvar_par = N.array([self.getVariable(par) for par in parameters])

        # Add sensitivity variables
        for par in mvar_par:
            par_var = par.getVar()
            for mvar in mvar_vectors['x']:
                # States
                mvar_var = mvar.getVar()
                name = "d%s/d%s" % (mvar.getName(), par.getName())
                sens_var = casadi.MX.sym(name)
                sens = ci.RealVariable(self, sens_var, ci.RealVariable.INTERNAL, ci.RealVariable.CONTINUOUS)
                self.addVariable(sens)

                # State derivatives
                dx_mvar = mvar.getMyDerivativeVariable()
                dx_mvar_var = dx_mvar.getVar()
                dx_name = "der(d%s/d%s)" % (mvar.getName(), par.getName())
                dx_sens_var = casadi.MX.sym(dx_name)
                dx_sens = ci.DerivativeVariable(self, dx_sens_var, sens)
                self.addVariable(dx_sens)
            for mvar in mvar_vectors['w']:
                # Algebraics
                mvar_var = mvar.getVar()
                name = "d%s/d%s" % (mvar.getName(), par.getName())
                sens_var = casadi.MX.sym(name)
                sens = ci.RealVariable(self, sens_var, ci.RealVariable.INTERNAL, ci.RealVariable.CONTINUOUS)
                self.addVariable(sens)

        # Compute derivatives
        dfdx = {}
        df0dx = {}
        for vk in var_kinds:
            dfdx[vk] = {}
            df0dx[vk] = {}
            for mvar in mvar_vectors[vk]:
                mvar_var = mvar.getVar()
                dfdx[vk][mvar.getName()] = N.array([casadi.jacobian(dae_eq, mvar_var) for dae_eq in dae])
                df0dx[vk][mvar.getName()] = N.array([casadi.jacobian(init_eq, mvar_var) for init_eq in init])
        
        # Add sensitivity differential equations
        mx_zero = casadi.MX(0.)
        for par in mvar_par:
            for i in xrange(dae.numel()):
                eq = mx_zero
                for vk in var_kinds:
                    for mvar in mvar_vectors[vk]:
                        if vk == "dx":
                            name = "der(d%s/d%s)" % (mvar.getMyDifferentiatedVariable().getName(), par.getName())
                        else:
                            name = "d%s/d%s" % (mvar.getName(), par.getName())
                        sens_var = self.getVariable(name).getVar()
                        eq += dfdx[vk][mvar.getName()][i] * sens_var
                eq += casadi.jacobian(dae[i], par.getVar())
                sens_eq = ci.Equation(eq, mx_zero)
                self.addDaeEquation(sens_eq)

        # Add sensitivity initial equations
        for par in mvar_par:
            for i in xrange(init.numel()):
                init_eq = mx_zero
                for vk in var_kinds:
                    for mvar in mvar_vectors[vk]:
                        if vk == "dx":
                            name = "der(d%s/d%s)" % (mvar.getMyDifferentiatedVariable().getName(), par.getName())
                        else:
                            name = "d%s/d%s" % (mvar.getName(), par.getName())
                        sens_var = self.getVariable(name).getVar()
                        init_eq += df0dx[vk][mvar.getName()][i] * sens_var
                init_eq += casadi.jacobian(init[i], par.getVar())
                sens_init_eq = ci.Equation(init_eq, mx_zero)
                self.addInitialEquation(sens_init_eq)