コード例 #1
0
    def solve_problem(self, target_variable, maximize=False):
        """
        Solve the linear programming problem
        """
        target_column = self.var_corr[target_variable]

        c = [0.0] * self.variable_count
        if maximize:
            c[target_column] = -1.0
        else:
            c[target_column] = 1.0
        sol = lp_solver.apply(c,
                              self.Aub,
                              self.bub,
                              self.Aeq,
                              self.beq,
                              variant=DEFAULT_LP_SOLVER_VARIANT)
        parameters_points = {
            "maximize": maximize,
            "return_when_none": True,
            "var_corr": self.var_corr
        }

        return lp_solver.get_points_from_sol(sol,
                                             parameters=parameters_points,
                                             variant=DEFAULT_LP_SOLVER_VARIANT)
コード例 #2
0
def __compute_exact_heuristic_new_version(sync_net, a_matrix, h_cvx, g_matrix, cost_vec, incidence_matrix,
                                          marking, fin_vec, variant, use_cvxopt=False, strict=True):
    m_vec = incidence_matrix.encode_marking(marking)
    b_term = [i - j for i, j in zip(fin_vec, m_vec)]
    b_term = np.matrix([x * 1.0 for x in b_term]).transpose()

    if not strict:
        g_matrix = np.vstack([g_matrix, a_matrix])
        h_cvx = np.vstack([h_cvx, b_term])
        a_matrix = np.zeros((0, a_matrix.shape[1]))
        b_term = np.zeros((0, b_term.shape[1]))

    if use_cvxopt:
        # not available in the latest version of PM4Py
        from cvxopt import matrix

        b_term = matrix(b_term)

    parameters_solving = {"solver": "glpk"}

    sol = lp_solver.apply(cost_vec, g_matrix, h_cvx, a_matrix, b_term, parameters=parameters_solving,
                          variant=variant)
    prim_obj = lp_solver.get_prim_obj_from_sol(sol, variant=variant)
    points = lp_solver.get_points_from_sol(sol, variant=variant)

    prim_obj = prim_obj if prim_obj is not None else sys.maxsize
    points = points if points is not None else [0.0] * len(sync_net.transitions)

    return prim_obj, points
コード例 #3
0
ファイル: classic.py プロジェクト: kfly89/pm4py-core
    def solve(self, variant=None) -> Tuple[int, List[int]]:
        """
        Solves the extended marking equation, returning the heuristics and the x vector

        Parameters
        -------------
        variant
            Variant of the ILP solver to use

        Returns
        -------------
        h
            Heuristics value
        x
            X vector
        """
        if variant is None:
            variant = solver.DEFAULT_LP_SOLVER_VARIANT
        # use ILP solver
        if variant is solver.CVXOPT_SOLVER_CUSTOM_ALIGN:
            variant = solver.CVXOPT_SOLVER_CUSTOM_ALIGN_ILP
        c, Aub, bub, Aeq, beq = self.get_components()
        parameters_solver = {}
        parameters_solver["use_ilp"] = True
        sol = solver.apply(c, Aub, bub, Aeq, beq, variant=variant, parameters=parameters_solver)
        sol_points = solver.get_points_from_sol(sol, variant=variant)
        if sol_points is not None:
            x = self.get_x_vector(sol_points)
            x = [int(y) for y in x]
            h = self.get_h(sol_points)
            return h, x
        return None, None
