<file_sep>package algs.multi

import algs.AbstractAlgorithm
import containers.AlgorithmDataContainer
import containers.DataContainer
import func.GlobalFunc
import func.Vector


class StepDivideMethod: AbstractAlgorithm() {
    override val algName: String get() = "Метод дробления шага пополам"
    override val requiredArgs: List<String> get() = listOf("a", "u")


    private val eps = GlobalFunc.epsilon

    override fun apply(args: Map<String, Any>): DataContainer {
        checkArgs(args)

        var a = args.getValue("a") as Double
        var u0 = args.getValue("u") as Vector

        for (iterations in 1 until maxIterations) {
            val grad = GlobalFunc.gradient(u0)

            if (GlobalFunc.module(grad) < eps) {
                return AlgorithmDataContainer(
                    solution = u0,
                    iteration = iterations,
                    epsilon = eps,
                    algName = algName
                )
            }

            var u1 = u0 - grad * a
            while (GlobalFunc.J(u1) >= GlobalFunc.J(u0)) {
                a /= 2
                u1 = u0 - grad * a
            }
            u0 = u1
        }
        throw Error(iterationErrorMsg)
    }
}

<file_sep>package containers

import func.Vector

abstract class DataContainer(var solution: Vector, var iteration: Int, var epsilon: Double) {
    override fun toString(): String {
        return "Решение = $solution\nитераций = $iteration\neps = $epsilon"
    }
}<file_sep>package algs.multi

import algs.AbstractAlgorithm
import algs.single.BisectionMethod
import containers.AlgorithmDataContainer
import containers.DataContainer
import func.GlobalFunc
import func.Vector

class FastDownMethod: AbstractAlgorithm() {
    override val algName: String get() = "Алгоритм наискорейшего спуска"
    override val requiredArgs: List<String> get() = listOf("u")
    override val maxIterations: Int get() = 5

    override fun apply(args: Map<String, Any>): DataContainer {
        checkArgs(args)

        var u = args.getValue("u") as Vector
        val eps = GlobalFunc.epsilon

        for (iteration in 1 until maxIterations) {
            val grad = GlobalFunc.gradient(u)

            if (GlobalFunc.module(grad) < eps) {
                return AlgorithmDataContainer(
                    solution = u,
                    iteration = iteration,
                    epsilon = eps,
                    algName = algName
                )
            }

            val method = BisectionMethod()
            val a = method.apply(mapOf("a" to 0.0, "b" to 1.0, "u0" to u))
            u -= grad.times(a.solution[0])
        }
        throw Error(iterationErrorMsg)
    }
}<file_sep>package algs


abstract class AbstractAlgorithm: AlgorithmI {
    protected val iterationErrorMsg = "$algName превысил предел в $maxIterations итераций!"
    protected fun checkArgs(args: Map<String, Any>) {
        for(arg in requiredArgs) {
            if(!args.keys.contains(arg))
                throw IllegalArgumentException("Не передан аргумент \"$arg\", для работы $algName")
        }
        this.args = args
    }
    protected lateinit var args:Map<String, Any>

    open val algName: String get() = this.javaClass.name
    open val requiredArgs: List<String> get() = listOf()
    open val maxIterations: Int get() = 100

    override fun equals(other: Any?): Boolean {
        if(this === other) return true

        if(other is AbstractAlgorithm) {
            return other.algName == algName
        }
        return false
    }

    override fun hashCode(): Int {
        return iterationErrorMsg.hashCode()
    }

}<file_sep>package algs

//import algorithm.containers.DataContainer
import containers.DataContainer

interface AlgorithmI {
    fun apply(args: Map<String, Any>) : DataContainer
}<file_sep>rootProject.name = 'MO-lab2'
<file_sep>package algs.multi

import algs.AbstractAlgorithm
import containers.AlgorithmDataContainer
import containers.DataContainer
import func.GlobalFunc
import func.Vector

class NewtonsMethod: AbstractAlgorithm() {
    override val algName: String get() = "<NAME>"
    override val requiredArgs: List<String> get() = listOf("u")

    override fun apply(args: Map<String, Any>): DataContainer {
        checkArgs(args)

        var u0 = args.getValue("u") as Vector
        val eps = GlobalFunc.epsilon

        for (iterations in 1 until maxIterations) {
            var grad = GlobalFunc.gradient(u0)

            if (GlobalFunc.module(grad) < eps) {
                return AlgorithmDataContainer(
                    solution = u0,
                    epsilon = eps,
                    iteration = iterations,
                    algName = algName
                )
            }

            u0 -= Vector.toVector(grad * GlobalFunc.getH(u0).inverse)
        }
        throw Error(iterationErrorMsg)
    }
}

<file_sep>package algs.single

import algs.AbstractAlgorithm
import containers.AlgorithmDataContainer
import func.GlobalFunc
import func.Vector
import java.lang.Math.abs

class BisectionMethod: AbstractAlgorithm() {
    override val algName: String get() = "Метод деления пополам"
    override val requiredArgs get() = listOf("a", "b", "u0")

    private val sigma = 0.0001


    override fun apply(args: Map<String, Any>): AlgorithmDataContainer {
        checkArgs(args)

        var a = args.getValue("a") as Double
        var b = args.getValue("b") as Double
        val eps = GlobalFunc.epsilon
        val u1 = args.getValue("u0") as Vector

        for(iterations in 1 until maxIterations) {
            val a1 = (b + a - sigma) / 2
            val a2 = (b + a + sigma) / 2
            val f1 = GlobalFunc.J(u1 - a1 * GlobalFunc.gradient(u1))
            val f2 = GlobalFunc.J(u1 - a2 * GlobalFunc.gradient(u1))

            when {
                f1 < f2 -> b = a2
                f1 > f2 -> a = a1
                else -> {
                    a = a1
                    b = a2
                }
            }

            if(abs(b - a) < eps)
                return AlgorithmDataContainer(
                    solution = Vector(listOf((b + a) / 2)),
                    iteration = iterations,
                    epsilon = eps,
                    algName = algName
                )
        }
        throw Error(iterationErrorMsg)
    }
}

