예제 #1
0
 def buildSolverModel(self, lp):
     """
     Takes the pulp lp model and translates it into a glpk model
     """
     log.debug("create the glpk model")
     prob = glpk.glp_create_prob()
     glpk.glp_set_prob_name(prob, lp.name)
     log.debug("set the sense of the problem")
     if lp.sense == constants.LpMaximize:
         glpk.glp_set_obj_dir(prob, glpk.GLP_MAX)
     log.debug("add the constraints to the problem")
     glpk.glp_add_rows(prob, len(list(lp.constraints.keys())))
     for i, v in enumerate(lp.constraints.items(), start=1):
         name, constraint = v
         glpk.glp_set_row_name(prob, i, name)
         if constraint.sense == constants.LpConstraintLE:
             glpk.glp_set_row_bnds(prob, i, glpk.GLP_UP, 0.0,
                                   -constraint.constant)
         elif constraint.sense == constants.LpConstraintGE:
             glpk.glp_set_row_bnds(prob, i, glpk.GLP_LO,
                                   -constraint.constant, 0.0)
         elif constraint.sense == constants.LpConstraintEQ:
             glpk.glp_set_row_bnds(prob, i, glpk.GLP_FX,
                                   -constraint.constant,
                                   -constraint.constant)
         else:
             raise PulpSolverError(
                 'Detected an invalid constraint type')
         constraint.glpk_index = i
     log.debug("add the variables to the problem")
     glpk.glp_add_cols(prob, len(lp.variables()))
     for j, var in enumerate(lp.variables(), start=1):
         glpk.glp_set_col_name(prob, j, var.name)
         lb = 0.0
         ub = 0.0
         t = glpk.GLP_FR
         if not var.lowBound is None:
             lb = var.lowBound
             t = glpk.GLP_LO
         if not var.upBound is None:
             ub = var.upBound
             t = glpk.GLP_UP
         if not var.upBound is None and not var.lowBound is None:
             if ub == lb:
                 t = glpk.GLP_FX
             else:
                 t = glpk.GLP_DB
         glpk.glp_set_col_bnds(prob, j, t, lb, ub)
         if var.cat == constants.LpInteger:
             glpk.glp_set_col_kind(prob, j, glpk.GLP_IV)
             assert glpk.glp_get_col_kind(prob, j) == glpk.GLP_IV
         var.glpk_index = j
     log.debug("set the objective function")
     for var in lp.variables():
         value = lp.objective.get(var)
         if value:
             glpk.glp_set_obj_coef(prob, var.glpk_index, value)
     log.debug("set the problem matrix")
     for constraint in lp.constraints.values():
         l = len(list(constraint.items()))
         ind = glpk.intArray(l + 1)
         val = glpk.doubleArray(l + 1)
         for j, v in enumerate(constraint.items(), start=1):
             var, value = v
             ind[j] = var.glpk_index
             val[j] = value
         glpk.glp_set_mat_row(prob, constraint.glpk_index, l, ind, val)
     lp.solverModel = prob