コード例 #4
0
ファイル: matrix_lp.py プロジェクト: hieule23/pm4py-core
def __ilp_solve(c, Aub, bub, Aeq, beq):
    Aeq = np.asmatrix(Aeq).astype(np.float64)
    beq = np.asmatrix(beq).transpose().astype(np.float64)
    Aub = np.asmatrix(Aub).astype(np.float64)
    bub = np.asmatrix(bub).transpose().astype(np.float64)

    if "cvxopt" in solver.DEFAULT_LP_SOLVER_VARIANT:
        # does this part only if cvxopt is imported
        from cvxopt import matrix
        c = matrix([x * 1.0 for x in c])
        Aeq = matrix(Aeq)
        beq = matrix(beq)
        Aub = matrix(Aub)
        bub = matrix(bub)

        # tries to solve the problem with LP solving
        # (faster)
        # if it produces a vector which elements are different from 0 or 1
        # then use the ILP solver
        sol = solver.apply(c, Aub, bub, Aeq, beq, variant="cvxopt_solver_custom_align")
        points = solver.get_points_from_sol(sol, variant="cvxopt_solver_custom_align")
        condition_points = True
        for x in points:
            if x > TOL or x < 1 - TOL:
                continue
            condition_points = False
            break
        # there is at least one point in the solution that is not integer.
        # in that case, it is better to apply the ILP solver instead of just rounding the points
        if condition_points is False:
            sol = solver.apply(c, Aub, bub, Aeq, beq, variant="cvxopt_solver_custom_align_ilp")
            points = solver.get_points_from_sol(sol, variant="cvxopt_solver_custom_align_ilp")
        # round the points to the nearest integer (0 or 1).
        # if the ILP solver is called, these are already integer
        points = [round(x) for x in points]
    else:
        # calls other linear solvers (pulp, ortools) with REQUIRE_ILP set to True
        sol = solver.apply(c, Aub, bub, Aeq, beq, variant=solver.DEFAULT_LP_SOLVER_VARIANT,
                           parameters={solver.Parameters.REQUIRE_ILP: True})
        points = solver.get_points_from_sol(sol, variant=solver.DEFAULT_LP_SOLVER_VARIANT)

    return points
コード例 #5
0
    def solve_given_components(self, c, Aub, bub, Aeq, beq):
        """
        Solves the linear problem given the components

        Parameters
        --------------
        c
            Objective vector
        Aub
            Inequalities matrix
        bub
            Inequalities vector
        Aeq
            Equalities matrix
        beq
            Equalities vector

        Returns
        -------------
        h
            Heuristics value
        x
            X vector
        """
        if solver.DEFAULT_LP_SOLVER_VARIANT == solver.CVXOPT_SOLVER_CUSTOM_ALIGN and type(
                c) is list:
            from cvxopt import matrix
            Aub = matrix(Aub.astype(np.float64))
            bub = matrix(bub.astype(np.float64))
            Aeq = matrix(Aeq.astype(np.float64))
            beq = matrix(beq.astype(np.float64))
            c = matrix([1.0 * x for x in c])
        sol = solver.apply(c,
                           Aub,
                           bub,
                           Aeq,
                           beq,
                           variant=solver.DEFAULT_LP_SOLVER_VARIANT)
        sol_points = solver.get_points_from_sol(
            sol, variant=solver.DEFAULT_LP_SOLVER_VARIANT)
        if sol_points is not None:
            x = self.get_x_vector(sol_points)
            x = [int(y) for y in x]
            h = self.get_h(sol_points)
            return h, x
        return None, None
