func indexCheck(c, A, b *base.Matrix) (m, n int) { // Check matrix rows and columns. m1, n1 := A.Size() // numRows, numCols m2, _ := b.Size() _, n2 := c.Size() if m1 == m2 && n1 == n2 { if m1 < n1 { m = m1 n = n1 } else { return 0, -1 } } else { return 0, -2 } return m, n }
func Simplex(c, A, b *base.Matrix) (z float64, x base.Vector, iB []int, iN []int, err error) { // Check matrix rows and columns. m, n := indexCheck(c, A, b) switch n { case -1: return 0, nil, nil, nil, ErrorIllegalIndex case -2: return 0, nil, nil, nil, ErrorDimensionMismatch } // Prepare index list for creating matrices in each iteration. index := make([]int, n, n) for i := 1; i <= n; i++ { index[i-1] = i } iB = index[n-m : n] iN = index[0 : n-m] // Define variables specified in Simplex algorithm. var X, Z, cB, cN, B, N *base.Matrix var k, l int var σmax, βmin float64 // For starting the iteration. k = -1 for k != 0 { // Initialize matrices. X = base.MakeZero(n, 1) cB = c.GetCols(iB) cN = c.GetCols(iN) B = A.GetCols(iB) N = A.GetCols(iN) // Compute intermidiate matrices for algorithm. Binv, _ := B.Inverse() T1, _ := base.Product(cB, Binv, N) Sigma, _ := base.Subtract(cN, T1) σ := Sigma.Vector // Find the biggest σ for judgement. k = 0 σmax = 0 for i, s := range σ { if s > σmax { σmax = s k = i + 1 } } if k == 0 { // If there is no σ positive, the iteration stop and optimization reaches. d, _ := base.Multiply(Binv, b) X.SetRows(iB, d) Z, _ = base.Product(cB, Binv, b) x = X.Vector z = Z.Get(1, 1) continue } else { // If there is at least one σ positive, looking for varialbe to exchange. ak := N.GetCol(k) a, _ := base.Multiply(Binv, ak) d, _ := base.Multiply(Binv, b) // This is for find a positive β for later comparison. avec := a.Vector dvec := d.Vector for i, ai := range avec { if ai > 0 { βmin = dvec[i] / ai l = i + 1 break } } // Find the smallest β which corresponding to the variable to exchange. for i := 0; i < m; i++ { β := dvec[i] / avec[i] if avec[i] > 0 && β < βmin { βmin = β l = i + 1 } } // Exchange varialbes, controlled by indices. iB[l-1], iN[k-1] = iN[k-1], iB[l-1] } } return z, x, iB, iN, nil }