예제 #2
0
    def create_problem(self, data):

        hosts_attacked = data["attacked"]
        hosts_executing = data["executing"]
        metrics = data["metric"]
        damage = data["damage"]
        responses = data["response"]

        logging.info("CSR Optimizer creating problem...")
        glpki.glp_init_env()
        problem = glpki.glp_create_prob()
        glpki.glp_set_prob_name(problem, "CSR")

        # Set optimization direction to minimize
        glpki.glp_set_obj_dir(problem, glpki.GLP_MIN)

        # Column C_m_i :Create a column for every property
        logging.debug("Adding %s columns for metrics", len(metrics))
        first = glpki.glp_add_cols(problem, len(metrics))
        for m in metrics:
            logging.debug("Adding column [%s] for metric '%s'", first, m.name)
            m.column = first
            glpki.glp_set_col_name(problem, m.column, "C_m_" + str(m.name))
            glpki.glp_set_col_bnds(problem, m.column, glpki.GLP_LO, 0, 0)
            glpki.glp_set_col_kind(problem, m.column, glpki.GLP_CV)
            glpki.glp_set_obj_coef(problem, m.column, 1.0)
            first += 1

        # Column C_m_i : Create a column for every response
        first = glpki.glp_add_cols(problem, len(responses))
        for r in responses:
            logging.debug("Adding column [%s] for response '%s'", first,
                          r.name)
            r.column = first
            glpki.glp_set_col_name(problem, r.column, "C_n_" + str(r.name))
            glpki.glp_set_col_bnds(problem, r.column, glpki.GLP_DB, 0, 1)
            glpki.glp_set_col_kind(problem, r.column, glpki.GLP_IV)
            glpki.glp_set_obj_coef(problem, r.column, 0)
            first += 1
        # Row: C1) Every victim is freed: Create a constrain row for every attacked host
        logging.debug("Adding %s row for attacked hosts", len(hosts_attacked))
        first = glpki.glp_add_rows(problem, len(hosts_attacked))
        for a in hosts_attacked:
            logging.debug("Adding constraint [%s] for attacked host '%s'",
                          first, a.name)
            a.row_freed = first
            # set row name
            glpki.glp_set_row_name(problem, a.row_freed, a.name + "_freed")
            # set row bounds:
            glpki.glp_set_row_bnds(problem, a.row_freed, glpki.GLP_LO, 1, 0)
            first += 1

        # Row: C2) Sum of costs is lower than damage: Create a constrain row for every property
        if (None != damage):
            logging.debug("Adding damage row %s row for metrics", len(metrics))
            first = glpki.glp_add_rows(problem, len(metrics))
            for m in metrics:
                logging.debug("Adding damage constraint [%s] for metric '%s'",
                              first, m.name)
                m.row_damage = first
                # set row name
                glpki.glp_set_row_name(problem, m.row_damage,
                                       m.name + "_damage")
                # set row bounds:
                cur_damage = -1
                for d in damage:
                    if (d.name == m.name):
                        cur_damage = d.value
                assert (-1 != cur_damage)
                glpki.glp_set_row_bnds(problem, m.row_damage, glpki.GLP_UP, 0,
                                       cur_damage)
                first += 1

        # Row C3) Cost of each metric: Create a row for every property
        logging.debug("Adding %s row for metrics", len(metrics))
        first = glpki.glp_add_rows(problem, len(metrics))
        for m in metrics:
            logging.debug("Adding constraint [%s] for metric '%s'", first,
                          m.name)
            m.row_cost = first
            # set row name
            glpki.glp_set_row_name(problem, m.row_cost, m.name + "_cost")
            # set row bounds:
            glpki.glp_set_row_bnds(problem, m.row_cost, glpki.GLP_FX, 0, 0)
            first += 1

        # Set problem matrix content
        c_conflicts = 0
        for r in responses:
            for c in r.conflicting_responses:
                if (c == ""):
                    continue
                c_conflicts += 1
        c_freed = 0
        for a in hosts_attacked:
            for r in responses:
                if (a.name == r.dest or r.dest.count(a.name) != 0):
                    c_freed += 1
        array_size = 1 + c_freed + 2 * len(metrics) * len(responses) + len(
            metrics) + 2 * c_conflicts
        ia = glpki.intArray(array_size)
        ja = glpki.intArray(array_size)
        ar = glpki.doubleArray(array_size)
        index = 1
        count = 0

        # Conflicting responses
        ConflictingContraints = 0
        for r in responses:
            for c in r.conflicting_responses:
                if (c == ""):
                    continue
                r2 = None
                for r_tmp in responses:
                    if (c == r_tmp.name):
                        r2 = r_tmp

                if (None == r2) or (r.name == r2.name):
                    continue
                # Add a constraint for every conflict
                ConflictingContraints = ConflictingContraints + 1
                logging.debug(
                    "Adding constraint [%s] for conflict '%s' <-> '%s'", first,
                    r.name, c)
                first = glpki.glp_add_rows(problem, 1)
                glpki.glp_set_row_name(problem, first,
                                       "conflict_" + r.name + "-" + r2.name)
                glpki.glp_set_row_bnds(problem, first, glpki.GLP_DB, 0, 1)

                ia[index] = first
                ja[index] = r.column
                ar[index] = 1
                logging.debug("%s: [%s][%s] = %s", count, ia[index], ja[index],
                              ar[index])
                index += 1
                count += 1
                ia[index] = first
                ja[index] = r2.column
                ar[index] = 1
                logging.debug("%s: [%s][%s] = %s", count, ia[index], ja[index],
                              ar[index])
                index += 1
                count += 1

        # Constraint 1) Every attacked not has to be freed
        for a in hosts_attacked:
            logging.debug("1) Free %s", a.name)
            for r in responses:
                if (a.name == r.dest or r.dest.count(a.name) != 0):
                    ia[index] = a.row_freed
                    ja[index] = r.column
                    ar[index] = 1.0
                    logging.debug("%s: [%s][%s] = %s", count, ia[index],
                                  ja[index], ar[index])
                    index += 1
                    count += 1
        # Constraint 2) damage
        if (None != damage):
            for m in metrics:
                logging.debug("2) Damage for metric %s", m.name)
                for r in responses:
                    ia[index] = m.row_damage
                    ja[index] = r.column
                    ar[index] = r.get_cost(m.name)
                    logging.debug("%s: [%s][%s] = %s", count, ia[index],
                                  ja[index], ar[index])
                    index += 1
                    count += 1

        # Constraint 3) cost
        for m in metrics:
            logging.debug("3) Cost for metric %s", m.name)
            ia[index] = m.row_cost
            ja[index] = m.column
            ar[index] = 1
            logging.debug("H: %s [%s][%s] = %s", count, ia[index], ja[index],
                          ar[index])
            index += 1
            count += 1
            for r in responses:
                ia[index] = m.row_cost
                ja[index] = r.column
                ar[index] = -r.get_cost(m.name)
                logging.debug("%s: [%s][%s] = %s", count, ia[index], ja[index],
                              ar[index])
                index += 1
                count += 1

        glpki.glp_load_matrix(problem, count, ia, ja, ar)

        return problem