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)
複製代碼
文中若有錯誤,歡迎指出。