コード例 #1
0
ファイル: simplex.go プロジェクト: wwguo/cigo
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
}
コード例 #2
0
ファイル: simplex.go プロジェクト: wwguo/cigo
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
}