python代码实现Bottleneck Generalized Assignment Problems

Bottleneck Generalized Assignment Problems

参考文献:Mazzola J B, Neebe A W. Bottleneck generalized assignment problems[J]. Engineering Costs and Production Economics, 1988, 14(1): 61-65.

实现的总体思路:

1初始化相关的输入数据
2 根据cij与ck的关系建立新的TGBAP(K)问题
3 找到Z的下限,从这个下限开始往更大的数方向寻找
4 TGBAP(K)是否存在可行解,如果不存在的话,继续往下个数找,直到找到一个可行的TGBAP(K)
5 输出这个可行方案和对应的最小最大时间

上代码

详细的数据集见github地址https://github.com/yasuoman/BGAP

# project : BGAP
# file   : TBGAP.py
# author:yasuoman
# datetime:2024/3/27 11:31
# software: PyCharm

"""
description:
说明:
"""
# 参考的文献Mazzola J B, Neebe A W. Bottleneck generalized assignment problems[J].
# Engineering Costs and Production Economics, 1988, 14(1): 61-65.
#且实现的是TBGAP

# 实现的总体思路:
# 1初始化相关的输入数据
# 2 根据cij与ck的关系建立新的TGBAP(K)问题
# 3 找到Z的下限,从这个下限开始往更大的数方向寻找
# 4 TGBAP(K)是否存在可行解,如果不存在的话,继续往下个数找,直到找到一个可行的TGBAP(K)
# 5 输出这个可行方案和对应的最小最大时间
import numpy as np

#这里是相关的数据集,输出相关的数据和变量
def construct_dataset():
    m, n = 5, 10
    # 运行成本矩阵
    cost_matrix = np.array(
        [[36,102,35,31,18,25,30,76,108,82],
         [61,75,69,19,45,97,117,74,35,85],
         [34,79,26,114,27,44,25,76,93,89],
         [17,97,65,51,81,82,89,40,21,95],
         [70,7,74,79,74,44,52,94,107,108]])
    #
    # cost_matrix = np.array(
    #     [[36, 102, 35, 31, 18, 25, 30, 76, 108, 65],
    #      [61, 75, 69, 19, 45, 97, 117, 74, 35, 85],
    #      [34, 79, 26, 114, 27, 44, 25, 76, 93, 76],
    #      [17, 97, 69, 51, 81, 82, 89, 40, 21, 95],
    #      [70, 7, 74, 79, 74, 44, 52, 94, 107, 108]])
    # 资源需求矩阵
    resource_matrix = np.array(
        [[78,14,82,70,87,93,78,34,7,36],
        [59,28,40,89,69,21,3,32,70,33],
        [72,40,95,6,85,60,94,25,9,29],
        [96,16,34,57,39,29,20,62,95,16],
        [39,98,33,24,45,61,59,7,12,12]])

    # resource_matrix = np.array(
    #     [[78, 14, 82, 70, 87, 93, 78, 34, 7, 36],
    #      [59, 28, 40, 89, 69, 21, 3, 32, 70, 33],
    #      [72, 40, 95, 6, 85, 60, 94, 25, 9, 29],
    #      [96, 16, 34, 57, 39, 29, 20, 62, 95, 16],
    #      [39, 98, 33, 24, 45, 61, 59, 7, 12, 12]])

    # 机器资源容量向量
    capacity_vector = np.array([93,71,82,74,62])

    return m,n,cost_matrix,resource_matrix,capacity_vector
#这里是对http://www.al.cm.is.nagoya-u.ac.jp/~yagiura/gap/ 的a20100数据集进行简单的测试
#目前没有优化这组数据集的读取,只是写了个示例。有需要可以自行写这里的代码
# def construct_dataset():
#     with open('Data/gap_a/a20100', 'r') as file:
#         #先随便写着
#         import re
#         # 读取文件内容
#         content = file.read()
#         # words = content.split(' ')
#         words= re.split(r'[ ,\n]+', content)
#
#         m,n = int(words[1]),int(words[2])
#         c_list = words[3:2003]
#         r_list = words[2003:4003]
#         cap_list = words[4003:4023]
#         c_int_list = [int(item) for item in c_list]
#         r_int_list = [int(item) for item in r_list]
#         cap_int_list = [int(item) for item in cap_list]
#         cost_matrix = np.array(c_int_list).reshape(m, n)
#         resource_matrix = np.array(r_int_list).reshape(m, n)
#         capacity_vector =np.array(cap_int_list)
#         return m, n, cost_matrix, resource_matrix, capacity_vector



#输入resource_matrix、cost_matrix、capacity_vector和初始的k,输出新的resource_matrix矩阵
def reconstruct_resource_matrix(resource_matrix, cost_matrix, capacity_vector,k):
    import copy
    copy_resource_matrix =copy.deepcopy(resource_matrix)
    # 使用fancy indexing来更新矩阵
    mask = k < cost_matrix
    # resource_matrix[mask] = 9999
    copy_resource_matrix[mask] = max(capacity_vector)
    return copy_resource_matrix