コード例 #6
0
def resolve_LP(C_matrix, duration_matrix, activities, activities_counter):
    """
    Formulates and solve the LP problem

    Parameters
    --------------
    C_matrix
        C_matrix
    duration_matrix
        Duration matrix
    activities
        Ordered list of activities of the log
    activities_counter
        Counter of activities

    Returns
    -------------
    dfg
        Directly-Follows Graph
    performance_dfg
        Performance DFG (containing the estimated performance for the arcs)
    """
    edges = [(i, j) for i in range(len(activities))
             for j in range(len(activities))]
    c = [
        C_matrix[i, j] for i in range(len(activities))
        for j in range(len(activities))
    ]
    edges_sources = {
        i: [z for z in range(len(edges)) if edges[z][0] == i]
        for i in range(len(activities))
    }
    edges_targets = {
        j: [z for z in range(len(edges)) if edges[z][1] == j]
        for j in range(len(activities))
    }
    activities_occurrences = {
        i: activities_counter[activities[i]]
        for i in range(len(activities))
    }
    Aeq = []
    beq = []
    for i in range(len(activities)):
        rec = [0] * len(edges)
        for e in edges_sources[i]:
            rec[e] = 1
        Aeq.append(rec)
        beq.append(activities_occurrences[i])
    for j in range(len(activities)):
        rec = [0] * len(edges)
        for e in edges_targets[j]:
            rec[e] = 1
        Aeq.append(rec)
        beq.append(activities_occurrences[j])
    Aeq = np.asmatrix(Aeq).astype(np.float64)
    beq = np.asmatrix(beq).transpose().astype(np.float64)
    Aub = []
    bub = []
    for i in range(len(activities)):
        for e in edges_sources[i]:
            rec = [0] * len(edges)
            rec[e] = 1
            Aub.append(rec)
            bub.append(activities_occurrences[i])
            rec = [-x for x in rec]
            Aub.append(rec)
            bub.append(0)
    for j in range(len(activities)):
        for e in edges_targets[j]:
            rec = [0] * len(edges)
            rec[e] = 1
            Aub.append(rec)
            bub.append(activities_occurrences[j])
            rec = [-x for x in rec]
            Aub.append(rec)
            bub.append(0)
    Aub = np.asmatrix(Aub).astype(np.float64)
    bub = np.asmatrix(bub).transpose().astype(np.float64)

    use_cvxopt = False
    if solver.DEFAULT_LP_SOLVER_VARIANT == solver.CVXOPT_SOLVER_CUSTOM_ALIGN or solver.DEFAULT_LP_SOLVER_VARIANT == solver.CVXOPT_SOLVER_CUSTOM_ALIGN_ILP:
        use_cvxopt = True

    if use_cvxopt:
        from cvxopt import matrix

        c = matrix(c)
        Aub = matrix(Aub)
        bub = matrix(bub)
        Aeq = matrix(Aeq)
        beq = matrix(beq)

    res = solver.apply(c,
                       Aub,
                       bub,
                       Aeq,
                       beq,
                       variant=solver.DEFAULT_LP_SOLVER_VARIANT)
    points = solver.get_points_from_sol(
        res, variant=solver.DEFAULT_LP_SOLVER_VARIANT)
    points = [round(p) for p in points]

    dfg = {}
    performance_dfg = {}

    for idx, p in enumerate(points):
        if p > 0:
            dfg[(activities[edges[idx][0]], activities[edges[idx][1]])] = p
            performance_dfg[(
                activities[edges[idx][0]],
                activities[edges[idx][1]])] = duration_matrix[edges[idx][0],
                                                              edges[idx][1]]
    return dfg, performance_dfg
