def _f(m: Block): m.lmbda = Var(vertices, domain=NonNegativeReals) # 非负 m.y = Var(simplices, domain=Binary) # 二进制 m.a0 = Constraint(dimensions, rule=lambda m, d: sum(m.lmbda[v] * pointsT[d][v] for v in vertices) == input[d]) if bound == 'eq': m.a1 = Constraint(expr=output == sum(m.lmbda[v] * values[v] for v in vertices)) elif bound == 'lb': m.a1 = Constraint(expr=output <= sum(m.lmbda[v] * values[v] for v in vertices)) elif bound == 'ub': m.a1 = Constraint(expr=output >= sum(m.lmbda[v] * values[v] for v in vertices)) else: raise RuntimeError("bound值错误!bound=" + bound) m.b = Constraint(expr=sum(m.lmbda[v] for v in vertices) == 1) # generate a map from vertex index to simplex index, # which avoids an n^2 lookup when generating the # constraint vertex_to_simplex = [[] for _ in vertices] for s, simplex in enumerate(tri.simplices): for v in simplex: vertex_to_simplex[v].append(s) m.c0 = Constraint(vertices, rule=lambda m, v: m.lmbda[v] <= sum(m.y[s] for s in vertex_to_simplex[v])) m.c1 = Constraint(expr=sum(m.y[s] for s in simplices) == 1) return m
def cc(m: Block, tri: qhull.Delaunay, values: List[float], input: List[SimpleVar] = None, output: SimpleVar = None, bound: str = 'eq', **kw): values = np.array(values).tolist() ndim = len(input) nsimplices = len(tri.simplices) npoints = len(tri.points) pointsT = list(zip(*tri.points)) # create index objects dimensions = list(range(ndim)) simplices = list(range(nsimplices)) # 跟单纯形 数量一致 vertices = list(range(npoints)) bound = bound.lower() m.lmbda = Var(vertices, domain=NonNegativeReals) # 非负 m.y = Var(simplices, domain=Binary) # 二进制 # m.y = Var(simplices, domain=NonNegativeReals, bounds=(0, 1)) # 二进制 m.a0 = Constraint(dimensions, rule=lambda m, d: sum(m.lmbda[v] * pointsT[d][v] for v in vertices) == input[d]) if bound == 'eq': m.a1 = Constraint(expr=output == sum(m.lmbda[v] * values[v] for v in vertices)) elif bound == 'lb': m.a1 = Constraint(expr=output <= sum(m.lmbda[v] * values[v] for v in vertices)) elif bound == 'ub': m.a1 = Constraint(expr=output >= sum(m.lmbda[v] * values[v] for v in vertices)) else: raise RuntimeError("bound值错误!bound=" + bound) m.b = Constraint(expr=sum(m.lmbda[v] for v in vertices) == 1) # generate a map from vertex index to simplex index, # which avoids an n^2 lookup when generating the # constraint vertex_to_simplex = [[] for _ in vertices] for s, simplex in enumerate(tri.simplices): for v in simplex: vertex_to_simplex[v].append(s) m.c0 = Constraint( vertices, rule=lambda m, v: m.lmbda[v] <= sum(m.y[s] for s in vertex_to_simplex[v])) m.c1 = Constraint(expr=sum(m.y[s] for s in simplices) == 1) return m
def log_lp(m: Block, tri: qhull.Delaunay, values: List[float], input: List[SimpleVar] = None, output: SimpleVar = None, bound: str = 'eq', **kw): num = kw["num"] values = np.array(values).tolist() ndim = len(input) npoints = len(tri.points) pointsT = list(zip(*tri.points)) dims = list(range(ndim)) vertices = list(range(npoints)) bound = bound.lower() # 与 npoints 匹配的索引 # vertices_idx = list(zip(*generate_points([list(range(num)) for _ in range(ndim)]))) vertices_idx = generate_points([list(range(num)) for _ in range(ndim)]).tolist() if len(vertices_idx) != len(vertices): raise RuntimeError("生成的的tri需要是米字形!") # (9a) m.lmbda = Var(vertices, domain=NonNegativeReals) # 非负 m.a0 = Constraint(dims, rule=lambda m, d: sum(m.lmbda[v] * pointsT[d][v] for v in vertices) == input[d]) m.a_sum = Expression(expr=sum(m.lmbda[v] * values[v] for v in vertices)) if bound == 'eq': m.a1 = Constraint(expr=output == m.a_sum) elif bound == 'lb': m.a1 = Constraint(expr=output <= m.a_sum) elif bound == 'ub': m.a1 = Constraint(expr=output >= m.a_sum) else: raise RuntimeError("bound值错误!bound=" + bound) # (9b) m.b = Constraint(expr=sum(m.lmbda[v] for v in vertices) == 1) # (9c) # 约束a和b与cc方法是一样的 K = num - 1 # K 必须是偶数 N = list(range(1, ndim + 1)) log2K = math.ceil(math.log2(K)) L = list(range(1, log2K + 1)) G = generate_gray_code(log2K) def O(l, b): # k == 0 或者 k == K 的意思是不能是第一个和最后一个,避免越界 res = [] for k in range(K + 1): if (k == 0 or G[k - 1][l - 1] == b) and (k == K or G[k][l - 1] == b): res.append(k) return res # return [k for k in range(K + 1) if (k == 0 or G[k][l] == b) and (k == K or G[k + 1][l] == b)] m.y_s1 = Var(N, L, domain=NonNegativeReals, bounds=(0, 1)) # 二进制 m.c1_s1 = Constraint(N, L, rule=lambda m, s1, s2: sum( m.lmbda[v] for v, idx in zip(vertices, vertices_idx) if idx[s1 - 1] in O(s2, 1) ) <= m.y_s1[s1, s2]) m.c2_s1 = Constraint(N, L, rule=lambda m, s1, s2: sum( m.lmbda[v] for v, idx in zip(vertices, vertices_idx) if idx[s1 - 1] in O(s2, 0) ) <= 1 - m.y_s1[s1, s2]) S2 = [(s1, s2) for s1 in N for s2 in N if s1 < s2] S2_idx = list(range(len(S2))) m.y_s2 = Var(S2_idx, domain=NonNegativeReals, bounds=(0, 1)) m.c1_s2 = Constraint(S2_idx, rule=lambda m, i: sum( m.lmbda[v] for v, idx in zip(vertices, vertices_idx) if idx[S2[i][0] - 1] % 2 == 0 and idx[S2[i][1] - 1] % 2 == 1 ) <= m.y_s2[i]) m.c2_s2 = Constraint(S2_idx, rule=lambda m, i: sum( m.lmbda[v] for v, idx in zip(vertices, vertices_idx) if idx[S2[i][0] - 1] % 2 == 1 and idx[S2[i][1] - 1] % 2 == 0 ) <= 1 - m.y_s2[i]) return m