private operator fun Double.times(gradient: Vector): Vector {
    return gradient * this
}
<file_sep>package func

import matrix.AbstractMatrix
import matrix.Matrix
import kotlin.math.pow
import kotlin.math.sqrt


class GlobalFunc {

    companion object {
        const val epsilon: Double = 0.001

        fun J(U: Vector) :Double {
            val u1 = U[0]
            val u2 = U[1]

//            return (u1 - u2).pow(2) + u1 - 5 * u2
//            return (u1 - 5).pow(2) + (u2 + 3).pow(2)
            return -(u1 + u2).pow(2) + 9 * u1 * u2
            //(u1 - u2)^2 + u1 - 5u2
        }


        fun JDiff_U1(U: Vector): Double {
            val u1 = U[0]
            val u2 = U[1]

//            return 2 * u1 - 2 * u2 + 1
//            return 2 * (u1 - 5)
            return 7 * u2 - 2 * u1
            //2u1 - 2u2 + 1
        }

        fun JDiff_U2(U: Vector): Double {
            val u1 = U[0]
            val u2 = U[1]

//            return 2 * u2 - 2 * u1 - 5
//            return 2 * (u2 + 3)
            return 7 * u1 - 2 * u2
            //-2u1 + 2u2 - 5
        }

        fun JDiff_U1_U2(U: Vector): Double {
//            return -2.0
//            return 0.0
            return 7.0
        }

        fun JDiff_U1_U1(U: Vector): Double {
//            return 2.0
//            return 2.0
            return -2.0
        }

        fun JDiff_U2_U1(U: Vector): Double {
//            return -2.0
//            return 0.0
            return 7.0
        }

        fun JDiff_U2_U2(U: Vector): Double {
//            return 2.0
//            return 2.0
            return -2.0
        }

        fun getH(U: Vector): AbstractMatrix {
            var array = arrayOf(
                doubleArrayOf(JDiff_U1_U1(U), JDiff_U2_U1(U)),
                doubleArrayOf(JDiff_U1_U2(U), JDiff_U2_U2(U))
            )
            return Matrix(array)
        }

        fun gradient(U: Vector): Vector {
            val coeffs = listOf(JDiff_U1(U), JDiff_U2(U))
            return Vector(coeffs)
        }

        fun gradValue(U: Vector): Double {
            val gradient = gradient(U)
            return module(gradient)
        }

        fun module(U: Vector): Double {
            var value = 0.0

            for (point in U) {
                value += point.pow(2)
            }
            return sqrt(value)
        }
    }
}<file_sep>package containers

import func.Vector

class AlgorithmDataContainer(solution: Vector, iteration: Int, epsilon: Double, val algName: String)
    : DataContainer(solution, iteration, epsilon) {

    override fun toString(): String {
        return super.toString().plus("\nалгоритм - $algName" )
    }
}<file_sep>package func

import matrix.AbstractMatrix
import matrix.Matrix
import java.util.*
import kotlin.collections.ArrayList


class Vector(private val coefficients: List<Double>) : Iterable<Double> {
    private val count = 4
    var format = "%.${count}f"

    override fun iterator(): Iterator<Double> {
        return coefficients.iterator()
    }

    operator fun get(i: Int): Double {
        return coefficients[i]
    }

    operator fun minus(vector: Vector): Vector {
        var list = ArrayList<Double>(coefficients.size)

        for ((i, item) in coefficients.withIndex()) {
            list.add(item - vector[i])
        }
        return Vector(list)
    }

    @JvmName("timeByDouble")
    operator fun times(coef: Double): Vector {
        var list = ArrayList<Double>(coefficients.size)

        for (item in coefficients) {
            list.add(item * coef)
        }
        return Vector(list)
    }

    @JvmName("timeByMatrix")
    operator fun times(matrix: AbstractMatrix): Vector {
        var temp = this.toMatrix()
        var result = temp * matrix

        return toVector(result)
    }

    override fun toString(): String {
        val sj = StringJoiner(", ")
        for (item in coefficients) {
            val str = String.format(format, item)
            sj.add(str)
        }
        return "($sj)"
    }

    fun toMatrix(): AbstractMatrix {
        return Matrix(
            arrayOf(
                doubleArrayOf(this[0], this[1])
            )
        )
    }

    companion object {
        fun toVector(matrix: AbstractMatrix): Vector {
            var list = ArrayList<Double>()

            if (matrix.rowsNum == 1) {
                for (elem in matrix.getRow(0)) {
                    list.add(elem)
                }
            }
            return Vector(list)
        }
    }



}

private operator fun AbstractMatrix.times(matrix: AbstractMatrix): AbstractMatrix {
    return this.mulMatrix(matrix)
}



<file_sep>import algs.AlgorithmI
import algs.multi.FastDownMethod
import algs.multi.NewtonsMethod
import algs.multi.StepDivideMethod
import containers.DataContainer
import func.Vector


fun main() {
    val algs = listOf(StepDivideMethod(), FastDownMethod(), NewtonsMethod())
    val bannedAlgs = emptyList<AlgorithmI>()

    val args = mapOf("a" to 0.1, "u" to Vector(listOf(1.0, 1.0)))

    var data = ArrayList<DataContainer>()
    for (alg in algs) {
        if (bannedAlgs.contains(alg)) continue

        val container = alg.apply(args)
        data.add(container)
    }

    data.forEach { println("$it\n") }
}