#输入新的resource_matrix矩阵和capacity_vector,输出一组可行解或输出FALSE,借用Pulp包求解
def find_soulution(resource_matrix,capacity_vector,m,n):
    import pulp
    # 创建问题实例
    prob = pulp.LpProblem("Machine_Assignment", pulp.LpMinimize)
    # 二元决策变量
    x = pulp.LpVariable.dicts("x", ((i, j) for i in range(m) for j in range(n)),
                              cat=pulp.LpBinary)
    # 目标函数:这里我们只需要找到可行解,因此可以设置一个任意的目标函数
    prob += 0
    # 约束条件
    # 1每个工件只能在一个机器上运行
    for j in range(n):
        prob += sum(x[(i, j)] for i in range(m)) == 1

    # 2每个机器的资源需求之和不能大于资源容量
    for i in range(m):
        prob += sum(resource_matrix[i][j] * x[(i, j)] for j in range(n)) <= capacity_vector[i]
    # 求解问题
    # status = prob.solve()
    status = prob.solve(pulp.PULP_CBC_CMD(msg=False))

    # 输出结果
    if pulp.LpStatus[status] == 'Optimal':
        solution = [0] * n
        for i in range(m):
            for j in range(n):
                if pulp.value(x[(i, j)]) == 1:
                    solution[j] = i + 1  # 机器编号从1开始
        return solution
    else:
        # 无法找到可行解
        return False

def main():
    #得到数据
    m, n, cost_matrix, resource_matrix, capacity_vector = construct_dataset()
    # 构建待遍历的数组
    # 得到目标函数的下界 max min(cij), 找到每一列的最小值
    min_values = np.min(cost_matrix, axis=0)
    # 从最小值中找到最大值
    max_of_mins = np.max(min_values)
    #对矩阵进行排序并去重,得到一维数组ck
    ck= np.unique(np.sort(cost_matrix, axis=None))
    # 截取从下界开始到数组ck末尾的数据,保存到新的数组new_ck中
    new_ck = ck[ck >= max_of_mins]

    # object_value = new_ck[0]
    #遍历去找
    for i,k in np.ndenumerate(new_ck):
        new_resource_matrix =reconstruct_resource_matrix(resource_matrix, cost_matrix, capacity_vector, k)
        solution = find_soulution(new_resource_matrix,capacity_vector,m,n)

        if solution != False:
            print("第"+str(i)+"次,分配方案为:",solution,"最优运行时间为:",k)

            break
        else:
            print("第"+str(i)+"次,最优运行时间的分配方案"+str(k)+"不存在")


if __name__ == "__main__":
    main()


  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
