auto layout是苹果公司提供的一个基于约束布局,动态计算视图大小和位置的库,而且已经集成到xcode开发环境里。如下两个时间点须要注意。html
Auto Layout不仅有布局算法Casswory,还包含了布局在运行时的生命周期等一整套布局引擎系统,用来赞成管理布局的建立、更新和销毁。前端
这一整套布局引擎系统叫作Layout Engine,是Auto Layout的核心,主导着整个界面布局。算法
每一个视图在获得本身的布局前,Layout Engine会将试图、约束、优先级、固定大小经过计算转换成最终的大小和位置。每当约束发生变化,就会触发Deffered Layout Pass,完成后进入监听约束变化的状态。当再次监听到约束变化,就会进入到下一轮的循环中。过程以下图。xcode
UIStackView是一个容器决定排版的布局模式,容器大小的变化,会影响子项的排版。相似于前端体系中的flexbox的简化版。markdown
线性规划(Linear programming,简称LP),是运筹学中研究较早、发展较快、应用普遍、方法较成熟的一个重要分支,它是辅助人们进行科学管理的一种数学方法。研究线性约束条件下线性目标函数的极值问题的数学理论和方法。函数
例以下面例子,就是一个线性规划问题:oop
能够列出不等式组:布局
这就是一个线性规划问题。性能
来看一个例子,考虑以下线性规划:flex
能够画出以下的图:
灰色部分的区域称做为可行域,从途中能够直观的看出,x1 = 2, x2 = 6时,取到最大值为8。
这里有一个定理是,能够证实老是在交点处取到最大值。
标准形式为:
min cT X
s.t. A X <= b
复制代码
松弛形式
min cT X
s.t. A X = b
X >= 0
复制代码
注意:
单纯形法是求解线性规划的经典方法,虽然它的执行时间在最坏的状况下是非多项式的(指数时间复杂度),可是在绝大部分状况或者说实际运行过程当中,它的确是多项式时间。
步骤:
考虑以下线性规划问题:
引入松弛变量后的形式:
分离基本变量和非基本变量:
注:等号右边的叫基本变量,左边的叫非基本变量。即引入的松弛变量为基本变量,原变量为非基本变量。
考虑基本解为,将非基本变量设为0,并计算左边基本变量的值,这里很容易获得,基本解为:(0, 0, 0, 4, 2, 3, 6)T。通常而言基本解是可行的,咱们称之为基本可行解(不可行的问题后面讨论)。
如今来进行第二个步骤,旋转的操做:
每次选择一个在目标函数中系数为负数的非基本变量Xe,而后尽量的增长Xe而不违反约束,并选取基本变量Xi,而后将其位置互换。
例如,咱们选择替入变量为X1,替出变量为X5,而后替换两者的角色。执行一次转动的过程与以前所描述的线性规划是等价的。替换后以下:
一样的,将非基本变量设为0,因而获得解:(2, 0, 0, 2, 0, 3, 6)T,目标函数的值减小为-2。
继续转动,只能选取X2或者X3,不能选择X5,由于此时X5的系数是正的。假设选取替入变量X2,替出变量X4,将会获得如下结果:
继续选择增大X5,选取最严格的等式4进行替换,得:
基本解变成了(2, 2, 0, 0, 0, 3, 0)T,目标函数值为-30。
接着还能够转动X3,过程省略,最后目标值为-32,已经没有能够转动的值了,所以获得目标值为-32。
在旋转过程当中,可能会存在保持目标值不变的状况,这种现象称之为退化。好比上面的例子里出现了两次-30。不过没有产生循环的状况。
在运算过程当中可能会出现无界的状况,须要注意,例如做图出来是两条平行的线的状况
对于上方的例题来讲:
咱们能够获得以下几个矩阵:
C = (-1, -14, -6, 0, 0, 0, 0)
B = (4, 2, 3, 6)T
<img style="border-radius: 0.3125em;"
src="https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/20f1e8f4192a4b4ab499c1feab89a775~tplv-k3u1fbpfcp-zoom-1.image">
复制代码
如今须要将这些矩阵拼接成一个矩阵:
这里不难看出,左下角放的是B,右上角放的是C,右下角放的是A,而左上角那一个数字,放的是-z。
能够看出,若是将等式改写成 基本变量 = F(非基本变量)的形式的话,B和C是不变的,A矩阵中,基本变量符号相同,非基本变量符号相反。
咱们这里选取X1和X5进行翻转,获得矩阵以下:
那么这里是怎么变换过来的呢?
首先看矩阵第三行,咱们须要改写成X1 = X5,其实很是简单,将该行每个元素除以X1的系数就能够了。
那么其它行呢,其余行实际上是将X1消去,例如第一行,其实是将X1的系数和第三行中X1的系数变成同样后做差。例如这里第一行* -1后减去第三行。其它行同理。
这里经过尝试就能够发现,左上角其实是-z,具体缘由能够在尝试中体会。
不断进行替入与替出,直到第一行中全部的系数都为正。
这里咱们贴出 demo 代码,你们能够自行尝试:
import numpy as np
class Simplex(object):
def __init__(self, obj, max_mode=False):
self.max_mode = max_mode
self.mat = np.array([[0] + obj]) * (-1 if max_mode else 1)
def add_constraint(self, a, b):
self.mat = np.vstack([self.mat, [b] + a])
def solve(self):
m, n = self.mat.shape
temp, B = np.vstack([np.zeros((1, m - 1)), np.eye(m - 1)]), list(range(n - 1, n + m - 1)) # add diagonal array
mat = self.mat = np.hstack([self.mat, temp])
while mat[0, 1:].min() < 0:
col = np.where(mat[0, 1:] < 0)[0][0] + 1
row = np.array([mat[i][0] / mat[i][col] if mat[i][col] > 0 else 0x7fffffff for i in range(1, mat.shape[0])]).argmin() + 1 # find the theta index
if mat[row][col] <= 0: return None
mat[row] /= mat[row][col]
ids = np.arange(mat.shape[0]) != row
mat[ids] -= mat[row] * mat[ids, col:col + 1]
B[row] = col
return mat[0][0] * (1 if self.max_mode else -1), {B[i]: mat[i, 0] for i in range(1, m) if B[i] < n}
复制代码
from Simplex import Simplex
t = Simplex([-1, -14, -6])
t.add_constraint([1, 1, 1], 4)
t.add_constraint([1, 0, 0], 2)
t.add_constraint([0, 0, 1], 3)
t.add_constraint([0, 3, 1], 6)
print(t.solve())
print(t.mat)
复制代码
文中若有错误,欢迎指出。