コード例 #7
0
ファイル: utility.py プロジェクト: pm4py/pm4py-core
def transform_basis(basis, style=None):
    """
    We construct a (I)LP to transform our basis into a set of vectors by using linear combination to fit certain styles/
    properties
    :param basis: list of p-invariants. Commonly computed by the method 'compute_place_invariants' in
    place_invariants.py
    :param style: String that is used to construct certain constraints
    At the moment, 'uniform' (all weights have value 0 or 1), and 'weighted' (all weights are >=0) are supported
    :return: List of p-invariants that fits the style
    """
    if style == None:
        style = 'weighted'

    # First, we want to check if a vector of a basis only contains non-positve entries. If so, then we multiply the
    # vector -1.
    modified_base = []
    for vector in basis:
        all_non_positiv = True
        for entry in vector:
            if entry > 0:
                all_non_positiv = False
        if all_non_positiv:
            modified_base.append(-1 * vector)
        else:
            modified_base.append(vector)
    #For uniform variants, it is necessary that the weight for a place is either 0 or 1. We collect the variants for
    #which this condition does not hold. We also collect the variants for the weighted invariants the entry is <0.
    to_modify = []
    for vector in modified_base:
        for entry in vector:
            if ((entry < 0 or entry > 1)
                    and style == 'uniform') or (entry < 0
                                                and style == 'weighted'):
                to_modify.append(vector)
                break
    # if we have nothing to modify, we are done
    if len(to_modify) > 0:
        for vector in to_modify:
            removearray(modified_base, vector)
            set_B = range(0, len(modified_base))
            # start of the problem
            """prob = pulp.LpProblem("linear_combination", pulp.LpMinimize)
            X = pulp.LpVariable.dicts("x", set_B, cat='Integer')
            y = pulp.LpVariable("y", cat='Integer', lowBound=1)
            # add objective
            prob += pulp.lpSum(X[i] for i in set_B)
            if style=='uniform':
                # variables for uniform. Therefore, the resulting weight can either be 0 or 1
                z = pulp.LpVariable.dicts("z", range(0, len(vector)), lowBound=0, upBound=1, cat='Integer')
                # add constraints
                for i in range(len(vector)):
                    prob += pulp.lpSum(X[j]*modified_base[j][i] for j in range(len(modified_base)))+y*vector[i]== z[i]
            elif style=='weighted':
                for i in range(len(vector)):
                    prob += pulp.lpSum(X[j]*modified_base[j][i] for j in range(len(modified_base)))+y*vector[i] >= 0
            prob.solve()"""
            # problem is solved

            c = [1] * len(set_B) + [0] * (len(vector) + 1)
            zeros = [0] * (len(set_B) + len(vector) + 1)
            Aub = []
            bub = []
            Aeq = []
            beq = []
            first_constraint = copy(zeros)
            first_constraint[len(set_B)] = -1
            Aub.append(first_constraint)
            bub.append(-1)
            for i in range(len(vector)):
                this_row = copy(zeros)
                this_row[len(set_B)] = list(vector[i])[0]
                for j in range(len(modified_base)):
                    if type(modified_base[j][i]) is np.float64:
                        this_row[j] = float(modified_base[j][i])
                    else:
                        this_row[j] = list(modified_base[j][i])[0]

                    if style == "uniform":
                        this_row[len(set_B) + 1 + i] = -1
                        Aeq.append(this_row)
                        beq.append(0)
                    elif style == "weighted":
                        Aub.append([-x for x in this_row])
                        bub.append(0)
            for i in range(len(vector)):
                last_constraint_1 = copy(zeros)
                last_constraint_1[len(set_B) + 1 + i] = 1
                Aub.append(last_constraint_1)
                bub.append(1)
                last_constraint_2 = copy(zeros)
                last_constraint_2[len(set_B) + 1 + i] = -1
                Aub.append(last_constraint_2)
                bub.append(0)

            Aeq = np.asmatrix(Aeq).astype(np.float64)
            beq = np.asmatrix(beq).transpose().astype(np.float64)
            Aub = np.asmatrix(Aub).astype(np.float64)
            bub = np.asmatrix(bub).transpose().astype(np.float64)

            if Aeq.shape[1] == 0:
                Aeq = np.zeros((1, len(c))).astype(np.float64)
                beq = np.zeros(1).transpose().astype(np.float64)

            if Aub.shape[1] == 0:
                Aub = np.zeros((1, len(c))).astype(np.float64)
                bub = np.zeros(1).transpose().astype(np.float64)

            if "cvxopt" in solver.DEFAULT_LP_SOLVER_VARIANT:
                from cvxopt import matrix
                c = matrix([x * 1.0 for x in c])
                Aeq = matrix(Aeq)
                beq = matrix(beq)
                Aub = matrix(Aub)
                bub = matrix(bub)

            sol = solver.apply(c,
                               Aub,
                               bub,
                               Aeq,
                               beq,
                               variant=solver.DEFAULT_LP_SOLVER_VARIANT)
            points = solver.get_points_from_sol(
                sol, variant=solver.DEFAULT_LP_SOLVER_VARIANT)

            new_vector = np.zeros(len(vector))

            if style == "weighted":
                for i in range(len(new_vector)):
                    new_vector[i] = points[len(set_B)] * vector[i]
                    for j in range(len(modified_base)):
                        new_vector[i] = new_vector[
                            i] + modified_base[j][i] * points[j]
            elif style == "uniform":
                for i in range(len(new_vector)):
                    new_vector[i] = points[len(set_B) + 1 + i]
            modified_base.append(new_vector)

    return modified_base