diff --git "a/\320\2403212/medvedev_409111/lab1/go.mod" "b/\320\2403212/medvedev_409111/lab1/go.mod" new file mode 100644 index 0000000..1068dcb --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab1/go.mod" @@ -0,0 +1,3 @@ +module Lab_1 + +go 1.23 diff --git "a/\320\2403212/medvedev_409111/lab1/main.go" "b/\320\2403212/medvedev_409111/lab1/main.go" new file mode 100644 index 0000000..5d6ec07 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab1/main.go" @@ -0,0 +1,191 @@ +package main + +import ( + matrix2 "Lab_1/matrix" + "bufio" + "fmt" + "math/rand" + "os" + "strconv" + "strings" + "time" +) + +func main() { + var size, maxIter int + var accuracy float64 + var isFile bool + var isRandom bool + reader, file, readerErr := getReader() + if file != nil { + defer file.Close() + isFile = true + } else { + isFile = false + } + if readerErr != nil { + fmt.Println(readerErr.Error()) + return + } + var line string + var splitline []string + if !isFile { + fmt.Print("Введите размер матрицы: ") + } + line, err := reader.ReadString('\n') + if err != nil { + fmt.Println(err.Error()) + return + } + size, err = strconv.Atoi(strings.TrimSpace(line)) + if err != nil { + fmt.Println(err.Error()) + } + data := make([][]float64, size) + vecB := make([]float64, size) + if !isFile { + fmt.Print("Введите любой символ если хотите заполнить матрицу случайными числами: ") + line, err = reader.ReadString('\n') + line = line[:len(line)-1] + if line != "" { + rand.Seed(time.Now().UnixNano()) + for i := 0; i < size; i++ { + data[i] = make([]float64, size) + for j := 0; j < size; j++ { + data[i][j] = rand.Float64() * 100 + } + } + for i := 0; i < size; i++ { + vecB[i] = rand.Float64() + } + isRandom = true + } else { + isRandom = false + } + } + if !isRandom { + if !isFile { + fmt.Println("Введите матрицу:") + } + for i := 0; i < size; i++ { + data[i] = make([]float64, size) + line, err = reader.ReadString('\n') + if err != nil { + fmt.Println(err.Error()) + return + } + splitline = strings.Split(strings.TrimSpace(line), " ") + if len(splitline) != size { + fmt.Printf("Длина %d строки матрицы некорректна\n", i+1) + } + for j := 0; j < size; j++ { + data[i][j], err = strconv.ParseFloat(splitline[j], 64) + if err != nil { + fmt.Println(err.Error()) + return + } + } + } + if !isFile { + fmt.Println("Введите вектор b: ") + } + line, err = reader.ReadString('\n') + if err != nil { + fmt.Println(err.Error()) + return + } + splitline = strings.Split(strings.TrimSpace(line), " ") + if len(splitline) != size { + fmt.Println("Некорректное количество элементов для вектора b") + return + } + for i := 0; i < size; i++ { + vecB[i], err = strconv.ParseFloat(splitline[i], 64) + if err != nil { + fmt.Println(err.Error()) + return + } + } + } + if !isFile { + fmt.Print("Введите максимальное количество итераций: ") + } + line, err = reader.ReadString('\n') + if err != nil { + fmt.Println(err.Error()) + return + } + maxIter, err = strconv.Atoi(strings.TrimSpace(line)) + if err != nil { + fmt.Println(err.Error()) + return + } + if !isFile { + fmt.Print("Введите точность: ") + } + line, err = reader.ReadString('\n') + if err != nil { + fmt.Println(err.Error()) + return + } + accuracy, err = strconv.ParseFloat(strings.TrimSpace(line), 64) + if err != nil { + fmt.Println(err.Error()) + return + } + matrix := matrix2.BuildMatrix(size, maxIter, data, vecB, accuracy) + if isRandom { + fmt.Println("Сгенерированная матрица: ") + fmt.Println(matrix.StringMatrix()) + } + if matrix.MakeDiagonallyDominant() { + fmt.Println("Диагональное преобразование найдено:") + fmt.Println(matrix.StringMatrix()) + } else { + fmt.Println("Диагональное преобразование невозможно") + } + fmt.Printf("Норма матрицы: %f\n", matrix.Norm()) + x, iter, errors, err := matrix.GaussSeidel() + if err != nil { + fmt.Println(err.Error()) + fmt.Println("Отклонения: ") + for i := 0; i < size; i++ { + fmt.Println(errors[i]) + } + return + } + fmt.Printf("Решено за %d итераций\n", iter) + fmt.Println("Отклонения: ") + for i := 0; i < size; i++ { + fmt.Println(errors[i]) + } + fmt.Println("Решение: ") + for i := 0; i < size; i++ { + fmt.Println(x[i]) + } +} + +func getReader() (*bufio.Reader, *os.File, error) { + var line string + stdin := bufio.NewReader(os.Stdin) + fmt.Print("Введите любой символ, если хотите ввести данные из файла: ") + line, err := stdin.ReadString('\n') + line = line[:len(line)-1] + if err != nil { + return nil, nil, err + } + if line == "" { + return bufio.NewReader(stdin), nil, nil + } + fmt.Print("Введите название файла: ") + line, err = stdin.ReadString('\n') + line = line[:len(line)-1] + if err != nil { + return nil, nil, err + } + file, err := os.Open(line) + if err != nil { + return nil, nil, err + } + return bufio.NewReader(file), file, nil +} diff --git "a/\320\2403212/medvedev_409111/lab1/matrix/matrix.go" "b/\320\2403212/medvedev_409111/lab1/matrix/matrix.go" new file mode 100644 index 0000000..1fa79bd --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab1/matrix/matrix.go" @@ -0,0 +1,110 @@ +package matrix + +import ( + "fmt" + "math" +) + +type Matrix struct { + size, maxIter int + data [][]float64 + vecB []float64 + accuracy float64 +} + +func BuildMatrix(size, maxIter int, data [][]float64, vecB []float64, accuracy float64) *Matrix { + matrix := &Matrix{size, maxIter, data, vecB, accuracy} + return matrix +} + +func (matrix *Matrix) IsDiagonallyDominant() bool { + for i := 0; i < matrix.size; i++ { + sum := 0.0 + for j := 0; j < matrix.size; j++ { + if i != j { + sum += math.Abs(matrix.data[i][j]) + } + } + if math.Abs(matrix.data[i][i]) <= sum { + return false + } + } + return true +} + +func (matrix *Matrix) MakeDiagonallyDominant() bool { + for i := 0; i < matrix.size; i++ { + maxRow := i + maxVal := math.Abs(matrix.data[i][i]) + for k := i + 1; k < matrix.size; k++ { + if math.Abs(matrix.data[k][i]) > maxVal { + maxVal = math.Abs(matrix.data[k][i]) + maxRow = k + } + } + if maxRow != i { + matrix.data[i], matrix.data[maxRow] = matrix.data[maxRow], matrix.data[i] + matrix.vecB[i], matrix.vecB[maxRow] = matrix.vecB[maxRow], matrix.vecB[i] + } + } + if matrix.IsDiagonallyDominant() { + return true + } else { + return false + } +} + +func (matrix *Matrix) StringMatrix() string { + ans := "" + for i := 0; i < matrix.size; i++ { + for j := 0; j < matrix.size; j++ { + ans += fmt.Sprintf("%v", matrix.data[i][j]) + " " + } + ans += fmt.Sprintf("%v", matrix.vecB[i]) + string('\n') + } + return ans[:len(ans)-1] +} + +func (matrix *Matrix) GaussSeidel() ([]float64, int, []float64, error) { + x := make([]float64, matrix.size) + for idx, _ := range x { + x[idx] = matrix.vecB[idx] / matrix.data[idx][idx] + } + errors := make([]float64, matrix.size) + + for iter := 0; iter < matrix.maxIter; iter++ { + maxDiff := 0.0 + for i := 0; i < matrix.size; i++ { + sum := 0.0 + for j := 0; j < matrix.size; j++ { + if j != i { + sum += matrix.data[i][j] * x[j] + } + } + newX := float64(matrix.vecB[i]-sum) / float64(matrix.data[i][i]) + errors[i] = math.Abs(newX - x[i]) + if errors[i] > maxDiff { + maxDiff = errors[i] + } + x[i] = newX + } + if maxDiff <= matrix.accuracy { + return x, iter + 1, errors, nil + } + } + return nil, matrix.maxIter, errors, fmt.Errorf("Решения за %d итераций при указанной точности не найдено\n", matrix.maxIter) +} + +func (matrix *Matrix) Norm() float64 { + maxNorm := 0.0 + for _, row := range matrix.data { + sum := 0.0 + for _, val := range row { + sum += math.Abs(val) + } + if sum > maxNorm { + maxNorm = sum + } + } + return maxNorm +} diff --git "a/\320\2403212/medvedev_409111/lab1/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2261.docx" "b/\320\2403212/medvedev_409111/lab1/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2261.docx" new file mode 100644 index 0000000..c53cab7 Binary files /dev/null and "b/\320\2403212/medvedev_409111/lab1/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2261.docx" differ diff --git "a/\320\2403212/medvedev_409111/lab1/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2261.pdf" "b/\320\2403212/medvedev_409111/lab1/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2261.pdf" new file mode 100644 index 0000000..66cb769 Binary files /dev/null and "b/\320\2403212/medvedev_409111/lab1/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2261.pdf" differ diff --git "a/\320\2403212/medvedev_409111/lab2/equation.go" "b/\320\2403212/medvedev_409111/lab2/equation.go" new file mode 100644 index 0000000..f9b1c43 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab2/equation.go" @@ -0,0 +1,122 @@ +package main + +import ( + "errors" + "math" +) + +type Equation struct { + fn func(float64) float64 + diff func(float64) float64 + fi func(float64) float64 + checkConvergence func(float64, float64) bool + checkRoots func(float64, float64) bool + roots []float64 +} + +func GetEquation(number int) (*Equation, error) { + switch number { + case 1: + { + roots := []float64{-1.15624, 0.629971, 2.41627} + fn := func(x float64) float64 { + return math.Pow(x, 3.0) - 1.89*math.Pow(x, 2.0) - 2.0*x + 1.76 + } + diff := func(x float64) float64 { + return 2*math.Pow(x, 2.0) - 3.78*x - 2 + } + fi := func(x float64) float64 { + return math.Pow(x, 3.0)*0.5 - 0.945*math.Pow(x, 2.0) + 1.76 + } + check := func(a float64, b float64) bool { + if a > b || a <= -1*math.Sqrt(2/3*2.89) || b >= math.Sqrt(2/3*2.89) { + return false + } + return true + } + checkRoot := func(a float64, b float64) bool { + countRoots := 0 + for _, x := range roots { + if a <= x && b >= x { + countRoots += 1 + } + } + if countRoots != 1 { + return false + } + return true + } + return &Equation{fn, diff, fi, check, checkRoot, roots}, nil + } + case 2: + roots := []float64{-1.24967, 0.508787, 3.86589} + fn := func(x float64) float64 { + return math.Pow(x, 3.0) - 3.125*math.Pow(x, 2.0) - 3.5*x + 2.458 + } + diff := func(x float64) float64 { + return 3*math.Pow(x, 2.0) - 6.25*x - 3.5 + } + fi := func(x float64) float64 { + return (math.Pow(x, 3.0) - 3.125*math.Pow(x, 2.0) + 2.458) / 3.5 + } + check := func(a float64, b float64) bool { + if a > b || a <= -0.46 || b >= 2.54 { + return false + } + return true + } + checkRoot := func(a float64, b float64) bool { + countRoots := 0 + for _, x := range roots { + if a <= x && b >= x { + countRoots += 1 + } + } + if countRoots != 1 { + return false + } + return true + } + return &Equation{fn, diff, fi, check, checkRoot, roots}, nil + case 3: + { + roots := []float64{-1.35672, 0.254703, 2.47424} + fn := func(x float64) float64 { + return 1.8*math.Pow(x, 3.0) - 2.47*math.Pow(x, 2.0) - 5.53*x + 1.539 + } + diff := func(x float64) float64 { + return 5.4*math.Pow(x, 2.0) - 4.94*x - 5.53 + } + fi := func(x float64) float64 { + return 1.8/5.53*math.Pow(x, 3.0) - 2.47/5.53*math.Pow(x, 2.0) + 1.539/5.53 + } + check := func(a float64, b float64) bool { + if a > b || a <= -1.31 || b >= 3.14 { + return true + } + return true + } + checkRoot := func(a float64, b float64) bool { + countRoots := 0 + for _, x := range roots { + if a <= x && b >= x { + countRoots += 1 + } + } + if countRoots != 1 { + return false + } + return true + } + return &Equation{fn, diff, fi, check, checkRoot, roots}, nil + } + } + return nil, errors.New("Неверный номер уравнения") +} +func GetEqMap() map[int]string { + return map[int]string{ + 1: "x^3 - 1.89x^2 - 2x + 1.76 = 0", + 2: "x^3 - 3.125x^2 - 3.5x + 2.458 = 0", + 3: "1.8x^3 - 2.47x^2 - 5.53x + 1.539 = 0", + } +} diff --git "a/\320\2403212/medvedev_409111/lab2/equation_solution.go" "b/\320\2403212/medvedev_409111/lab2/equation_solution.go" new file mode 100644 index 0000000..fa53713 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab2/equation_solution.go" @@ -0,0 +1,80 @@ +package main + +import ( + "errors" + "math" +) + +func Bisection(eq *Equation, a, b, eps float64) (float64, int, error) { + if eq.fn(a)*eq.fn(b) > 0 { + return 0, 0, errors.New("Функция на концах отрезка имеет одинаковый знак.") + } + var c float64 + iterations := 0 + for (b-a)/2 > eps { + c = (a + b) / 2 + if eq.fn(c) == 0 { + break + } else if eq.fn(a)*eq.fn(c) < 0 { + b = c + } else { + a = c + } + iterations++ + } + return c, iterations, nil +} + +func Newton(eq *Equation, x0, eps float64) (float64, int, error) { + x := x0 + iterations := 0 + for math.Abs(eq.fn(x)) > eps { + if eq.diff(x) == 0 { + return 0, 0, errors.New("Производная равна нулю, метод не применим") + } + x = x - eq.fn(x)/eq.diff(x) + iterations++ + } + return x, iterations, nil +} + +func SimpleIteration(eq *Equation, x0, eps float64) (float64, int) { + x := x0 + iterations := 0 + xPrev := x0 + 1 + for math.Abs(x-xPrev) > eps { + xPrev = x + x = eq.fi(xPrev) + iterations++ + } + return x, iterations +} + +func NewtonMethod(sysEq *SystemEquation, x0, y0 float64, eps float64, maxIter int) (float64, float64, int, float64, error) { + x, y := x0, y0 + for i := 1; i <= maxIter; i++ { + F1 := sysEq.fn1(x, y) + F2 := sysEq.fn2(x, y) + diff11 := sysEq.diff11(x, y) + diff12 := sysEq.diff12(x, y) + diff21 := sysEq.diff21(x, y) + diff22 := sysEq.diff22(x, y) + detJ := diff11*diff22 - diff12*diff21 + if math.Abs(detJ) < 1e-10 { + return 0, 0, i, 0, errors.New("Якобиан вырожден, метод Ньютона не применим") + } + dx := (F2*diff12 - F1*diff22) / detJ + dy := (F1*diff21 - F2*diff11) / detJ + xNew := x + dx + yNew := y + dy + errX := math.Abs(xNew - x) + errY := math.Abs(yNew - y) + errorVal := math.Max(math.Abs(dx), math.Abs(dy)) + if errX < eps && errY < eps { + return xNew, yNew, i, errorVal, nil + } + x, y = xNew, yNew + } + + return x, y, maxIter, math.Max(math.Abs(x-x0), math.Abs(y-y0)), errors.New("Метод не сошелся за указанное число итераций") +} diff --git "a/\320\2403212/medvedev_409111/lab2/go.mod" "b/\320\2403212/medvedev_409111/lab2/go.mod" new file mode 100644 index 0000000..bba2619 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab2/go.mod" @@ -0,0 +1,36 @@ +module Lab_2 + +go 1.23.0 + +toolchain go1.23.6 + +require ( + gioui.org v0.2.0 // indirect + gioui.org/cpu v0.0.0-20220412190645-f1e9e8c3b1f7 // indirect + gioui.org/shader v1.0.6 // indirect + gioui.org/x v0.2.0 // indirect + git.sr.ht/~sbinet/gg v0.6.0 // indirect + github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b // indirect + github.com/andybalholm/stroke v0.0.0-20221221101821-bd29b49d73f0 // indirect + github.com/campoy/embedmd v1.0.0 // indirect + github.com/faiface/glhf v0.0.0-20181018222622-82a6317ac380 // indirect + github.com/faiface/mainthread v0.0.0-20171120011319-8b78f0a41ae3 // indirect + github.com/faiface/pixel v0.10.0 // indirect + github.com/go-fonts/liberation v0.3.3 // indirect + github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 // indirect + github.com/go-gl/glfw/v3.3/glfw v0.0.0-20231223183121-56fa3ac82ce7 // indirect + github.com/go-gl/mathgl v0.0.0-20190416160123-c4601bc793c7 // indirect + github.com/go-latex/latex v0.0.0-20240709081214-31cef3c7570e // indirect + github.com/go-pdf/fpdf v0.9.0 // indirect + github.com/go-text/typesetting v0.0.0-20230803102845-24e03d8b5372 // indirect + github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c // indirect + golang.org/x/exp/shiny v0.0.0-20241009180824-f66d83c29e7c // indirect + golang.org/x/image v0.25.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.23.0 // indirect + gonum.org/v1/plot v0.15.0 // indirect + rsc.io/pdf v0.1.1 // indirect +) diff --git "a/\320\2403212/medvedev_409111/lab2/go.sum" "b/\320\2403212/medvedev_409111/lab2/go.sum" new file mode 100644 index 0000000..0a8eb6c --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab2/go.sum" @@ -0,0 +1,95 @@ +gioui.org v0.2.0 h1:RbzDn1h/pCVf/q44ImQSa/J3MIFpY3OWphzT/Tyei+w= +gioui.org v0.2.0/go.mod h1:1H72sKEk/fNFV+l0JNeM2Dt3co3Y4uaQcD+I+/GQ0e4= +gioui.org/cpu v0.0.0-20210808092351-bfe733dd3334/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ= +gioui.org/cpu v0.0.0-20220412190645-f1e9e8c3b1f7 h1:tNJdnP5CgM39PRc+KWmBRRYX/zJ+rd5XaYxY5d5veqA= +gioui.org/cpu v0.0.0-20220412190645-f1e9e8c3b1f7/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ= +gioui.org/shader v1.0.6 h1:cvZmU+eODFR2545X+/8XucgZdTtEjR3QWW6W65b0q5Y= +gioui.org/shader v1.0.6/go.mod h1:mWdiME581d/kV7/iEhLmUgUK5iZ09XR5XpduXzbePVM= +gioui.org/x v0.2.0 h1:/MbdjKH19F16auv19UiQxli2n6BYPw7eyh9XBOTgmEw= +gioui.org/x v0.2.0/go.mod h1:rCGN2nZ8ZHqrtseJoQxCMZpt2xrZUrdZ2WuMRLBJmYs= +git.sr.ht/~sbinet/gg v0.6.0 h1:RIzgkizAk+9r7uPzf/VfbJHBMKUr0F5hRFxTUGMnt38= +git.sr.ht/~sbinet/gg v0.6.0/go.mod h1:uucygbfC9wVPQIfrmwM2et0imr8L7KQWywX0xpFMm94= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= +github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= +github.com/andybalholm/stroke v0.0.0-20221221101821-bd29b49d73f0 h1:uF5Q/hWnDU1XZeT6CsrRSxHLroUSEYYO3kgES+yd+So= +github.com/andybalholm/stroke v0.0.0-20221221101821-bd29b49d73f0/go.mod h1:ccdDYaY5+gO+cbnQdFxEXqfy0RkoV25H3jLXUDNM3wg= +github.com/campoy/embedmd v1.0.0 h1:V4kI2qTJJLf4J29RzI/MAt2c3Bl4dQSYPuflzwFH2hY= +github.com/campoy/embedmd v1.0.0/go.mod h1:oxyr9RCiSXg0M3VJ3ks0UGfp98BpSSGr0kpiX3MzVl8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/faiface/glhf v0.0.0-20181018222622-82a6317ac380 h1:FvZ0mIGh6b3kOITxUnxS3tLZMh7yEoHo75v3/AgUqg0= +github.com/faiface/glhf v0.0.0-20181018222622-82a6317ac380/go.mod h1:zqnPFFIuYFFxl7uH2gYByJwIVKG7fRqlqQCbzAnHs9g= +github.com/faiface/mainthread v0.0.0-20171120011319-8b78f0a41ae3 h1:baVdMKlASEHrj19iqjARrPbaRisD7EuZEVJj6ZMLl1Q= +github.com/faiface/mainthread v0.0.0-20171120011319-8b78f0a41ae3/go.mod h1:VEPNJUlxl5KdWjDvz6Q1l+rJlxF2i6xqDeGuGAxa87M= +github.com/faiface/pixel v0.10.0 h1:EHm3ZdQw2Ck4y51cZqFfqQpwLqNHOoXwbNEc9Dijql0= +github.com/faiface/pixel v0.10.0/go.mod h1:lU0YYcW77vL0F1CG8oX51GXurymL45MXd57otHNLK7A= +github.com/go-fonts/liberation v0.3.3 h1:tM/T2vEOhjia6v5krQu8SDDegfH1SfXVRUNNKpq0Usk= +github.com/go-fonts/liberation v0.3.3/go.mod h1:eUAzNRuJnpSnd1sm2EyloQfSOT79pdw7X7++Ri+3MCU= +github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 h1:SCYMcCJ89LjRGwEa0tRluNRiMjZHalQZrVrvTbPh+qw= +github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20231223183121-56fa3ac82ce7 h1:7tf/0aw5DxRQjr7WaNqgtjidub6v21L2cogKIbMcTYw= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20231223183121-56fa3ac82ce7/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/mathgl v0.0.0-20190416160123-c4601bc793c7 h1:THttjeRn1iiz69E875U6gAik8KTWk/JYAHoSVpUxBBI= +github.com/go-gl/mathgl v0.0.0-20190416160123-c4601bc793c7/go.mod h1:yhpkQzEiH9yPyxDUGzkmgScbaBVlhC06qodikEM0ZwQ= +github.com/go-latex/latex v0.0.0-20240709081214-31cef3c7570e h1:xcdj0LWnMSIU1j8+jIeJyfvk6SjgJedFQssSqFthJ2E= +github.com/go-latex/latex v0.0.0-20240709081214-31cef3c7570e/go.mod h1:J4SAGzkcl+28QWi7yz72tyC/4aGnppOvya+AEv4TaAQ= +github.com/go-pdf/fpdf v0.9.0 h1:PPvSaUuo1iMi9KkaAn90NuKi+P4gwMedWPHhj8YlJQw= +github.com/go-pdf/fpdf v0.9.0/go.mod h1:oO8N111TkmKb9D7VvWGLvLJlaZUQVPM+6V42pp3iV4Y= +github.com/go-text/typesetting v0.0.0-20230803102845-24e03d8b5372 h1:FQivqchis6bE2/9uF70M2gmmLpe82esEm2QadL0TEJo= +github.com/go-text/typesetting v0.0.0-20230803102845-24e03d8b5372/go.mod h1:evDBbvNR/KaVFZ2ZlDSOWWXIUKq0wCOEtzLxRM8SG3k= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c h1:7dEasQXItcW1xKJ2+gg5VOiBnqWrJc+rq0DPKyvvdbY= +golang.org/x/exp v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:NQtJDoLvd6faHhE7m4T/1IY708gDefGGjR/iUW8yQQ8= +golang.org/x/exp/shiny v0.0.0-20241009180824-f66d83c29e7c h1:jTMrjjZRcSH/BDxWhXCP6OWsfVgmnwI7J+F4/nyVXaU= +golang.org/x/exp/shiny v0.0.0-20241009180824-f66d83c29e7c/go.mod h1:3F+MieQB7dRYLTmnncoFbb1crS5lfQoTfDgQy6K4N0o= +golang.org/x/image v0.0.0-20190321063152-3fc05d484e9f/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190523035834-f03afa92d3ff/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s= +golang.org/x/image v0.21.0/go.mod h1:vUbsLavqK/W303ZroQQVKQ+Af3Yl6Uz1Ppu5J/cLz78= +golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ= +golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/plot v0.15.0 h1:SIFtFNdZNWLRDRVjD6CYxdawcpJDWySZehJGpv1ukkw= +gonum.org/v1/plot v0.15.0/go.mod h1:3Nx4m77J4T/ayr/b8dQ8uGRmZF6H3eTqliUExDrQHnM= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git "a/\320\2403212/medvedev_409111/lab2/graph.go" "b/\320\2403212/medvedev_409111/lab2/graph.go" new file mode 100644 index 0000000..f798668 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab2/graph.go" @@ -0,0 +1,206 @@ +package main + +import ( + "fmt" + "git.sr.ht/~sbinet/gg" + "github.com/faiface/pixel" + "github.com/faiface/pixel/pixelgl" + "image/color" + "log" + "math" + "strconv" +) + +const width, height = 600, 600 + +func DrawGraphic(cancel <-chan struct{}, eq ...*Equation) { + dc := gg.NewContext(width, height) + dc.SetColor(color.White) + dc.Clear() + dc.SetColor(color.Black) + dc.SetLineWidth(1) + dc.DrawLine(0, height/2, width, height/2) + dc.DrawLine(width/2, 0, width/2, height) + dc.Stroke() + const tickCount = 10 + xStep := float64(width) / float64(tickCount) + yStep := float64(height) / float64(tickCount) + for i := 0; i <= tickCount; i++ { + x := float64(i) * xStep + label := strconv.Itoa(i - tickCount/2) + dc.DrawStringAnchored(label, x, height/2+15, 0.5, 0.5) + } + for i := 0; i <= tickCount; i++ { + y := float64(i) * yStep + label := strconv.Itoa(tickCount/2 - i) + dc.DrawStringAnchored(label, width/2-15, y, 0.5, 0.5) + } + colors := []color.Color{ + color.RGBA{255, 0, 0, 255}, + color.RGBA{0, 255, 0, 255}, + color.RGBA{0, 0, 255, 255}, + color.RGBA{255, 165, 0, 255}, + } + for i, equation := range eq { + dc.SetColor(colors[i%len(colors)]) + dc.SetLineWidth(2) + prevX, prevY := 0.0, 0.0 + firstPoint := true + for px := 1; px <= width; px++ { + x := (float64(px) * 10 / float64(width)) - 5 + y := equation.fn(x) + if math.IsNaN(y) || math.IsInf(y, 0) { + firstPoint = true + continue + } + screenX := float64(px) + screenY := height/2 - (y * 40) + if firstPoint { + prevX, prevY = screenX, screenY + firstPoint = false + continue + } + dc.DrawLine(prevX, prevY, screenX, screenY) + prevX, prevY = screenX, screenY + } + dc.Stroke() + dc.SetColor(color.RGBA{0, 0, 0, 255}) + for _, root := range equation.roots { + px := int(((root + 5) / 10) * float64(width)) + py := int(height / 2) + dc.DrawCircle(float64(px), float64(py), 3) + dc.Fill() + label := fmt.Sprintf("(%.2f, 0)", root) + dc.SetColor(color.Black) + dc.DrawStringAnchored(label, float64(px)+10, float64(py)-10, 0.5, 0.5) + } + } + + pixelgl.Run(func() { + cfg := pixelgl.WindowConfig{ + Title: "График уравнения", + Bounds: pixel.R(0, 0, width, height), + VSync: true, + } + win, err := pixelgl.NewWindow(cfg) + if err != nil { + log.Fatal(err) + return + } + pic := pixel.PictureDataFromImage(dc.Image()) + sprite := pixel.NewSprite(pic, pic.Bounds()) + for !win.Closed() { + select { + case <-cancel: + win.SetClosed(true) + break + default: + win.Clear(color.White) + sprite.Draw(win, pixel.IM.Moved(win.Bounds().Center())) + win.Update() + } + } + }) +} + +func DrawSystemGraphic(cancel <-chan struct{}, eq *SystemEquation) { + dc := gg.NewContext(width, height) + dc.SetColor(color.White) + dc.Clear() + + dc.SetColor(color.Black) + dc.SetLineWidth(1) + dc.DrawLine(0, height/2, width, height/2) + dc.DrawLine(width/2, 0, width/2, height) + dc.Stroke() + + const tickCount = 10 + xStep := float64(width) / float64(tickCount) + yStep := float64(height) / float64(tickCount) + for i := 0; i <= tickCount; i++ { + x := float64(i) * xStep + label := strconv.Itoa(i - tickCount/2) + dc.DrawStringAnchored(label, x, height/2+15, 0.5, 0.5) + } + + for i := 0; i <= tickCount; i++ { + y := float64(i) * yStep + label := strconv.Itoa(tickCount/2 - i) + dc.DrawStringAnchored(label, width/2-15, y, 0.5, 0.5) + } + + colors := []color.Color{ + color.RGBA{255, 0, 0, 255}, + color.RGBA{0, 0, 255, 255}, + } + + dc.SetColor(colors[0]) + dc.SetLineWidth(1) + for px := 0; px < width; px++ { + for py := 0; py < height; py++ { + x := (float64(px)/width)*10 - 5 + y := (float64(py)/height)*10 - 5 + z := eq.fn1(x, y) + if z > -0.05 && z < 0.05 { + dc.SetPixel(px, height-int((y+5)/10*float64(height))) + } + } + } + dc.Stroke() + + dc.SetColor(colors[1]) + dc.SetLineWidth(1) + for px := 0; px < width; px++ { + for py := 0; py < height; py++ { + x := (float64(px)/width)*10 - 5 + y := (float64(py)/height)*10 - 5 + z := eq.fn2(x, y) + if z > -0.05 && z < 0.05 { + dc.SetPixel(px, height-int((y+5)/10*float64(height))) + } + } + } + dc.Stroke() + + dc.SetColor(color.Black) + dc.SetLineWidth(2) + for _, root := range eq.roots { + px := int(((root[0] + 5) / 10) * float64(width)) + py := height - int(((root[1]+5)/10)*float64(height)) + dc.DrawCircle(float64(px), float64(py), 3) + dc.Fill() + + label := fmt.Sprintf("(%.2f, %.2f)", root[0], root[1]) + dc.SetColor(color.Black) + dc.DrawStringAnchored(label, float64(px)+8, float64(py)-8, 0, 0) + } + + pixelgl.Run(func() { + cfg := pixelgl.WindowConfig{ + Title: "График системы нелинейных уравнений", + Bounds: pixel.R(0, 0, width, height), + VSync: true, + } + + win, err := pixelgl.NewWindow(cfg) + if err != nil { + log.Fatal(err) + return + } + + pic := pixel.PictureDataFromImage(dc.Image()) + sprite := pixel.NewSprite(pic, pic.Bounds()) + + for !win.Closed() { + select { + case <-cancel: + win.SetClosed(true) + return + default: + win.Clear(color.White) + sprite.Draw(win, pixel.IM.Moved(win.Bounds().Center())) + win.Update() + } + } + }) +} diff --git "a/\320\2403212/medvedev_409111/lab2/main.go" "b/\320\2403212/medvedev_409111/lab2/main.go" new file mode 100644 index 0000000..52f9635 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab2/main.go" @@ -0,0 +1,132 @@ +package main + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" +) + +func main() { + reader, inFile, err := getReader() + if err != nil { + fmt.Println(err) + return + } + writer, outFile, err := getWriter() + if err != nil { + fmt.Println(err) + return + } + isFile := false + if inFile != nil { + isFile = true + defer inFile.Close() + } + if outFile != nil { + defer outFile.Close() + } + stdin := bufio.NewReader(os.Stdin) + fmt.Print("Введите 1, если хотите решить уравнение, и 2, если систему линейных уравнений: ") + ans, err := stdin.ReadString('\n') + if err != nil { + fmt.Println(err) + return + } + ans = strings.TrimSpace(ans) + if ans == "1" { + fmt.Println("Выберете уравнение:") + eqMap := GetEqMap() + for key, _ := range eqMap { + fmt.Printf("%v - %v\n", key, eqMap[key]) + } + line, err := stdin.ReadString('\n') + if err != nil { + fmt.Println(err) + return + } + number, err := strconv.Atoi(strings.TrimSpace(line)) + if err != nil { + fmt.Println(err) + return + } + err = HandleSimple(reader, writer, isFile, number) + if err != nil { + fmt.Println(err) + } + } else if ans == "2" { + fmt.Println("Выберете уравнение:") + sysEqMap := GetSysEqMap() + for key, _ := range sysEqMap { + fmt.Printf("%v - %v\n", key, sysEqMap[key]) + } + line, err := stdin.ReadString('\n') + if err != nil { + fmt.Println(err) + return + } + number, err := strconv.Atoi(strings.TrimSpace(line)) + if err != nil { + fmt.Println(err) + return + } + err = HandleSystem(reader, writer, isFile, number) + if err != nil { + fmt.Println(err) + } + } else { + fmt.Println("Неверный ввод") + return + } +} + +func getReader() (*bufio.Reader, *os.File, error) { + var line string + stdin := bufio.NewReader(os.Stdin) + fmt.Print("Введите любой символ, если хотите ввести данные из файла: ") + line, err := stdin.ReadString('\n') + line = line[:len(line)-1] + if err != nil { + return nil, nil, err + } + if line == "" { + return bufio.NewReader(stdin), nil, nil + } + fmt.Print("Введите название файла: ") + line, err = stdin.ReadString('\n') + line = line[:len(line)-1] + if err != nil { + return nil, nil, err + } + file, err := os.Open(line) + if err != nil { + return nil, nil, err + } + return bufio.NewReader(file), file, nil +} + +func getWriter() (*bufio.Writer, *os.File, error) { + var line string + stdin := bufio.NewReader(os.Stdin) + fmt.Print("Введите любой символ, если хотите перенаправить вывод в файл: ") + line, err := stdin.ReadString('\n') + line = line[:len(line)-1] + if err != nil { + return nil, nil, err + } + if line == "" { + return bufio.NewWriter(os.Stdout), nil, nil + } + fmt.Print("Введите название файла: ") + line, err = stdin.ReadString('\n') + line = line[:len(line)-1] + if err != nil { + return nil, nil, err + } + file, err := os.Create(line) + if err != nil { + return nil, nil, err + } + return bufio.NewWriter(file), file, nil +} diff --git "a/\320\2403212/medvedev_409111/lab2/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2262.pdf" "b/\320\2403212/medvedev_409111/lab2/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2262.pdf" new file mode 100644 index 0000000..0203d03 Binary files /dev/null and "b/\320\2403212/medvedev_409111/lab2/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2262.pdf" differ diff --git "a/\320\2403212/medvedev_409111/lab2/simple_eq_controller.go" "b/\320\2403212/medvedev_409111/lab2/simple_eq_controller.go" new file mode 100644 index 0000000..e70328f --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab2/simple_eq_controller.go" @@ -0,0 +1,204 @@ +package main + +import ( + "bufio" + "errors" + "fmt" + "strconv" + "strings" +) + +func HandleSimple(reader *bufio.Reader, writer *bufio.Writer, isFile bool, number int) error { + eq, err := GetEquation(number) + if err != nil { + return err + } + cancel := make(chan struct{}) + errChan := make(chan error) + go func() { + defer func() { + close(errChan) + close(cancel) + }() + if !isFile { + fmt.Println("Выберете каким методом решить уравнение:") + fmt.Println("1 - метод простой итерации") + fmt.Println("2 - метод Ньютона") + fmt.Println("3 - метод половинного деления") + } + ans, err := reader.ReadString('\n') + if err != nil { + cancel <- struct{}{} + errChan <- err + return + } + ans = strings.TrimSpace(ans) + if ans == "1" { + err := handleSimpleIter(reader, writer, eq, isFile) + if err != nil { + cancel <- struct{}{} + errChan <- err + return + } + } else if ans == "2" { + err := handleNewton(reader, writer, eq, isFile) + if err != nil { + cancel <- struct{}{} + errChan <- err + return + } + } else if ans == "3" { + err := handleBisection(reader, writer, eq, isFile) + if err != nil { + cancel <- struct{}{} + errChan <- err + return + } + } else { + cancel <- struct{}{} + errChan <- errors.New("Неверно выбран метод для решения") + return + } + cancel <- struct{}{} + errChan <- nil + }() + DrawGraphic(cancel, eq) + return <-errChan +} + +func handleSimpleIter(reader *bufio.Reader, writer *bufio.Writer, eq *Equation, isFile bool) error { + for i := 0; i < len(eq.roots); i++ { + if !isFile { + fmt.Printf("Введите данные для корня %v:\n", i+1) + } + eps, a, b, err := handleInterval(reader, writer, eq, isFile) + if err != nil { + return err + } + if !eq.checkConvergence(a, b) { + return errors.New("Функция на сходится на данном промежутке") + } + res, iter := SimpleIteration(eq, (a+b)/2, eps) + _, err = writer.WriteString(fmt.Sprintf("Корень: %v\n", res)) + if err != nil { + return err + } + err = writer.Flush() + if err != nil { + return err + } + _, err = writer.WriteString(fmt.Sprintf("Количество итераций: %v\n", iter)) + if err != nil { + return err + } + err = writer.Flush() + if err != nil { + return err + } + } + return nil +} + +func handleBisection(reader *bufio.Reader, writer *bufio.Writer, eq *Equation, isFile bool) error { + for i := 0; i < len(eq.roots); i++ { + if !isFile { + fmt.Printf("Введите данные для корня %v:\n", i+1) + } + eps, a, b, err := handleInterval(reader, writer, eq, isFile) + if err != nil { + return err + } + res, iter, err := Bisection(eq, a, b, eps) + if err != nil { + return err + } + _, err = writer.WriteString(fmt.Sprintf("Корень: %v\n", res)) + if err != nil { + return err + } + err = writer.Flush() + if err != nil { + return err + } + _, err = writer.WriteString(fmt.Sprintf("Количество итераций: %v\n", iter)) + if err != nil { + return err + } + err = writer.Flush() + if err != nil { + return err + } + } + return nil +} + +func handleNewton(reader *bufio.Reader, writer *bufio.Writer, eq *Equation, isFile bool) error { + for i := 0; i < len(eq.roots); i++ { + if !isFile { + fmt.Printf("Введите данные для корня %v:\n", i+1) + } + eps, a, b, err := handleInterval(reader, writer, eq, isFile) + if err != nil { + return err + } + res, iter, err := Newton(eq, (a+b)/2, eps) + if err != nil { + return err + } + _, err = writer.WriteString(fmt.Sprintf("Корень: %v\n", res)) + if err != nil { + return err + } + err = writer.Flush() + if err != nil { + return err + } + _, err = writer.WriteString(fmt.Sprintf("Количество итераций: %v\n", iter)) + if err != nil { + return err + } + err = writer.Flush() + if err != nil { + return err + } + } + return nil +} + +func handleInterval(reader *bufio.Reader, writer *bufio.Writer, eq *Equation, isFile bool) (float64, float64, float64, error) { + if !isFile { + fmt.Print("Введите точность: ") + } + line, err := reader.ReadString('\n') + if err != nil { + return 0, 0, 0, err + } + eps, err := strconv.ParseFloat(strings.TrimSpace(line), 64) + if err != nil { + return 0, 0, 0, err + } + if eps <= 0 { + return 0, 0, 0, errors.New("Неверно указана точность") + } + if !isFile { + fmt.Print("Введите начало промежутка: ") + } + line, err = reader.ReadString('\n') + if err != nil { + return 0, 0, 0, err + } + a, err := strconv.ParseFloat(strings.TrimSpace(line), 64) + if !isFile { + fmt.Print("Введите конец промежутка: ") + } + line, err = reader.ReadString('\n') + if err != nil { + return 0, 0, 0, err + } + b, err := strconv.ParseFloat(strings.TrimSpace(line), 64) + + if !eq.checkRoots(a, b) { + return 0, 0, 0, errors.New("На промежутке имеется количество корней не равное 1") + } + return eps, a, b, nil +} diff --git "a/\320\2403212/medvedev_409111/lab2/sys_eq_controller.go" "b/\320\2403212/medvedev_409111/lab2/sys_eq_controller.go" new file mode 100644 index 0000000..164b993 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab2/sys_eq_controller.go" @@ -0,0 +1,133 @@ +package main + +import ( + "bufio" + "errors" + "fmt" + "strconv" + "strings" +) + +func HandleSystem(reader *bufio.Reader, writer *bufio.Writer, isFile bool, number int) error { + sysEq, err := GetSystemEquation(number) + if err != nil { + return err + } + cancel := make(chan struct{}) + errChan := make(chan error, 1) + go func() { + defer func() { + close(errChan) + close(cancel) + }() + if !isFile { + fmt.Print("Введите точность: ") + } + line, err := reader.ReadString('\n') + if err != nil { + cancel <- struct{}{} + errChan <- err + return + } + eps, err := strconv.ParseFloat(strings.TrimSpace(line), 64) + if eps <= 0 { + cancel <- struct{}{} + errChan <- errors.New("Неверно указана точность") + return + } + if !isFile { + fmt.Print("Введите максимальное количество итераций: ") + } + line, err = reader.ReadString('\n') + if err != nil { + cancel <- struct{}{} + errChan <- err + return + } + maxIter, err := strconv.Atoi(strings.TrimSpace(line)) + if maxIter <= 0 { + cancel <- struct{}{} + errChan <- errors.New("Неверно указано максимальное количество итераций") + return + } + if !isFile { + fmt.Println("Введите начальные приближения: ") + fmt.Print("x0: ") + } + line, err = reader.ReadString('\n') + if err != nil { + cancel <- struct{}{} + errChan <- err + return + } + x0, err := strconv.ParseFloat(strings.TrimSpace(line), 64) + if !isFile { + fmt.Print("y0: ") + } + line, err = reader.ReadString('\n') + if err != nil { + cancel <- struct{}{} + errChan <- err + return + } + y0, err := strconv.ParseFloat(strings.TrimSpace(line), 64) + x, y, iter, maxError, err := NewtonMethod(sysEq, x0, y0, eps, maxIter) + if err != nil { + cancel <- struct{}{} + errChan <- err + return + } + _, err = writer.WriteString(fmt.Sprintf("X: %v\n", x)) + if err != nil { + cancel <- struct{}{} + errChan <- err + return + } + err = writer.Flush() + if err != nil { + cancel <- struct{}{} + errChan <- err + return + } + _, err = writer.WriteString(fmt.Sprintf("Y: %v\n", y)) + if err != nil { + cancel <- struct{}{} + errChan <- err + return + } + err = writer.Flush() + if err != nil { + cancel <- struct{}{} + errChan <- err + return + } + _, err = writer.WriteString(fmt.Sprintf("Итерация: %v\n", iter)) + if err != nil { + cancel <- struct{}{} + errChan <- err + return + } + err = writer.Flush() + if err != nil { + cancel <- struct{}{} + errChan <- err + return + } + _, err = writer.WriteString(fmt.Sprintf("Максимальная ошибка: %v\n", maxError)) + if err != nil { + cancel <- struct{}{} + errChan <- err + return + } + err = writer.Flush() + if err != nil { + cancel <- struct{}{} + errChan <- err + return + } + cancel <- struct{}{} + errChan <- nil + }() + DrawSystemGraphic(cancel, sysEq) + return <-errChan +} diff --git "a/\320\2403212/medvedev_409111/lab2/system_equation.go" "b/\320\2403212/medvedev_409111/lab2/system_equation.go" new file mode 100644 index 0000000..f51dfa7 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab2/system_equation.go" @@ -0,0 +1,72 @@ +package main + +import "math" + +type SystemEquation struct { + fn1 func(float64, float64) float64 + fn2 func(float64, float64) float64 + diff11 func(float64, float64) float64 + diff12 func(float64, float64) float64 + diff21 func(float64, float64) float64 + diff22 func(float64, float64) float64 + roots [][]float64 +} + +func GetSystemEquation(number int) (*SystemEquation, error) { + switch number { + case 1: + { + fn1 := func(x float64, y float64) float64 { + return math.Tan(x*y) - x*x + } + fn2 := func(x float64, y float64) float64 { + return 0.5*x*x + 2*y*y - 1 + } + diff11 := func(x float64, y float64) float64 { + return y/math.Pow(math.Cos(x*y), 2.0) - 2*x + } + diff12 := func(x float64, y float64) float64 { + return x / math.Pow(math.Cos(x*y), 2.0) + } + diff21 := func(x float64, y float64) float64 { + return x + } + diff22 := func(x float64, y float64) float64 { + return 4 * y + } + return &SystemEquation{fn1, fn2, diff11, diff12, diff21, diff22, [][]float64{[]float64{0.664, 0.624}, []float64{-0.662, -0.624}}}, nil + } + case 2: + { + fn1 := func(x float64, y float64) float64 { + return x + math.Sin(y) + 0.4 + } + fn2 := func(x float64, y float64) float64 { + return 2*y - math.Cos(x+1) + } + diff11 := func(x float64, y float64) float64 { + return 1 + } + diff12 := func(x float64, y float64) float64 { + return math.Cos(y) + } + diff21 := func(x float64, y float64) float64 { + return math.Sin(x + 1) + } + diff22 := func(x float64, y float64) float64 { + return 2 + } + return &SystemEquation{fn1, fn2, diff11, diff12, diff21, diff22, [][]float64{[]float64{-0.87, 0.49}}}, nil + } + } + return nil, nil +} + +func GetSysEqMap() map[int]string { + return map[int]string{ + 1: "\n| tg(xy) = x^2\n" + + "| 0.5x^2 + 2y^2 = 1", + 2: "\n| x + sin(y) = -0.4\n" + + "| 2y - cos(x + 1) = 0", + } +} diff --git "a/\320\2403212/medvedev_409111/lab3/go.mod" "b/\320\2403212/medvedev_409111/lab3/go.mod" new file mode 100644 index 0000000..a883462 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab3/go.mod" @@ -0,0 +1,3 @@ +module Lab_3 + +go 1.23 diff --git "a/\320\2403212/medvedev_409111/lab3/input.go" "b/\320\2403212/medvedev_409111/lab3/input.go" new file mode 100644 index 0000000..3484c1f --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab3/input.go" @@ -0,0 +1,87 @@ +package main + +import ( + "bufio" + "errors" + "fmt" + "strconv" + "strings" +) + +func ParseIntegral(reader *bufio.Reader) (*Integral, error) { + fmt.Println("Выберите интеграл для вычисления: ") + descMap := GetIntegralDescription() + for key, _ := range descMap { + fmt.Printf("%v - %v\n", key, descMap[key]) + } + line, err := reader.ReadString('\n') + if err != nil { + return nil, err + } + intNum, err := strconv.Atoi(strings.TrimSpace(line)) + if err != nil { + return nil, err + } + integral, err := GetIntegral(intNum) + if err != nil { + return nil, err + } + fmt.Println("Укажите начало промежутка: ") + line, err = reader.ReadString('\n') + if err != nil { + return nil, err + } + a, err := strconv.ParseFloat(strings.TrimSpace(line), 64) + if err != nil { + return nil, err + } + fmt.Println("Укажите конец промежутка: ") + line, err = reader.ReadString('\n') + if err != nil { + return nil, err + } + b, err := strconv.ParseFloat(strings.TrimSpace(line), 64) + if err != nil { + return nil, err + } + if a >= b { + return nil, errors.New("Некорректно указан промежуток") + } + integral.start = a + integral.end = b + return integral, nil +} + +func ParseAccuracy(reader *bufio.Reader) (float64, error) { + fmt.Println("Укажите точность: ") + line, err := reader.ReadString('\n') + if err != nil { + return -1.0, err + } + acc, err := strconv.ParseFloat(strings.TrimSpace(line), 64) + if err != nil { + return -1.0, err + } + if acc <= 0.0 { + return -1.0, errors.New("Некорректно указана точность") + } + return acc, nil +} + +func ParseMethod(reader *bufio.Reader) (func(*Integral, int) float64, error) { + fmt.Println("Выберите метод для вычисления интеграла: ") + methodMap := GetMethodDescription() + for key, _ := range methodMap { + fmt.Printf("%v - %v\n", key, methodMap[key]) + } + line, err := reader.ReadString('\n') + if err != nil { + return nil, err + } + methodNum, err := strconv.Atoi(strings.TrimSpace(line)) + if err != nil { + return nil, err + } + method, err := GetMethod(methodNum) + return method, err +} diff --git "a/\320\2403212/medvedev_409111/lab3/integral.go" "b/\320\2403212/medvedev_409111/lab3/integral.go" new file mode 100644 index 0000000..bfa8280 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab3/integral.go" @@ -0,0 +1,46 @@ +package main + +import ( + "errors" + "math" +) + +type Integral struct { + fn func(float64) float64 + start float64 + end float64 +} + +func GetIntegral(num int) (*Integral, error) { + var fn func(float64) float64 + switch num { + case 1: + fn = func(x float64) float64 { + return -1*math.Pow(x, 3.0) - math.Pow(x, 2.0) - 2*x + 1 + } + case 2: + fn = func(x float64) float64 { + return math.Pow(x, 3.0) - 3*math.Pow(x, 2.0) + 6*x - 19 + } + case 3: + fn = func(x float64) float64 { + return math.Pow(x, 2.0) + math.Cos(x) + } + case 4: + fn = func(x float64) float64 { + return (3*x + 12) * math.Sin(x) + } + default: + return nil, errors.New("Некорректно выбран интеграл") + } + return &Integral{fn: fn}, nil +} + +func GetIntegralDescription() map[int]string { + return map[int]string{ + 1: "-x^3 - x^2 - 2x + 1", + 2: "x^3 - 3x^2 + 6x - 19", + 3: "x^2 + cos(x)", + 4: "(3x + 12)sin(x)", + } +} diff --git "a/\320\2403212/medvedev_409111/lab3/main.go" "b/\320\2403212/medvedev_409111/lab3/main.go" new file mode 100644 index 0000000..249cef5 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab3/main.go" @@ -0,0 +1,29 @@ +package main + +import ( + "bufio" + "fmt" + "os" +) + +func main() { + reader := bufio.NewReader(os.Stdin) + integral, err := ParseIntegral(reader) + if err != nil { + fmt.Println(err) + return + } + acc, err := ParseAccuracy(reader) + if err != nil { + fmt.Println(err) + return + } + method, err := ParseMethod(reader) + if err != nil { + fmt.Println(err) + return + } + ans, iter := SolveIntegral(integral, acc, method) + fmt.Printf("Значение интеграла: %v\n", ans) + fmt.Printf("Итерация: %v\n", iter) +} diff --git "a/\320\2403212/medvedev_409111/lab3/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2263.pdf" "b/\320\2403212/medvedev_409111/lab3/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2263.pdf" new file mode 100644 index 0000000..9c1d876 Binary files /dev/null and "b/\320\2403212/medvedev_409111/lab3/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2263.pdf" differ diff --git "a/\320\2403212/medvedev_409111/lab3/solution_integrals.go" "b/\320\2403212/medvedev_409111/lab3/solution_integrals.go" new file mode 100644 index 0000000..e55b950 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab3/solution_integrals.go" @@ -0,0 +1,110 @@ +package main + +import ( + "errors" + "math" +) + +func getPartition(integral *Integral, start float64, h float64, count int) []float64 { + yArr := make([]float64, count) + for i := 0; i < count; i++ { + yArr[i] = integral.fn(start + float64(i)*h) + } + return yArr +} + +func countH(integral *Integral, iter int) float64 { + return (integral.end - integral.start) / float64(iter) +} + +func rectangle(yArr []float64, h float64) float64 { + i0 := 0.0 + for _, y := range yArr { + i0 += y + } + return i0 * h +} + +func SolveIntegral(integral *Integral, accuracy float64, fn func(*Integral, int) float64) (float64, int) { + iter := 4 + i0 := fn(integral, iter) + iter *= 2 + i1 := fn(integral, iter) + for math.Abs(i1-i0) >= accuracy { + iter *= 2 + i0 = i1 + i1 = fn(integral, iter) + } + return i1, iter +} + +func LeftRectangle(integral *Integral, startIter int) float64 { + h := countH(integral, startIter) + yArr := getPartition(integral, integral.start, h, startIter) + return rectangle(yArr, h) +} + +func RightRectangle(integral *Integral, iter int) float64 { + h := countH(integral, iter) + yArr := getPartition(integral, integral.start+h, h, iter) + return rectangle(yArr, h) +} + +func MidRectangle(integral *Integral, iter int) float64 { + h := countH(integral, iter) + yArr := getPartition(integral, integral.start+h/2, h, iter) + return rectangle(yArr, h) +} + +func Trapeze(integral *Integral, iter int) float64 { + h := countH(integral, iter) + yArr := getPartition(integral, integral.start, h, iter+1) + i0 := yArr[0] + yArr[len(yArr)-1] + i0 /= 2 + for i := 1; i < len(yArr)-1; i++ { + i0 += yArr[i] + } + return i0 * h +} + +func Simpson(integral *Integral, iter int) float64 { + h := countH(integral, iter) + yArr := getPartition(integral, integral.start, h, iter+1) + i0 := yArr[0] + yArr[len(yArr)-1] + for i := 1; i < len(yArr)-1; i += 2 { + i0 += 4 * yArr[i] + } + for i := 2; i < len(yArr)-1; i += 2 { + i0 += 2 * yArr[i] + } + return i0 * h / 3 +} + +func GetMethodDescription() map[int]string { + return map[int]string{ + 1: "Метод левых прямоугольников", + 2: "Метод правых прямоугольников", + 3: "Метод средних прямоугольников", + 4: "Метод трапеции", + 5: "Метод Симпсона", + } +} + +func GetMethod(num int) (func(*Integral, int) float64, error) { + var fn func(*Integral, int) float64 + switch num { + case 1: + fn = LeftRectangle + case 2: + fn = RightRectangle + case 3: + fn = MidRectangle + case 4: + fn = Trapeze + case 5: + fn = Simpson + default: + return nil, errors.New("Метод выбран некорректно") + } + return fn, nil +} diff --git "a/\320\2403212/medvedev_409111/lab4/approximate.go" "b/\320\2403212/medvedev_409111/lab4/approximate.go" new file mode 100644 index 0000000..93064de --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab4/approximate.go" @@ -0,0 +1,234 @@ +package main + +import ( + "fmt" + "math" +) + +type Point struct { + X float64 + Y float64 +} + +type ApproxFunc struct { + Name string + Func func(float64, []float64) float64 + Approximate func([]Point) ([]float64, error) + Coefficients []float64 +} + +func NewLinear(points []Point) (*ApproxFunc, error) { + approx := ApproxFunc{ + Name: "Линейная", + Func: func(x float64, coeffs []float64) float64 { + return coeffs[0] + coeffs[1]*x + }, + Approximate: func(points []Point) ([]float64, error) { + var sx, sy, sxx, sxy float64 + n := float64(len(points)) + for _, p := range points { + sx += p.X + sy += p.Y + sxx += p.X * p.X + sxy += p.X * p.Y + } + det := n*sxx - sx*sx + if det == 0 { + return nil, fmt.Errorf("невозможно аппроксимировать") + } + a := (sy*sxx - sx*sxy) / det + b := (n*sxy - sx*sy) / det + return []float64{a, b}, nil + }, + } + coef, err := approx.Approximate(points) + if err != nil { + return nil, err + } + approx.Coefficients = coef + return &approx, nil +} + +func NewPoly2(points []Point) (*ApproxFunc, error) { + approx := ApproxFunc{ + Name: "Полином 2-й степени", + Func: func(x float64, c []float64) float64 { + return c[0] + c[1]*x + c[2]*x*x + }, + Approximate: polyApprox(2), + } + coef, err := approx.Approximate(points) + if err != nil { + return nil, err + } + approx.Coefficients = coef + return &approx, nil +} + +func NewPoly3(points []Point) (*ApproxFunc, error) { + approx := ApproxFunc{ + Name: "Полином 3-й степени", + Func: func(x float64, c []float64) float64 { + return c[0] + c[1]*x + c[2]*x*x + c[3]*x*x*x + }, + Approximate: polyApprox(3), + } + coef, err := approx.Approximate(points) + if err != nil { + return nil, err + } + approx.Coefficients = coef + return &approx, nil +} + +func NewPower(points []Point) (*ApproxFunc, error) { + approx := ApproxFunc{ + Name: "Степенная", + Func: func(x float64, c []float64) float64 { + return c[0] * math.Pow(x, c[1]) + }, + Approximate: func(points []Point) ([]float64, error) { + var sumLnX, sumLnY, sumLnXLnX, sumLnXLnY float64 + n := float64(len(points)) + for _, p := range points { + if p.X <= 0 || p.Y <= 0 { + return nil, fmt.Errorf("отрицательные значения для логарифма") + } + lnx := math.Log(p.X) + lny := math.Log(p.Y) + sumLnX += lnx + sumLnY += lny + sumLnXLnX += lnx * lnx + sumLnXLnY += lnx * lny + } + b := (n*sumLnXLnY - sumLnX*sumLnY) / (n*sumLnXLnX - sumLnX*sumLnX) + a := math.Exp((sumLnY - b*sumLnX) / n) + return []float64{a, b}, nil + }, + } + coef, err := approx.Approximate(points) + if err != nil { + return nil, err + } + approx.Coefficients = coef + return &approx, nil +} + +func NewExp(points []Point) (*ApproxFunc, error) { + approx := ApproxFunc{ + Name: "Экспоненциальная", + Func: func(x float64, c []float64) float64 { + return c[0] * math.Exp(c[1]*x) + }, + Approximate: func(points []Point) ([]float64, error) { + var sx, sy, sxx, sxy float64 + n := float64(len(points)) + for _, p := range points { + if p.Y <= 0 { + return nil, fmt.Errorf("Y <= 0 для логарифма") + } + lnY := math.Log(p.Y) + sx += p.X + sy += lnY + sxx += p.X * p.X + sxy += p.X * lnY + } + det := n*sxx - sx*sx + b := (n*sxy - sx*sy) / det + a := math.Exp((sy - b*sx) / n) + return []float64{a, b}, nil + }, + } + coef, err := approx.Approximate(points) + if err != nil { + return nil, err + } + approx.Coefficients = coef + return &approx, nil +} + +func NewLog(points []Point) (*ApproxFunc, error) { + approx := ApproxFunc{ + Name: "Логарифмическая", + Func: func(x float64, c []float64) float64 { + return c[0] + c[1]*math.Log(x) + }, + Approximate: func(points []Point) ([]float64, error) { + var sx, sy, sxx, sxy float64 + n := float64(len(points)) + for _, p := range points { + if p.X <= 0 { + return nil, fmt.Errorf("X <= 0 для логарифма") + } + lnX := math.Log(p.X) + sx += lnX + sy += p.Y + sxx += lnX * lnX + sxy += lnX * p.Y + } + det := n*sxx - sx*sx + b := (n*sxy - sx*sy) / det + a := (sy - b*sx) / n + return []float64{a, b}, nil + }, + } + coef, err := approx.Approximate(points) + if err != nil { + return nil, err + } + approx.Coefficients = coef + return &approx, nil +} + +func polyApprox(degree int) func([]Point) ([]float64, error) { + return func(points []Point) ([]float64, error) { + A := make([][]float64, degree+1) + B := make([]float64, degree+1) + for i := range A { + A[i] = make([]float64, degree+1) + for j := range A[i] { + for _, p := range points { + A[i][j] += math.Pow(p.X, float64(i+j)) + } + } + for _, p := range points { + B[i] += math.Pow(p.X, float64(i)) * p.Y + } + } + return gauss(A, B) + } +} + +func gauss(A [][]float64, B []float64) ([]float64, error) { + n := len(B) + for i := 0; i < n; i++ { + max := math.Abs(A[i][i]) + maxRow := i + for k := i + 1; k < n; k++ { + if math.Abs(A[k][i]) > max { + max = math.Abs(A[k][i]) + maxRow = k + } + } + A[i], A[maxRow] = A[maxRow], A[i] + B[i], B[maxRow] = B[maxRow], B[i] + + for k := i + 1; k < n; k++ { + c := A[k][i] / A[i][i] + for j := i; j < n; j++ { + A[k][j] -= c * A[i][j] + } + B[k] -= c * B[i] + } + } + + x := make([]float64, n) + for i := n - 1; i >= 0; i-- { + x[i] = B[i] + for j := i + 1; j < n; j++ { + x[i] -= A[i][j] * x[j] + } + x[i] /= A[i][i] + } + return x, nil +} diff --git "a/\320\2403212/medvedev_409111/lab4/go.mod" "b/\320\2403212/medvedev_409111/lab4/go.mod" new file mode 100644 index 0000000..06ee171 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab4/go.mod" @@ -0,0 +1,20 @@ +module Lab_4 + +go 1.23.0 + +toolchain go1.23.6 + +require ( + codeberg.org/go-fonts/liberation v0.5.0 // indirect + codeberg.org/go-latex/latex v0.1.0 // indirect + codeberg.org/go-pdf/fpdf v0.10.0 // indirect + git.sr.ht/~sbinet/gg v0.6.0 // indirect + github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b // indirect + github.com/campoy/embedmd v1.0.0 // indirect + github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/image v0.25.0 // indirect + golang.org/x/text v0.23.0 // indirect + gonum.org/v1/plot v0.16.0 // indirect + rsc.io/pdf v0.1.1 // indirect +) diff --git "a/\320\2403212/medvedev_409111/lab4/go.sum" "b/\320\2403212/medvedev_409111/lab4/go.sum" new file mode 100644 index 0000000..a926441 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab4/go.sum" @@ -0,0 +1,51 @@ +codeberg.org/go-fonts/liberation v0.5.0 h1:SsKoMO1v1OZmzkG2DY+7ZkCL9U+rrWI09niOLfQ5Bo0= +codeberg.org/go-fonts/liberation v0.5.0/go.mod h1:zS/2e1354/mJ4pGzIIaEtm/59VFCFnYC7YV6YdGl5GU= +codeberg.org/go-latex/latex v0.1.0 h1:hoGO86rIbWVyjtlDLzCqZPjNykpWQ9YuTZqAzPcfL3c= +codeberg.org/go-latex/latex v0.1.0/go.mod h1:LA0q/AyWIYrqVd+A9Upkgsb+IqPcmSTKc9Dny04MHMw= +codeberg.org/go-pdf/fpdf v0.10.0 h1:u+w669foDDx5Ds43mpiiayp40Ov6sZalgcPMDBcZRd4= +codeberg.org/go-pdf/fpdf v0.10.0/go.mod h1:Y0DGRAdZ0OmnZPvjbMp/1bYxmIPxm0ws4tfoPOc4LjU= +git.sr.ht/~sbinet/gg v0.6.0 h1:RIzgkizAk+9r7uPzf/VfbJHBMKUr0F5hRFxTUGMnt38= +git.sr.ht/~sbinet/gg v0.6.0/go.mod h1:uucygbfC9wVPQIfrmwM2et0imr8L7KQWywX0xpFMm94= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= +github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= +github.com/campoy/embedmd v1.0.0 h1:V4kI2qTJJLf4J29RzI/MAt2c3Bl4dQSYPuflzwFH2hY= +github.com/campoy/embedmd v1.0.0/go.mod h1:oxyr9RCiSXg0M3VJ3ks0UGfp98BpSSGr0kpiX3MzVl8= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ= +golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/plot v0.16.0 h1:dK28Qx/Ky4VmPUN/2zeW0ELyM6ucDnBAj5yun7M9n1g= +gonum.org/v1/plot v0.16.0/go.mod h1:Xz6U1yDMi6Ni6aaXILqmVIb6Vro8E+K7Q/GeeH+Pn0c= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git "a/\320\2403212/medvedev_409111/lab4/graphic.go" "b/\320\2403212/medvedev_409111/lab4/graphic.go" new file mode 100644 index 0000000..1e2d2d3 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab4/graphic.go" @@ -0,0 +1,45 @@ +package main + +import ( + "bufio" + "gonum.org/v1/plot" + "gonum.org/v1/plot/plotter" + "gonum.org/v1/plot/plotutil" + "gonum.org/v1/plot/vg" +) + +func DrawApproximations(points []Point, approximations []*ApproxFunc, filename string, writer *bufio.Writer) error { + p := plot.New() + p.Title.Text = "Аппроксимации" + p.X.Label.Text = "X" + p.Y.Label.Text = "Y" + pts := make(plotter.XYs, len(points)) + for i := range points { + pts[i].X = points[i].X + pts[i].Y = points[i].Y + } + scatter, _ := plotter.NewScatter(pts) + scatter.GlyphStyle.Radius = vg.Points(3) + p.Add(scatter) + p.Legend.Add("Эксперимент", scatter) + addFunc := func(name string, f func(float64, []float64) float64, coeffs []float64, colorIdx int) { + line := plotter.NewFunction(func(x float64) float64 { return f(x, coeffs) }) + line.Width = vg.Points(1) + line.Color = plotutil.Color(colorIdx) + p.Add(line) + p.Legend.Add(name, line) + } + for idx, approx := range approximations { + coeffs, err := approx.Approximate(points) + if err != nil { + _, err = writer.WriteString(err.Error()) + if err != nil { + return err + } + continue + } + approx.Coefficients = coeffs + addFunc(approx.Name, approx.Func, coeffs, idx) + } + return p.Save(8*vg.Inch, 6*vg.Inch, filename) +} diff --git "a/\320\2403212/medvedev_409111/lab4/input_output.go" "b/\320\2403212/medvedev_409111/lab4/input_output.go" new file mode 100644 index 0000000..98632e7 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab4/input_output.go" @@ -0,0 +1,140 @@ +package main + +import ( + "bufio" + "fmt" + "strconv" + "strings" +) + +func ReadIntervals(reader *bufio.Reader, writer *bufio.Writer, isOutFile bool) (int, error) { + if !isOutFile { + _, err := writer.WriteString("Введите количество точек от 8 до 12: ") + err = writer.Flush() + if err != nil { + return -1, err + } + } + data, err := reader.ReadString('\n') + if err != nil { + return -1, err + } + number, err := strconv.Atoi(strings.TrimSpace(data)) + if err != nil { + return -1, err + } + if number > 12 || number < 8 { + return -1, fmt.Errorf("Число не входит в указанный интервал") + } + return number, nil +} + +func ReadPoints(reader *bufio.Reader, writer *bufio.Writer, isOutFile bool, intervalsNumber int) ([]Point, error) { + if !isOutFile { + _, err := writer.WriteString("Введите x и y через пробел:\n") + err = writer.Flush() + if err != nil { + return nil, err + } + } + var line string + var splitline []string + var err error + var x, y float64 + answer := make([]Point, intervalsNumber) + for i := 0; i < intervalsNumber; i++ { + line, err = reader.ReadString('\n') + if err != nil { + return nil, err + } + splitline = strings.Split(strings.TrimSpace(line), " ") + if len(splitline) != 2 { + return nil, fmt.Errorf("Неверное количество аргументов") + } + x, err = strconv.ParseFloat(strings.TrimSpace(splitline[0]), 64) + if err != nil { + return nil, err + } + y, err = strconv.ParseFloat(strings.TrimSpace(splitline[1]), 64) + if err != nil { + return nil, err + } + answer[i] = Point{x, y} + } + return answer, nil +} + +func PrintFuncInfo(writer *bufio.Writer, points []Point, approximate *ApproxFunc) error { + _, err := writer.WriteString(approximate.Name + ":\n") + err = writer.Flush() + if err != nil { + return err + } + _, err = writer.WriteString("Коэффициенты:\n") + err = writer.Flush() + if err != nil { + return err + } + for _, coef := range approximate.Coefficients { + _, err = writer.WriteString(fmt.Sprintf("%v\n", coef)) + if err != nil { + return err + } + } + _, err = writer.WriteString(fmt.Sprintf("СКО: %v\n", CalcStdDeviation(points, approximate.Func, approximate.Coefficients))) + err = writer.Flush() + if err != nil { + return err + } + _, err = writer.WriteString("x_i, y_i, fi(x_i), eps_i\n") + err = writer.Flush() + if err != nil { + return err + } + for _, point := range points { + _, err = writer.WriteString(fmt.Sprintf("%v, %v, %v, %v\n", point.X, point.Y, approximate.Func(point.X, approximate.Coefficients), approximate.Func(point.X, approximate.Coefficients)-point.Y)) + err = writer.Flush() + if err != nil { + return err + } + } + if approximate.Name == "Линейная" { + _, err = writer.WriteString(fmt.Sprintf("Коэффициент Пирсона: %v\n", PearsonCorrelation(points))) + err = writer.Flush() + if err != nil { + return err + } + } + det := CalcDetermination(points, approximate.Func, approximate.Coefficients) + _, err = writer.WriteString(fmt.Sprintf("Коэффицент детерминации: %v\n", det)) + err = writer.Flush() + if err != nil { + return err + } + if det >= 0.95 { + _, err = writer.WriteString("Высокая точность аппроксимации\n") + err = writer.Flush() + if err != nil { + return err + } + } else if det >= 0.75 { + _, err = writer.WriteString("Удовлетворительная точность аппроксимации\n") + err = writer.Flush() + if err != nil { + return err + } + } else if det >= 0.5 { + _, err = writer.WriteString("Слабая точность аппроксимации\n") + err = writer.Flush() + if err != nil { + return err + } + } else { + _, err = writer.WriteString("Недостаточная точность аппроксимации\n") + err = writer.Flush() + if err != nil { + return err + } + } + return nil +} diff --git "a/\320\2403212/medvedev_409111/lab4/main.go" "b/\320\2403212/medvedev_409111/lab4/main.go" new file mode 100644 index 0000000..f8ae478 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab4/main.go" @@ -0,0 +1,175 @@ +package main + +import ( + "bufio" + "fmt" + "os" +) + +func main() { + reader, inFile, err := getReader() + if err != nil { + fmt.Println(err) + return + } + if inFile != nil { + defer inFile.Close() + } + writer, outFile, err := getWriter() + if err != nil { + fmt.Println(err) + return + } + if outFile != nil { + defer outFile.Close() + } + defer writer.Flush() + intNumber, err := ReadIntervals(reader, writer, outFile != nil) + if err != nil { + fmt.Println(err) + return + } + points, err := ReadPoints(reader, writer, outFile != nil, intNumber) + if err != nil { + fmt.Println(err.Error() + "\n") + return + } + approximations := []*ApproxFunc{} + exp, err := NewExp(points) + if err != nil { + _, err = writer.WriteString(err.Error() + "\n") + if err != nil { + fmt.Println(err) + } + } else { + approximations = append(approximations, exp) + } + log, err := NewLog(points) + if err != nil { + _, err = writer.WriteString(err.Error() + "\n") + if err != nil { + fmt.Println(err) + } + } else { + approximations = append(approximations, log) + } + lin, err := NewLinear(points) + if err != nil { + _, err = writer.WriteString(err.Error() + "\n") + if err != nil { + fmt.Println(err) + } + } else { + approximations = append(approximations, lin) + } + poly2, err := NewPoly2(points) + if err != nil { + _, err = writer.WriteString(err.Error() + "\n") + if err != nil { + fmt.Println(err) + } + } else { + approximations = append(approximations, poly2) + } + power, err := NewPower(points) + if err != nil { + _, err = writer.WriteString(err.Error() + "\n") + if err != nil { + fmt.Println(err) + } + } else { + approximations = append(approximations, power) + } + poly3, err := NewPoly3(points) + if err != nil { + _, err = writer.WriteString(err.Error() + "\n") + if err != nil { + fmt.Println(err) + } + } else { + approximations = append(approximations, poly3) + } + err = DrawApproximations(points, approximations, "out.png", writer) + if err != nil { + fmt.Println(err) + return + } + for _, appr := range approximations { + err = PrintFuncInfo(writer, points, appr) + if err != nil { + fmt.Println(err) + return + } + } + least, appr := GetBestApproximation(points, approximations) + _, err = writer.WriteString(fmt.Sprintf("Наименьшей S является: %v\n", least)) + if err != nil { + fmt.Println(err) + return + } + writer.Flush() + _, err = writer.WriteString("Ею обладает: ") + if err != nil { + fmt.Println(err) + return + } + writer.Flush() + for _, approx := range appr { + _, err = writer.WriteString(approx.Name + "\n") + if err != nil { + fmt.Println(err) + return + } + writer.Flush() + } +} + +func getReader() (*bufio.Reader, *os.File, error) { + var line string + stdin := bufio.NewReader(os.Stdin) + fmt.Print("Введите любой символ, если хотите ввести данные из файла: ") + line, err := stdin.ReadString('\n') + line = line[:len(line)-1] + if err != nil { + return nil, nil, err + } + if line == "" { + return bufio.NewReader(stdin), nil, nil + } + fmt.Print("Введите название файла: ") + line, err = stdin.ReadString('\n') + line = line[:len(line)-1] + if err != nil { + return nil, nil, err + } + file, err := os.Open(line) + if err != nil { + return nil, nil, err + } + return bufio.NewReader(file), file, nil +} + +func getWriter() (*bufio.Writer, *os.File, error) { + var line string + stdin := bufio.NewReader(os.Stdin) + fmt.Print("Введите любой символ, если хотите перенаправить вывод в файл: ") + line, err := stdin.ReadString('\n') + line = line[:len(line)-1] + if err != nil { + return nil, nil, err + } + if line == "" { + return bufio.NewWriter(os.Stdout), nil, nil + } + fmt.Print("Введите название файла: ") + line, err = stdin.ReadString('\n') + line = line[:len(line)-1] + if err != nil { + return nil, nil, err + } + file, err := os.Create(line) + if err != nil { + return nil, nil, err + } + return bufio.NewWriter(file), file, nil +} diff --git "a/\320\2403212/medvedev_409111/lab4/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2264.pdf" "b/\320\2403212/medvedev_409111/lab4/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2264.pdf" new file mode 100644 index 0000000..752a73d Binary files /dev/null and "b/\320\2403212/medvedev_409111/lab4/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2264.pdf" differ diff --git "a/\320\2403212/medvedev_409111/lab4/utils.go" "b/\320\2403212/medvedev_409111/lab4/utils.go" new file mode 100644 index 0000000..734f2f3 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab4/utils.go" @@ -0,0 +1,74 @@ +package main + +import ( + "math" + "sort" +) + +func CalcStdDeviation(points []Point, f func(float64, []float64) float64, coeffs []float64) float64 { + var s float64 + for _, p := range points { + yPred := f(p.X, coeffs) + s += math.Pow(p.Y-yPred, 2) + } + return math.Sqrt(s / float64(len(points))) +} + +func CalcDetermination(points []Point, f func(float64, []float64) float64, coeffs []float64) float64 { + var sTot, sRes float64 + var meanY float64 + for _, p := range points { + meanY += p.Y + } + meanY /= float64(len(points)) + + for _, p := range points { + yPred := f(p.X, coeffs) + sTot += math.Pow(p.Y-meanY, 2) + sRes += math.Pow(p.Y-yPred, 2) + } + return 1 - (sRes / sTot) +} + +func PearsonCorrelation(points []Point) float64 { + var sumX, sumY float64 + n := float64(len(points)) + for _, p := range points { + sumX += p.X + sumY += p.Y + } + meanX := sumX / n + meanY := sumY / n + var num, denomX, denomY float64 + for _, p := range points { + dx := p.X - meanX + dy := p.Y - meanY + num += dx * dy + denomX += dx * dx + denomY += dy * dy + } + if denomX == 0 || denomY == 0 { + return 0 + } + return num / math.Sqrt(denomX*denomY) +} + +func LeastSquaresMethod(points []Point, approximate *ApproxFunc) float64 { + sum := 0.0 + for _, point := range points { + sum += math.Pow(approximate.Func(point.X, approximate.Coefficients)-point.Y, 2.0) + } + return sum +} + +func GetBestApproximation(points []Point, approximations []*ApproxFunc) (float64, []*ApproxFunc) { + mp := make(map[float64][]*ApproxFunc) + keys := []float64{} + for _, appr := range approximations { + num := LeastSquaresMethod(points, appr) + mp[num] = append(mp[num], appr) + keys = append(keys, num) + } + sort.Float64s(keys) + return keys[0], mp[keys[0]] +} diff --git "a/\320\2403212/medvedev_409111/lab5/go.mod" "b/\320\2403212/medvedev_409111/lab5/go.mod" new file mode 100644 index 0000000..c3ca06b --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab5/go.mod" @@ -0,0 +1,20 @@ +module Lab_5 + +go 1.23.0 + +toolchain go1.23.6 + +require ( + codeberg.org/go-fonts/liberation v0.5.0 // indirect + codeberg.org/go-latex/latex v0.1.0 // indirect + codeberg.org/go-pdf/fpdf v0.10.0 // indirect + git.sr.ht/~sbinet/gg v0.6.0 // indirect + github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b // indirect + github.com/campoy/embedmd v1.0.0 // indirect + github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/image v0.25.0 // indirect + golang.org/x/text v0.23.0 // indirect + gonum.org/v1/plot v0.16.0 // indirect + rsc.io/pdf v0.1.1 // indirect +) diff --git "a/\320\2403212/medvedev_409111/lab5/go.sum" "b/\320\2403212/medvedev_409111/lab5/go.sum" new file mode 100644 index 0000000..a926441 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab5/go.sum" @@ -0,0 +1,51 @@ +codeberg.org/go-fonts/liberation v0.5.0 h1:SsKoMO1v1OZmzkG2DY+7ZkCL9U+rrWI09niOLfQ5Bo0= +codeberg.org/go-fonts/liberation v0.5.0/go.mod h1:zS/2e1354/mJ4pGzIIaEtm/59VFCFnYC7YV6YdGl5GU= +codeberg.org/go-latex/latex v0.1.0 h1:hoGO86rIbWVyjtlDLzCqZPjNykpWQ9YuTZqAzPcfL3c= +codeberg.org/go-latex/latex v0.1.0/go.mod h1:LA0q/AyWIYrqVd+A9Upkgsb+IqPcmSTKc9Dny04MHMw= +codeberg.org/go-pdf/fpdf v0.10.0 h1:u+w669foDDx5Ds43mpiiayp40Ov6sZalgcPMDBcZRd4= +codeberg.org/go-pdf/fpdf v0.10.0/go.mod h1:Y0DGRAdZ0OmnZPvjbMp/1bYxmIPxm0ws4tfoPOc4LjU= +git.sr.ht/~sbinet/gg v0.6.0 h1:RIzgkizAk+9r7uPzf/VfbJHBMKUr0F5hRFxTUGMnt38= +git.sr.ht/~sbinet/gg v0.6.0/go.mod h1:uucygbfC9wVPQIfrmwM2et0imr8L7KQWywX0xpFMm94= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= +github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= +github.com/campoy/embedmd v1.0.0 h1:V4kI2qTJJLf4J29RzI/MAt2c3Bl4dQSYPuflzwFH2hY= +github.com/campoy/embedmd v1.0.0/go.mod h1:oxyr9RCiSXg0M3VJ3ks0UGfp98BpSSGr0kpiX3MzVl8= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ= +golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/plot v0.16.0 h1:dK28Qx/Ky4VmPUN/2zeW0ELyM6ucDnBAj5yun7M9n1g= +gonum.org/v1/plot v0.16.0/go.mod h1:Xz6U1yDMi6Ni6aaXILqmVIb6Vro8E+K7Q/GeeH+Pn0c= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git "a/\320\2403212/medvedev_409111/lab5/graphic.go" "b/\320\2403212/medvedev_409111/lab5/graphic.go" new file mode 100644 index 0000000..e29c3f1 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab5/graphic.go" @@ -0,0 +1,102 @@ +package main + +import ( + "fmt" + "gonum.org/v1/plot" + "gonum.org/v1/plot/plotter" + "gonum.org/v1/plot/plotutil" + "gonum.org/v1/plot/vg" + "gonum.org/v1/plot/vg/draw" +) + +func DrawGraphic(points []Point, x, lagrange, newton, gauss float64, filename string) error { + p := plot.New() + p.Title.Text = "Интерполяция функции" + p.X.Label.Text = "X" + p.Y.Label.Text = "Y" + pts := make(plotter.XYs, len(points)) + for i, pt := range points { + pts[i].X = pt.X + pts[i].Y = pt.Y + } + scatter, err := plotter.NewScatter(pts) + if err != nil { + return err + } + scatter.GlyphStyle.Color = plotutil.Color(4) + scatter.GlyphStyle.Radius = vg.Points(3) + scatter.GlyphStyle.Shape = draw.CircleGlyph{} + p.Add(scatter) + p.Legend.Add("Исходные точки", scatter) + minX, maxX := points[0].X, points[len(points)-1].X + nPoints := 100 + step := (maxX - minX) / float64(nPoints-1) + lagrangePts := make(plotter.XYs, nPoints) + for i := 0; i < nPoints; i++ { + xVal := minX + float64(i)*step + lagrangePts[i].X = xVal + lagrangePts[i].Y = LagrangeInterpolation(points, xVal) + } + lagrangeLine, err := plotter.NewLine(lagrangePts) + if err != nil { + return err + } + lagrangeLine.Color = plotutil.Color(1) + p.Add(lagrangeLine) + p.Legend.Add("Лагранж", lagrangeLine) + newtonPts := make(plotter.XYs, nPoints) + for i := 0; i < nPoints; i++ { + xVal := minX + float64(i)*step + newtonPts[i].X = xVal + newtonPts[i].Y = NewtonInterpolation(points, xVal) + } + newtonLine, err := plotter.NewLine(newtonPts) + if err != nil { + return err + } + newtonLine.Color = plotutil.Color(2) + p.Add(newtonLine) + p.Legend.Add("Ньютон", newtonLine) + gaussPts := make(plotter.XYs, nPoints) + for i := 0; i < nPoints; i++ { + xVal := minX + float64(i)*step + gaussPts[i].X = xVal + gaussPts[i].Y = GaussInterpolation(points, xVal) + } + gaussLine, err := plotter.NewLine(gaussPts) + if err != nil { + return err + } + gaussLine.Color = plotutil.Color(3) + p.Add(gaussLine) + p.Legend.Add("Гаусс", gaussLine) + lagrangeScatter, err := plotter.NewScatter(plotter.XYs{{X: x, Y: lagrange}}) + if err != nil { + return err + } + lagrangeScatter.GlyphStyle.Color = plotutil.Color(1) + lagrangeScatter.GlyphStyle.Shape = draw.CircleGlyph{} + lagrangeScatter.GlyphStyle.Radius = vg.Points(4) + p.Add(lagrangeScatter) + p.Legend.Add(fmt.Sprintf("Лагранж (x=%v)", x), lagrangeScatter) + newtonScatter, err := plotter.NewScatter(plotter.XYs{{X: x, Y: newton}}) + if err != nil { + return err + } + newtonScatter.GlyphStyle.Color = plotutil.Color(2) + newtonScatter.GlyphStyle.Shape = draw.SquareGlyph{} + newtonScatter.GlyphStyle.Radius = vg.Points(4) + p.Add(newtonScatter) + p.Legend.Add(fmt.Sprintf("Ньютон (x=%v)", x), newtonScatter) + gaussScatter, err := plotter.NewScatter(plotter.XYs{{X: x, Y: gauss}}) + if err != nil { + return err + } + gaussScatter.GlyphStyle.Color = plotutil.Color(3) + gaussScatter.GlyphStyle.Shape = draw.TriangleGlyph{} + gaussScatter.GlyphStyle.Radius = vg.Points(6) + p.Add(gaussScatter) + p.Legend.Add(fmt.Sprintf("Гаусс (x=%v)", x), gaussScatter) + err = p.Save(10*vg.Inch, 6*vg.Inch, filename) + return err +} diff --git "a/\320\2403212/medvedev_409111/lab5/input.go" "b/\320\2403212/medvedev_409111/lab5/input.go" new file mode 100644 index 0000000..8ee4a55 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab5/input.go" @@ -0,0 +1,149 @@ +package main + +import ( + "bufio" + "fmt" + "sort" + "strconv" + "strings" +) + +func GetPoints(reader *bufio.Reader, isFile bool) ([]Point, error) { + if !isFile { + fmt.Print("Введите 1, если хотите задать функцию таблицей и 2, если хотите выбрать из предложенных: ") + } + line, err := reader.ReadString('\n') + if err != nil { + return nil, fmt.Errorf("Ошибка при чтении данных: ", err) + } + line = strings.TrimSpace(line) + switch line { + case "1": + return ReadTable(reader, isFile) + case "2": + return ReadReadyFunction(reader, isFile) + default: + return nil, fmt.Errorf("Некорректный ввод.") + } +} + +func GetX(reader *bufio.Reader, isFile bool) (float64, error) { + if !isFile { + fmt.Print("Введите значение X для интерполяции: ") + } + line, err := reader.ReadString('\n') + if err != nil { + return -1.0, fmt.Errorf("Ошибка при чтении данных: ", err) + } + ans, err := strconv.ParseFloat(strings.TrimSpace(line), 64) + if err != nil { + return -1.0, fmt.Errorf("Ошибка при чтении кординат точки: ", err) + } + return ans, nil +} + +func ReadTable(reader *bufio.Reader, isFile bool) ([]Point, error) { + if !isFile { + fmt.Print("Введите количество точек: ") + } + line, err := reader.ReadString('\n') + if err != nil { + return nil, fmt.Errorf("Ошибка при чтении данных: ", err) + } + number, err := strconv.Atoi(strings.TrimSpace(line)) + if err != nil { + return nil, fmt.Errorf("Ошибка при вводе количества точек: ", err) + } + if !isFile { + fmt.Println("Введите значения x и y через пробел в каждой отдельной строке: ") + } + ans := make([]Point, number) + for i := 0; i < number; i++ { + line, err = reader.ReadString('\n') + if err != nil { + return nil, fmt.Errorf("Ошибка при чтении данных: ", err) + } + splitline := strings.Split(line, " ") + if len(splitline) != 2 { + return nil, fmt.Errorf("Неверное количество аргументов при вводе точки") + } + ans[i].X, err = strconv.ParseFloat(strings.TrimSpace(splitline[0]), 64) + if err != nil { + return nil, fmt.Errorf("Ошибка при чтении кординат точки: ", err) + } + ans[i].Y, err = strconv.ParseFloat(strings.TrimSpace(splitline[1]), 64) + if err != nil { + return nil, fmt.Errorf("Ошибка при чтении кординат точки: ", err) + } + } + sort.Slice(ans, func(i, j int) bool { + return ans[i].X < ans[j].X + }) + return ans, nil +} + +func ReadReadyFunction(reader *bufio.Reader, isFile bool) ([]Point, error) { + if !isFile { + fmt.Println("Выберите функцию: ") + descMap := GetFuncsDescription() + for key, _ := range descMap { + fmt.Printf("%v - %v\n", key, descMap[key]) + } + } + line, err := reader.ReadString('\n') + if err != nil { + return nil, fmt.Errorf("Ошибка при выборе функции: ", err) + } + line = strings.TrimSpace(line) + fn, ok := GetFuncs()[line] + if !ok { + return nil, fmt.Errorf("Некорректно указана функция") + } + if !isFile { + fmt.Println("Укажите начало и конец интервала через пробел: ") + } + line, err = reader.ReadString('\n') + if err != nil { + return nil, fmt.Errorf("Ошибка при чтении данных: ", err) + } + splitline := strings.Split(line, " ") + if len(splitline) != 2 { + return nil, fmt.Errorf("Неверное количество аргументов при вводе интервала") + } + start, err := strconv.ParseFloat(strings.TrimSpace(splitline[0]), 64) + if err != nil { + return nil, fmt.Errorf("Ошибка при чтении начала интервала: ", err) + } + end, err := strconv.ParseFloat(strings.TrimSpace(splitline[1]), 64) + if err != nil { + return nil, fmt.Errorf("Ошибка при чтении конца интервала: ", err) + } + if end <= start { + return nil, fmt.Errorf("Интервал введен некорректно") + } + if !isFile { + fmt.Print("Введите количество точек: ") + } + line, err = reader.ReadString('\n') + if err != nil { + return nil, fmt.Errorf("Ошибка при чтении данных: ", err) + } + number, err := strconv.Atoi(strings.TrimSpace(line)) + if err != nil { + return nil, fmt.Errorf("Ошибка при чтении количества точек: ", err) + } + if number < 2 { + return nil, fmt.Errorf("Некорректное значение для количества точек (должно быть минимум 2).") + } + ans := make([]Point, number) + for i := 0; i < number-1; i++ { + ans[i].X = float64(start) + float64(end-start)/float64(number-1)*float64(i) + ans[i].Y = fn(ans[i].X) + } + ans[number-1].X = end + ans[number-1].Y = fn(ans[number-1].X) + sort.Slice(ans, func(i, j int) bool { + return ans[i].X < ans[j].X + }) + return ans, nil +} diff --git "a/\320\2403212/medvedev_409111/lab5/interpolation.go" "b/\320\2403212/medvedev_409111/lab5/interpolation.go" new file mode 100644 index 0000000..b44bf2f --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab5/interpolation.go" @@ -0,0 +1,57 @@ +package main + +func LagrangeInterpolation(points []Point, x float64) float64 { + ans := 0.0 + for i := 0; i < len(points); i++ { + curr := points[i].Y + for j := 0; j < len(points); j++ { + if i != j { + curr *= (x - points[j].X) / (points[i].X - points[j].X) + } + } + ans += curr + } + return ans +} + +func NewtonInterpolation(points []Point, x float64) float64 { + table := DividedDifferences(points) + ans := table[0][0] + curr := 1.0 + for i := 1; i < len(points); i++ { + curr *= (x - points[i-1].X) + ans += table[0][i] * curr + } + return ans +} + +func GaussInterpolation(points []Point, x0 float64) float64 { + h := points[1].X - points[0].X + t := (x0 - points[len(points)/2].X) / h + table := FiniteDifferences(points) + ans := table[len(points)/2][0] + curr := 1.0 + fact := 1.0 + isForward := x0 >= points[len(points)/2].X + for i := 1; i < len(points); i++ { + var idx int + fact *= float64(i) + if isForward { + if i%2 == 1 { + curr *= (t + float64(i/2)) + } else { + curr *= (t - float64(i/2)) + } + idx = len(points)/2 - (i / 2) + } else { + if i%2 == 1 { + curr *= (t - float64(i/2)) + } else { + curr *= (t + float64(i/2)) + } + idx = len(points)/2 - ((i + 1) / 2) + } + ans += curr * table[idx][i] / fact + } + return ans +} diff --git "a/\320\2403212/medvedev_409111/lab5/main.go" "b/\320\2403212/medvedev_409111/lab5/main.go" new file mode 100644 index 0000000..e87fb31 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab5/main.go" @@ -0,0 +1,81 @@ +package main + +import ( + "bufio" + "fmt" + "os" +) + +func main() { + isFile := false + reader, inFile, err := getReader() + if err != nil { + fmt.Println(err) + return + } + if inFile != nil { + defer inFile.Close() + isFile = true + } + points, err := GetPoints(reader, isFile) + if err != nil { + fmt.Println(err) + return + } + table := FiniteDifferences(points) + fmt.Println("\nТаблица конечных разностей:") + fmt.Printf("%10s %10s", "x", "y") + for i := 1; i < len(table); i++ { + fmt.Printf(" %12s", fmt.Sprintf("Δ^%d", i)) + } + fmt.Println() + for i := 0; i < len(table); i++ { + fmt.Printf("%10.4f %10.4f", points[i].X, points[i].Y) + for j := 1; j < len(table)-i; j++ { + fmt.Printf(" %12.6f", table[i][j]) + } + fmt.Println() + } + x, err := GetX(reader, isFile) + if err != nil { + fmt.Println(err) + return + } + lagrange := LagrangeInterpolation(points, x) + newton := NewtonInterpolation(points, x) + gauss := GaussInterpolation(points, x) + fmt.Printf("Результаты интерполяции для x = %v\n", x) + fmt.Printf("Интерполяция по Лагранжу: %v\n", lagrange) + fmt.Printf("Интерполяция по Ньютону с разельными суммами: %v\n", newton) + fmt.Printf("Интерполяция по Гауссу: %v\n", gauss) + err = DrawGraphic(points, x, lagrange, newton, gauss, "out.png") + if err != nil { + fmt.Println(err) + return + } +} + +func getReader() (*bufio.Reader, *os.File, error) { + var line string + stdin := bufio.NewReader(os.Stdin) + fmt.Print("Введите любой символ, если хотите ввести данные из файла: ") + line, err := stdin.ReadString('\n') + line = line[:len(line)-1] + if err != nil { + return nil, nil, err + } + if line == "" { + return bufio.NewReader(stdin), nil, nil + } + fmt.Print("Введите название файла: ") + line, err = stdin.ReadString('\n') + line = line[:len(line)-1] + if err != nil { + return nil, nil, err + } + file, err := os.Open(line) + if err != nil { + return nil, nil, err + } + return bufio.NewReader(file), file, nil +} diff --git "a/\320\2403212/medvedev_409111/lab5/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2265.pdf" "b/\320\2403212/medvedev_409111/lab5/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2265.pdf" new file mode 100644 index 0000000..67e9609 Binary files /dev/null and "b/\320\2403212/medvedev_409111/lab5/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2265.pdf" differ diff --git "a/\320\2403212/medvedev_409111/lab5/utils.go" "b/\320\2403212/medvedev_409111/lab5/utils.go" new file mode 100644 index 0000000..7cef40e --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab5/utils.go" @@ -0,0 +1,53 @@ +package main + +import "math" + +type Point struct { + X, Y float64 +} + +func GetFuncsDescription() map[string]string { + return map[string]string{ + "1": "sin(x)", + "2": "cos(x)", + "3": "exp(x)", + } +} + +func GetFuncs() map[string]func(float64) float64 { + return map[string]func(float64) float64{ + "1": math.Sin, + "2": math.Cos, + "3": math.Exp, + } +} + +func FiniteDifferences(points []Point) [][]float64 { + ans := make([][]float64, len(points)) + for i := range ans { + ans[i] = make([]float64, len(points)) + } + for i := 0; i < len(ans); i++ { + ans[i][0] = points[i].Y + } + for j := 1; j < len(ans); j++ { + for i := 0; i < len(ans)-j; i++ { + ans[i][j] = ans[i+1][j-1] - ans[i][j-1] + } + } + return ans +} + +func DividedDifferences(points []Point) [][]float64 { + ans := make([][]float64, len(points)) + for i := range ans { + ans[i] = make([]float64, len(points)) + ans[i][0] = points[i].Y + } + for j := 1; j < len(ans); j++ { + for i := 0; i < len(ans)-j; i++ { + ans[i][j] = (ans[i+1][j-1] - ans[i][j-1]) / (points[i+j].X - points[i].X) + } + } + return ans +} diff --git "a/\320\2403212/medvedev_409111/lab6/go.mod" "b/\320\2403212/medvedev_409111/lab6/go.mod" new file mode 100644 index 0000000..2356962 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab6/go.mod" @@ -0,0 +1,20 @@ +module Lab_6 + +go 1.23.0 + +toolchain go1.23.6 + +require ( + codeberg.org/go-fonts/liberation v0.5.0 // indirect + codeberg.org/go-latex/latex v0.1.0 // indirect + codeberg.org/go-pdf/fpdf v0.10.0 // indirect + git.sr.ht/~sbinet/gg v0.6.0 // indirect + github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b // indirect + github.com/campoy/embedmd v1.0.0 // indirect + github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + golang.org/x/image v0.25.0 // indirect + golang.org/x/text v0.23.0 // indirect + gonum.org/v1/plot v0.16.0 // indirect + rsc.io/pdf v0.1.1 // indirect +) diff --git "a/\320\2403212/medvedev_409111/lab6/go.sum" "b/\320\2403212/medvedev_409111/lab6/go.sum" new file mode 100644 index 0000000..a926441 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab6/go.sum" @@ -0,0 +1,51 @@ +codeberg.org/go-fonts/liberation v0.5.0 h1:SsKoMO1v1OZmzkG2DY+7ZkCL9U+rrWI09niOLfQ5Bo0= +codeberg.org/go-fonts/liberation v0.5.0/go.mod h1:zS/2e1354/mJ4pGzIIaEtm/59VFCFnYC7YV6YdGl5GU= +codeberg.org/go-latex/latex v0.1.0 h1:hoGO86rIbWVyjtlDLzCqZPjNykpWQ9YuTZqAzPcfL3c= +codeberg.org/go-latex/latex v0.1.0/go.mod h1:LA0q/AyWIYrqVd+A9Upkgsb+IqPcmSTKc9Dny04MHMw= +codeberg.org/go-pdf/fpdf v0.10.0 h1:u+w669foDDx5Ds43mpiiayp40Ov6sZalgcPMDBcZRd4= +codeberg.org/go-pdf/fpdf v0.10.0/go.mod h1:Y0DGRAdZ0OmnZPvjbMp/1bYxmIPxm0ws4tfoPOc4LjU= +git.sr.ht/~sbinet/gg v0.6.0 h1:RIzgkizAk+9r7uPzf/VfbJHBMKUr0F5hRFxTUGMnt38= +git.sr.ht/~sbinet/gg v0.6.0/go.mod h1:uucygbfC9wVPQIfrmwM2et0imr8L7KQWywX0xpFMm94= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= +github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= +github.com/campoy/embedmd v1.0.0 h1:V4kI2qTJJLf4J29RzI/MAt2c3Bl4dQSYPuflzwFH2hY= +github.com/campoy/embedmd v1.0.0/go.mod h1:oxyr9RCiSXg0M3VJ3ks0UGfp98BpSSGr0kpiX3MzVl8= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ= +golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/plot v0.16.0 h1:dK28Qx/Ky4VmPUN/2zeW0ELyM6ucDnBAj5yun7M9n1g= +gonum.org/v1/plot v0.16.0/go.mod h1:Xz6U1yDMi6Ni6aaXILqmVIb6Vro8E+K7Q/GeeH+Pn0c= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git "a/\320\2403212/medvedev_409111/lab6/graphic.go" "b/\320\2403212/medvedev_409111/lab6/graphic.go" new file mode 100644 index 0000000..4216ac3 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab6/graphic.go" @@ -0,0 +1,54 @@ +package main + +import ( + "gonum.org/v1/plot" + "gonum.org/v1/plot/plotter" + "gonum.org/v1/plot/plotutil" + "gonum.org/v1/plot/vg" +) + +func DrawGraphic(euler, rungeKutta, milne Diffur, filename string) error { + p := plot.New() + p.Title.Text = "Решение дифференциального уравнения" + p.X.Label.Text = "x" + p.Y.Label.Text = "y" + makeLine := func(x, y []float64) plotter.XYs { + pts := make(plotter.XYs, len(x)) + for i := range x { + pts[i].X = x[i] + pts[i].Y = y[i] + } + return pts + } + eulerLine := makeLine(euler.x, euler.y) + rkLine := makeLine(rungeKutta.x, rungeKutta.y) + milneLine := makeLine(milne.x, milne.y) + var exactLine plotter.XYs + if euler.exactFn != nil { + exactLine = make(plotter.XYs, len(euler.x)) + for i, x := range euler.x { + exactLine[i].X = x + exactLine[i].Y = euler.exactFn(x) + } + } + err := plotutil.AddLines(p, + "Эйлер", eulerLine, + "Рунге-Кутта", rkLine, + "Милн", milneLine, + ) + if err != nil { + return err + } + if euler.exactFn != nil { + exact, err := plotter.NewLine(exactLine) + if err != nil { + return err + } + exact.Color = plotutil.Color(3) + exact.Width = vg.Points(2) + exact.Dashes = []vg.Length{vg.Points(5), vg.Points(3)} + p.Add(exact) + p.Legend.Add("Точное решение", exact) + } + return p.Save(6*vg.Inch, 4*vg.Inch, filename) +} diff --git "a/\320\2403212/medvedev_409111/lab6/input_output.go" "b/\320\2403212/medvedev_409111/lab6/input_output.go" new file mode 100644 index 0000000..e19472f --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab6/input_output.go" @@ -0,0 +1,86 @@ +package main + +import ( + "fmt" + "strings" +) + +func ReadDiffurInput() (Diffur, error) { + fmt.Println("Выберите ОДУ:") + for key, _ := range fnsDescription { + fmt.Printf("%v - %v\n", key, fnsDescription[key]) + } + var fnChoice string + _, err := fmt.Scan(&fnChoice) + if err != nil { + return Diffur{}, err + } + fn, ok := fns[strings.TrimSpace(fnChoice)] + if !ok { + return Diffur{}, fmt.Errorf("Некорректно указан номер ОДУ") + } + fmt.Print("Введите y0: ") + var y0 float64 + _, err = fmt.Scan(&y0) + if err != nil { + return Diffur{}, err + } + fmt.Print("Введите интервал дифференцирования через пробел: ") + var x0, xn float64 + _, err = fmt.Scan(&x0) + if err != nil { + return Diffur{}, err + } + _, err = fmt.Scan(&xn) + if err != nil { + return Diffur{}, err + } + if x0 >= xn { + return Diffur{}, fmt.Errorf("Интервал указан некорректно") + } + exactY, err := GetExactSolutionFunction(strings.TrimSpace(fnChoice), x0, y0) + if err != nil { + return Diffur{}, err + } + fmt.Print("Введите шаг: ") + var step float64 + _, err = fmt.Scan(&step) + if err != nil { + return Diffur{}, err + } + if step > xn-x0 || step <= 0 { + return Diffur{}, fmt.Errorf("Шаг указан некорректно") + } + fmt.Print("Введите точность: ") + var accuracy float64 + _, err = fmt.Scan(&accuracy) + if err != nil { + return Diffur{}, err + } + if accuracy <= 0 { + return Diffur{}, fmt.Errorf("Точность указана некорректно") + } + return BuildDiffur(fn, exactY, getXArray(x0, xn, step), y0, accuracy), nil +} + +func getXArray(x0, xn, step float64) []float64 { + xArr := make([]float64, int((xn-x0)/step)+1) + pointer := 0 + for i := x0; i < xn; i += step { + xArr[pointer] = i + pointer++ + } + xArr[len(xArr)-1] = xn + return xArr +} + +func PrintTable(euler, rungeKutta, milne Diffur) { + fmt.Printf("%-10s %-15s %-15s %-15s\n", "x", "Эйлер", "Рунге-Кутта", "Милн") + for i := 0; i < len(euler.x); i++ { + x := euler.x[i] + yEuler := euler.y[i] + yRK := rungeKutta.y[i] + yMilne := milne.y[i] + fmt.Printf("%-10.4f %-15.8f %-15.8f %-15.8f\n", x, yEuler, yRK, yMilne) + } +} diff --git "a/\320\2403212/medvedev_409111/lab6/main.go" "b/\320\2403212/medvedev_409111/lab6/main.go" new file mode 100644 index 0000000..f84eb42 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab6/main.go" @@ -0,0 +1,45 @@ +package main + +import "fmt" + +func main() { + diffur, err := ReadDiffurInput() + if err != nil { + fmt.Println(err) + return + } + euler, err := Euler(diffur) + if err != nil { + fmt.Println(err) + return + } + accEuler, err := estimateRungeError(euler, Euler, 1.0) + if err != nil { + fmt.Println(err) + return + } + runge, err := RungeKutta4(diffur) + if err != nil { + fmt.Println(err) + return + } + accRunge, err := estimateRungeError(runge, RungeKutta4, 15.0) + if err != nil { + fmt.Println(err) + return + } + milne, accMilne, err := Milne(diffur) + if err != nil { + fmt.Println(err) + return + } + PrintTable(euler, runge, milne) + fmt.Printf("Точность для метода Эйлера: %v\n", accEuler) + fmt.Printf("Точность для метода Рунге-Кутта 4-го порядка: %v\n", accRunge) + fmt.Printf("Точность для метода Милне: %v\n", accMilne) + err = DrawGraphic(euler, runge, milne, "output.png") + if err != nil { + fmt.Println(err) + return + } +} diff --git "a/\320\2403212/medvedev_409111/lab6/model.go" "b/\320\2403212/medvedev_409111/lab6/model.go" new file mode 100644 index 0000000..c7b0a02 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab6/model.go" @@ -0,0 +1,60 @@ +package main + +import ( + "errors" + "math" +) + +var fns = map[string]func(float64, float64) float64{ + "1": func(x, y float64) float64 { + return x + y + }, + "2": func(x, y float64) float64 { + return x*x - 2*y + }, + "3": func(x, y float64) float64 { + return math.Sin(x) + y + }, +} + +var fnsDescription = map[string]string{ + "1": "x + y", + "2": "x^2 - 2y", + "3": "sin(x) + y", +} + +func GetExactSolutionFunction(eqChoice string, x0, y0 float64) (func(float64) float64, error) { + switch eqChoice { + case "1": + C := (y0 + x0 + 1) * math.Exp(-x0) + return func(x float64) float64 { + return C*math.Exp(x) - x - 1 + }, nil + case "2": + C := (y0 - (2*x0*x0-2*x0+1)/4) / math.Exp(-2*x0) + return func(x float64) float64 { + return C*math.Exp(-2*x) + (2*x*x-2*x+1)/4 + }, nil + case "3": + C := (y0 + (math.Sin(x0)+math.Cos(x0))/2) / math.Exp(x0) + return func(x float64) float64 { + return C*math.Exp(x) - (math.Sin(x)+math.Cos(x))/2 + }, nil + default: + return nil, errors.New("неизвестное уравнение") + } +} + +type Diffur struct { + fn func(float64, float64) float64 + exactFn func(float64) float64 + x []float64 + y []float64 + accuracy float64 +} + +func BuildDiffur(fn func(float64, float64) float64, exactFn func(float64) float64, x []float64, y0 float64, accuracy float64) Diffur { + y := make([]float64, len(x)) + y[0] = y0 + return Diffur{fn, exactFn, x, y, accuracy} +} diff --git "a/\320\2403212/medvedev_409111/lab6/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2266.pdf" "b/\320\2403212/medvedev_409111/lab6/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2266.pdf" new file mode 100644 index 0000000..67d70bc Binary files /dev/null and "b/\320\2403212/medvedev_409111/lab6/reports/\320\222\321\213\321\207\320\274\320\260\321\202_\342\204\2266.pdf" differ diff --git "a/\320\2403212/medvedev_409111/lab6/solution.go" "b/\320\2403212/medvedev_409111/lab6/solution.go" new file mode 100644 index 0000000..db52fc6 --- /dev/null +++ "b/\320\2403212/medvedev_409111/lab6/solution.go" @@ -0,0 +1,133 @@ +package main + +import ( + "errors" + "fmt" + "math" +) + +func Euler(d Diffur) (Diffur, error) { + h := d.x[1] - d.x[0] + result := Diffur{ + fn: d.fn, + exactFn: d.exactFn, + x: d.x, + accuracy: d.accuracy, + y: make([]float64, len(d.x)), + } + result.y[0] = d.y[0] + for i := 1; i < len(result.x); i++ { + result.y[i] = result.y[i-1] + h*d.fn(result.x[i-1], result.y[i-1]) + } + return result, nil +} + +func RungeKutta4(d Diffur) (Diffur, error) { + if len(d.x) < 2 { + return Diffur{}, errors.New("Недостаточно точек x для вычисления") + } + h := d.x[1] - d.x[0] + result := Diffur{ + fn: d.fn, + exactFn: d.exactFn, + x: d.x, + accuracy: d.accuracy, + y: make([]float64, len(d.x)), + } + result.y[0] = d.y[0] + for i := 1; i < len(result.x); i++ { + k1 := h * d.fn(result.x[i-1], result.y[i-1]) + k2 := h * d.fn(result.x[i-1]+h/2, result.y[i-1]+k1/2) + k3 := h * d.fn(result.x[i-1]+h/2, result.y[i-1]+k2/2) + k4 := h * d.fn(result.x[i-1]+h, result.y[i-1]+k3) + result.y[i] = result.y[i-1] + (k1+2*k2+2*k3+k4)/6 + } + return result, nil +} + +func Milne(d Diffur) (Diffur, float64, error) { + if len(d.x) < 5 { + return Diffur{}, 0, errors.New("Метод Милна требует минимум 5 точек") + } + h := d.x[1] - d.x[0] + result := Diffur{ + fn: d.fn, + exactFn: d.exactFn, + x: d.x, + accuracy: d.accuracy, + y: make([]float64, len(d.x)), + } + rk, err := RungeKutta4(Diffur{ + fn: d.fn, + exactFn: d.exactFn, + x: d.x[:4], + accuracy: d.accuracy, + y: d.y[:4], + }) + if err != nil { + return Diffur{}, 0, fmt.Errorf("Ошибка в подготовке начальных точек: %v", err) + } + copy(result.y[:4], rk.y[:4]) + for i := 4; i < len(result.x); i++ { + pred := result.y[i-4] + 4*h*(2*d.fn(result.x[i-3], result.y[i-3])-d.fn(result.x[i-2], result.y[i-2])+2*d.fn(result.x[i-1], result.y[i-1]))/3 + result.y[i] = result.y[i-2] + h*(d.fn(result.x[i-2], result.y[i-2])+4*d.fn(result.x[i-1], result.y[i-1])+d.fn(result.x[i], pred))/3 + } + maxError := 0.0 + for i, x := range result.x { + exactY := d.exactFn(x) + currErr := math.Abs(result.y[i] - exactY) + if currErr > maxError { + maxError = currErr + } + } + + return result, maxError, nil +} + +func estimateRungeError(d Diffur, method func(Diffur) (Diffur, error), coef float64) (float64, error) { + if len(d.x) < 2 { + return 0, errors.New("Недостаточно точек для оценки") + } + resH, err := method(d) + if err != nil { + return 0, err + } + var xHalf []float64 + h := d.x[1] - d.x[0] + for i := 0; i < len(d.x)-1; i++ { + xHalf = append(xHalf, d.x[i]) + xHalf = append(xHalf, d.x[i]+h/2) + } + xHalf = append(xHalf, d.x[len(d.x)-1]) + dHalf := Diffur{ + fn: d.fn, + x: xHalf, + accuracy: d.accuracy, + y: d.y, + exactFn: d.exactFn, + } + resHalf, err := method(dHalf) + if err != nil { + return 0, err + } + var yHalfInPoints []float64 + for _, x := range d.x { + for i, xh := range resHalf.x { + if math.Abs(xh-x) < 1e-9 { + yHalfInPoints = append(yHalfInPoints, resHalf.y[i]) + break + } + } + } + if len(yHalfInPoints) != len(resH.y) { + return 0, errors.New("несоответствие размеров") + } + maxError := 0.0 + for i := range resH.y { + error := math.Abs(resH.y[i] - yHalfInPoints[i]) + if error > maxError { + maxError = error + } + } + return maxError / coef, nil +}