JDA算法(Joint Distribution Adaptation)是一种域适应方法,它通过对源域数据和目标域数据分别建模,利用最大化它们之间的相似性来实现跨域知识转移。本文将介绍如何使用Python实现JDA算法。 首先,需要导入以下库:numpy,scipy,sklearn,和Cython。其中Cython是Python语言的扩展,主要用于编写C语言的扩展模块。 初始化函数中,我们需要指定两个域的标签、源域特征和目标域特征。在建模之前,需要计算出两个域的协方差矩阵。 然后,我们需要用高斯核函数来计算源域和目标域的核矩阵。接着,通过解决广义特征值问题来获取最大化领域间距离的变换矩阵,该矩阵可以将源域和目标域的特征转换成低维表示。 最后,在训练完变换矩阵后,我们可以将它应用于测试数据,以获得更好的分类效果。 下面是JDA算法Python代码实现: ``` import numpy as np from scipy import linalg from sklearn.metrics.pairwise import rbf_kernel from sklearn.base import BaseEstimator, TransformerMixin from sklearn.utils import check_array, check_random_state from scipy.spatial.distance import cdist from sklearn.decomposition import PCA from sklearn.linear_model import LogisticRegression try: from .jda_cython import inner_jda except ImportError: print('Cython not found. To compile cython .pyx file you need ' 'to run command "python setup.py build_ext --inplace" in' '"jda_cython" folder') from .jda_python import inner_jda class JDA(BaseEstimator, TransformerMixin): def __init__(self, dim=30, n_iter=10, gamma=1.0, kernel='rbf', random_state=None): self.dim = dim self.n_iter = n_iter self.gamma = gamma self.kernel = kernel self.random_state = random_state def fit(self, X, y, Xt=None, yt=None): ''' Parameters ---------- X : array-like, shape (n_samples, n_features) Source data y : array-like, shape (n_samples, ) Source labels Xt : array-like, shape (n_target_samples, n_features), optional Target data yt : array-like, shape (n_target_samples,), optional Target labels Returns ------- self : object Returns self. ''' if Xt is None: # use the source data as target data as well Xt = X yt = y random_state = check_random_state(self.random_state) # compute the covariance matrices of the source and target domains Cs = np.cov(X.T) Ct = np.cov(Xt.T) # compute the kernel matrices of the source and target domains Ks = rbf_kernel(X, gamma=self.gamma) Kt = rbf_kernel(Xt, X, gamma=self.gamma) self.scaler_ = PCA(n_components=self.dim).fit( np.vstack((X, Xt))) Xs_pca = self.scaler_.transform(X) Xt_pca = self.scaler_.transform(Xt) X_pca = np.vstack((Xs_pca, Xt_pca)) V_src = np.eye(Xs_pca.shape[1]) V_trg = np.eye(Xt_pca.shape[1]) for i in range(self.n_iter): W = JDA._calculate_projection( X_pca, np.array(source_labels+target_labels), V_src, V_trg, Ks, Kt) Xs_pca = Xs_pca.dot(W) Xt_pca = Xt_pca.dot(W) self.W_ = W self.Xs_pca_ = Xs_pca self.Xt_pca_ = Xt_pca self.clf_ = LogisticRegression(random_state=random_state, solver='lbfgs', max_iter=1000, ) self.clf_.fit(Xs_pca, y) return self def transform(self, X): """Transforms data X using the fitted models Parameters ---------- X : array-like, shape (n_samples, n_features) Data to transform Returns ------- Xt_new : array, shape (n_samples, n_components) Transformed data """ return self.scaler_.transform(X).dot(self.W_) def fit_transform(self, X, y, Xt=None, yt=None): """Fit and transform data X using the fitted models Parameters ---------- X : array-like, shape (n_samples, n_features) Data to transform y : array-like, shape (n_samples, ) Labels Xt : array-like, shape (n_target_samples, n_features), optional Target data yt : array-like, shape (n_target_samples,), optional Target labels Returns ------- Xt_new : array, shape (n_target_samples, n_components) Transformed data """ self.fit(X, y, Xt, yt) return self.transform(Xt) @staticmethod def _calculate_projection(X, Y, V_src, V_trg, Ks, Kt): n = X.shape[0] ns = Ks.shape[0] nt = Kt.shape[0] eps = 1e-4 H_s = np.eye(ns) - 1.0 / ns * np.ones((ns, ns)) H_t = np.eye(nt) - 1.0 / nt * np.ones((nt, nt)) A = np.vstack((np.hstack((Ks + eps * np.eye(ns), np.zeros((ns, nt)))), np.hstack((np.zeros((nt, ns)), Kt + eps * np.eye(nt))))) B = np.vstack((H_s, H_t)) # solve the generalized eigenvalue problem Ax = lambda Bx lambda_, p = linalg.eig(A, B) # sort eigenvalues in ascending order idx = np.argsort(-lambda_.real) lambda_ = lambda_[idx] p = p[:, idx] t = Y c1 = 1.0 / ns * sum(p[:ns, :].T.dot(t == 1)) c2 = 1.0 / nt * sum(p[ns:, :].T.dot(t == -1)) MMD = sum(sum(p[:ns, :].T.dot(Ks).dot(p[:ns, :])) / ns ** 2 + sum(p[ns:, :].T.dot(Kt).dot(p[ns:, :])) / nt ** 2 - 2 * sum(p[:ns, :].T.dot(Kt).dot(p[ns:, :])) / (ns * nt)) # calculate the optimal projection matrix V = p[:ns, :].dot(np.diag(1.0 / lambda_[:ns])).dot( p[:ns, :].T).dot(H_s - H_t).dot(p[ns:, :]).dot( np.diag(1.0 / lambda_[ns:])).dot(p[ns:, :].T) # calculate the transformation matrix W = X.T.dot(V).dot(X) return W if __name__ == "__main__": np.random.seed(1234) # generate example data n = 100 d = 100 X = np.random.randn(n, d) y = np.concatenate((np.ones(n // 2, dtype=np.int), -np.ones(n // 2, dtype=np.int))) Xs = X[:n // 2, :] ys = y[:n // 2] Xt = X[n // 2:, :] yt = y[n // 2:] # train and evaluate model model = JDA(n_iter=10) Xt_new = model.fit_transform(Xs, ys, Xt, yt) clf = LogisticRegression(random_state=1234) clf.fit(model.transform(Xs), ys) print('Accuracy on source domain: {:.2f}%'.format(clf.score(model.transform(Xs), ys) * 100)) print('Accuracy on target domain: {:.2f}%'.format(clf.score(Xt_new, yt) * 100)) ``` 以上就是JDA算法Python代码实现。我们可以使用上述代码实现域适应问题中的知识转移。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值