Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
def dlog(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()
    L = int(math.ceil(math.log2(nsimplices)))
    L_Range = list(range(L))
    vp = [0, 1, 2]
    #
    m.lmbda = Var(simplices, vp, domain=NonNegativeReals)  # 非负
    m.a0 = Constraint(
        dimensions,
        rule=lambda m, d: sum(m.lmbda[s, v] * pointsT[d][tri.simplices[s][v]]
                              for s in simplices for v in vp) == input[d])
    if bound == 'eq':
        m.a1 = Constraint(expr=output == sum(
            m.lmbda[s, v] * values[tri.simplices[s][v]] for s in simplices
            for v in vp))
    elif bound == 'lb':
        m.a1 = Constraint(
            expr=output <= sum(m.lmbda[s, v] * values[tri.simplices[s][v]]
                               for s in simplices for v in vp))
    elif bound == 'ub':
        m.a1 = Constraint(
            expr=output >= sum(m.lmbda[s, v] * values[tri.simplices[s][v]]
                               for s in simplices for v in vp))
    else:
        raise RuntimeError("bound值错误!bound=" + bound)

    m.b1 = Constraint(expr=sum(m.lmbda[s, v] for s in simplices
                               for v in vp) == 1)

    m.y = Var(L_Range, domain=Binary)  # 二进制

    m.c0 = Constraint(L_Range,
                      rule=lambda m, l: sum(m.lmbda[s, v] for s in simplices
                                            if bin(s)[2:].zfill(L)[l] == '1'
                                            for v in vp) <= m.y[l])
    m.c1 = Constraint(L_Range,
                      rule=lambda m, l: sum(m.lmbda[s, v] for s in simplices
                                            if bin(s)[2:].zfill(L)[l] == '0'
                                            for v in vp) <= 1 - m.y[l])
    return m
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
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