func vectorDistance(vec1, vec2 *mat.Vector) (v float64) { result := mat.NewVector(vec1.Len(), nil) result.SubVec(vec1, vec2) result.MulElemVec(result, result) v = mat.Sum(result) return }
// Scatter copies the values of x into the corresponding locations in the dense // vector y. Both vectors must have the same dimension. func Scatter(y *mat64.Vector, x *Vector) { if x.N != y.Len() { panic("sparse: vector dimension mismatch") } raw := y.RawVector() for i, index := range x.Indices { raw.Data[index*raw.Inc] = x.Data[i] } }
// Dot computes the dot product of the sparse vector x with the dense vector y. // The vectors must have the same dimension. func Dot(x *Vector, y *mat64.Vector) (dot float64) { if x.N != y.Len() { panic("sparse: vector dimension mismatch") } raw := y.RawVector() for i, index := range x.Indices { dot += x.Data[i] * raw.Data[index*raw.Inc] } return }
// findIn returns the indexes of the values in vec that match scalar func findIn(scalar float64, vec *mat.Vector) *mat.Vector { var result []float64 for i := 0; i < vec.Len(); i++ { if scalar == vec.At(i, 0) { result = append(result, float64(i)) } } return mat.NewVector(len(result), result) }
// Gather gathers entries given by indices of the dense vector y into the sparse // vector x. Indices must not be nil. func Gather(x *Vector, y *mat64.Vector, indices []int) { if indices == nil { panic("sparse: slice is nil") } x.reuseAs(y.Len(), len(indices)) copy(x.Indices, indices) raw := y.RawVector() for i, index := range x.Indices { x.Data[i] = raw.Data[index*raw.Inc] } }
// Axpy scales the sparse vector x by alpha and adds the result to the dense // vector y. If alpha is zero, y is not modified. func Axpy(y *mat64.Vector, alpha float64, x *Vector) { if x.N != y.Len() { panic("sparse: vector dimension mismatch") } if alpha == 0 { return } raw := y.RawVector() for i, index := range x.Indices { raw.Data[index*raw.Inc] += alpha * x.Data[i] } }
func dokMulMatVec(y *mat64.Vector, alpha float64, transA bool, a *DOK, x *mat64.Vector) { r, c := a.Dims() if transA { if r != x.Len() || c != y.Len() { panic("sparse: dimension mismatch") } } else { if r != y.Len() || c != x.Len() { panic("sparse: dimension mismatch") } } if alpha == 0 { return } xRaw := x.RawVector() yRaw := y.RawVector() if transA { for ij, aij := range a.data { yRaw.Data[ij[1]*yRaw.Inc] += alpha * aij * xRaw.Data[ij[0]*xRaw.Inc] } } else { for ij, aij := range a.data { yRaw.Data[ij[0]*yRaw.Inc] += alpha * aij * xRaw.Data[ij[1]*xRaw.Inc] } } }
// rowIndexIn returns a matrix contains the rows in indexes vector func rowIndexIn(indexes *mat.Vector, M mat.Matrix) mat.Matrix { m := indexes.Len() _, n := M.Dims() Res := mat.NewDense(m, n, nil) for i := 0; i < m; i++ { Res.SetRow(i, mat.Row( nil, int(indexes.At(i, 0)), M)) } return Res }
func Solve(a sparse.Matrix, b, xInit *mat64.Vector, settings *Settings, method Method) (result Result, err error) { stats := Stats{ StartTime: time.Now(), } dim, c := a.Dims() if dim != c { panic("iterative: matrix is not square") } if xInit != nil && dim != xInit.Len() { panic("iterative: mismatched size of the initial guess") } if b.Len() != dim { panic("iterative: mismatched size of the right-hand side vector") } if xInit == nil { xInit = mat64.NewVector(dim, nil) } if settings == nil { settings = DefaultSettings(dim) } ctx := Context{ X: mat64.NewVector(dim, nil), Residual: mat64.NewVector(dim, nil), } // X = xInit ctx.X.CopyVec(xInit) if mat64.Norm(ctx.X, math.Inf(1)) > 0 { // Residual = Ax sparse.MulMatVec(ctx.Residual, 1, false, a, ctx.X) stats.MatVecMultiplies++ } // Residual = Ax - b ctx.Residual.SubVec(ctx.Residual, b) if mat64.Norm(ctx.Residual, 2) >= settings.Tolerance { err = iterate(method, a, b, settings, &ctx, &stats) } result = Result{ X: ctx.X, Stats: stats, Runtime: time.Since(stats.StartTime), } return result, err }
func csrMulMatVec(y *mat64.Vector, alpha float64, transA bool, a *CSR, x *mat64.Vector) { r, c := a.Dims() if transA { if r != x.Len() || c != y.Len() { panic("sparse: dimension mismatch") } } else { if r != y.Len() || c != x.Len() { panic("sparse: dimension mismatch") } } if alpha == 0 { return } yRaw := y.RawVector() if transA { row := Vector{N: y.Len()} for i := 0; i < r; i++ { start := a.rowIndex[i] end := a.rowIndex[i+1] row.Data = a.values[start:end] row.Indices = a.columns[start:end] Axpy(y, alpha*x.At(i, 0), &row) } } else { row := Vector{N: x.Len()} for i := 0; i < r; i++ { start := a.rowIndex[i] end := a.rowIndex[i+1] row.Data = a.values[start:end] row.Indices = a.columns[start:end] yRaw.Data[i*yRaw.Inc] += alpha * Dot(&row, x) } } }