예제 #1
0
파일: solve.go 프로젝트: postfix/sparse-1
func main() {
	flag.Parse()
	if flag.NArg() == 0 {
		log.Fatal("missing file name")
	}
	name := flag.Args()[0]

	f, err := os.Open(name)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	var r io.Reader
	if path.Ext(name) == ".gz" {
		gz, err := gzip.NewReader(f)
		if err != nil {
			log.Fatal(err)
		}
		name = strings.TrimSuffix(name, ".gz")
		r = gz
	} else {
		r = f
	}

	var aDok *sparse.DOK
	switch path.Ext(name) {
	case ".mtx":
		aDok, err = readMatrixMarket(r)
	case ".rsa":
		log.Fatal("reading of Harwell-Boeing format not yet implemented")
	default:
		log.Fatal("unknown file extension")
	}
	if err != nil {
		log.Fatal(err)
	}

	a := sparse.NewCSR(aDok)
	n, _ := a.Dims()
	x := make([]float64, n)
	for i := range x {
		x[i] = 1
	}
	b := make([]float64, n)
	sparse.MulMatVec(1, false, a, x, 1, 0, b, 1)
	for i := range x {
		x[i] = 0
	}
	result, err := iterative.Solve(a, b, x, nil, &iterative.CG{})
	if err != nil {
		log.Fatal(err)
	}
	if len(result.X) > 10 {
		fmt.Println("Solution[:10]:", result.X[:10])
	} else {
		fmt.Println("Solution:", result.X)
	}
}
예제 #2
0
func iterate(method Method, a sparse.Matrix, b *mat64.Vector, settings *Settings, ctx *Context, stats *Stats) error {
	bNorm := mat64.Norm(b, 2)
	if bNorm == 0 {
		bNorm = 1
	}

	op := method.Init(ctx)
	for {
		switch op {
		case NoOperation:

		case ComputeAp:
			ctx.Ap.ScaleVec(0, ctx.Ap)
			sparse.MulMatVec(ctx.Ap, 1, false, a, ctx.P)
			stats.MatVecMultiplies++

		case ComputeAq:
			ctx.Aq.ScaleVec(0, ctx.Aq)
			sparse.MulMatVec(ctx.Aq, 1, false, a, ctx.Q)
			stats.MatVecMultiplies++

		case SolvePreconditioner:
			// TODO(vladimir-ch): Add preconditioners.
			// Z = Residual
			ctx.Z.CopyVec(ctx.Residual)
			stats.PrecondionerSolves++

		case CheckConvergence:
			stats.Iterations++
			stats.Residual = mat64.Norm(ctx.Residual, 2) / bNorm
			fmt.Println(stats.Residual)
			if stats.Residual < settings.Tolerance {
				return nil
			}
			if stats.Iterations == settings.Iterations {
				return errors.New("iterative: reached iteration limit")
			}
		}

		op = method.Iterate(ctx)
	}
}
예제 #3
0
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
}
예제 #4
0
func Solve(a sparse.Matrix, b, xInit []float64, settings *Settings, method Method) (result Result, err error) {
	stats := Stats{
		StartTime: time.Now(),
	}

	dim := len(xInit)
	if dim == 0 {
		panic("iterative: invalid dimension")
	}

	r, c := a.Dims()
	if r != c {
		panic("iterative: matrix is not square")
	}
	if c != dim {
		panic("iterative: mismatched size of the matrix")
	}
	if len(b) != dim {
		panic("iterative: mismatched size of the right-hand side vector")
	}

	if settings == nil {
		settings = DefaultSettings(dim)
	}

	ctx := Context{
		X:        make([]float64, dim),
		Residual: make([]float64, dim),
	}
	copy(ctx.X, xInit)
	copy(ctx.Residual, b)
	if floats.Norm(ctx.X, math.Inf(1)) > 0 {
		sparse.MulMatVec(-1, false, a, ctx.X, 1, 1, ctx.Residual, 1)
		stats.MatVecMultiplies++
	}

	if floats.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
}
예제 #5
0
func iterate(method Method, a sparse.Matrix, b []float64, settings *Settings, ctx *Context, stats *Stats) error {
	dim := len(ctx.X)
	bNorm := floats.Norm(b, 2)
	if bNorm == 0 {
		bNorm = 1
	}

	request := method.Init(ctx)
	for {
		switch request {
		case NoOperation:

		case ComputeAp:
			ctx.Ap = resize(ctx.Ap, dim)
			sparse.MulMatVec(1, false, a, ctx.P, 1, 0, ctx.Ap, 1)
			stats.MatVecMultiplies++

		case SolvePreconditioner:
			ctx.Z = resize(ctx.Z, dim)
			copy(ctx.Z, ctx.Residual)
			stats.PrecondionerSolves++

		case CheckConvergence:
			stats.Iterations++
			stats.Residual = floats.Norm(ctx.Residual, 2) / bNorm
			fmt.Println(stats.Residual)
			if stats.Residual < settings.Tolerance {
				return nil
			}
			if stats.Iterations == settings.Iterations {
				return errors.New("iterative: reached iteration limit")
			}
		}

		request = method.Iterate(ctx)
	}
}
예제 #6
0
파일: solve.go 프로젝트: vladimir-ch/sparse
func main() {
	flag.Parse()
	if flag.NArg() == 0 {
		log.Fatal("missing file name")
	}
	name := flag.Args()[0]

	f, err := os.Open(name)
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	var r io.Reader
	if path.Ext(name) == ".gz" {
		gz, err := gzip.NewReader(f)
		if err != nil {
			log.Fatal(err)
		}
		name = strings.TrimSuffix(name, ".gz")
		r = gz
	} else {
		r = f
	}

	// blas64.Use(cgo.Implementation{})
	blas64.Use(native.Implementation{})

	var aDok *sparse.DOK
	switch path.Ext(name) {
	case ".mtx":
		aDok, err = readMatrixMarket(r)
	case ".rsa":
		log.Fatal("reading of Harwell-Boeing format not yet implemented")
	default:
		log.Fatal("unknown file extension")
	}
	if err != nil {
		log.Fatal(err)
	}

	a := sparse.NewCSR(aDok)
	n, _ := a.Dims()

	// Create the right-hand side so that the solution is [1 1 ... 1].
	x := make([]float64, n)
	for i := range x {
		x[i] = 1
	}
	xVec := mat64.NewVector(n, x)
	bVec := mat64.NewVector(n, make([]float64, n))
	sparse.MulMatVec(bVec, 1, false, a, xVec)

	result, err := iterative.Solve(a, bVec, nil, nil, &iterative.CG{})
	if err != nil {
		log.Fatal(err)
	}
	if result.X.Len() > 10 {
		fmt.Println("Solution[:10]:", result.X.RawVector().Data[:10])
	} else {
		fmt.Println("Solution:", result.X.RawVector())
	}
}