Найшвидший виклик оптимізації алгоритму


9

Це мій перший експеримент із проблемою асимптотичної складності, хоча я задоволений відповідями цілком у коді, якщо вони приходять з поясненням їхньої складності у часі.

У мене є така проблема.

Розглянемо завдання T_1, ... T_n та procs M_1, ..., M_m. Кожне завдання потребує певного часу для виконання залежно від програми.

Кожне завдання також коштує певної суми, яку необхідно виконати залежно від завдань.

Завдання повинні бути виконані в суворому порядку (вони не можуть бути виконані паралельно), а для зміни процедур потрібен час. Завдання не можна переміщувати з однієї програми в іншу після її запуску.

Нарешті, кожне завдання має бути виконане до певного часу.

завдання

Завдання полягає в тому, щоб надати алгоритм (або якийсь код), який, даючи п'ять таблиць форми вище, мінімізує загальну вартість на виконання всіх завдань, переконуючись у тому, що всі завдання виконані в їх терміни. Якщо це неможливо, ми просто повідомляємо, що цього не можна зробити.

оцінка

Ви повинні надати великій Ой складність вашого рішення з точки зору змінних n, m і d, де d - останній термін. У вашій великій Ой складності не повинно бути зайвих констант. Отже, O (n / 1000), наприклад, слід записати як O (n).

Ваш бал обчислюється просто, встановивши n = 100, m = 100 і d = 1000 у вказану складність. Ви хочете найменший можливий бал.

вимикач для краватки

У разі зрівноваження виграє перша відповідь.


додав примітки

log у часовій складності відповіді буде взято базу 2.

табло

  • 10 ^ 202 від KSFT ( Python ) Перший поданий так отримує виграш .
  • 10 ^ 202 від Домініка Мюллера ( Скала )

"перемикання часу з рядкової машини на стовпчикову машину" Ви маєте на увазі вартість часу для переходу з M_1 на M_2? Також яка різниця між "перемиканням вартості" та "часом переключення". Зазвичай вони означають те саме, що стосується опису алгоритмів планування.
Світлий

@ Світло Придумайте час у секундах і вартість у доларах. У цьому питанні вони різні речі. У таблицях показано час (відповідно вартість) зміни машини для виконання наступного завдання. Це може бути від M_1 до M_2 або від M_2 до M_1.

Гаразд, це пояснює це.
Світлий

Коротка відповідь - складність буде O(m ^ n). Жоден алгоритм не буде "швидшим" ​​за це. Обрізка на основі максимально необхідного часу або витрат не змінює складність алгоритму, а також не має як долара, так і витрат часу, отже d, не є елементом складності.
Боб Даглегіш

1
@BobDalgleish Це дає 100 балів при потужності 100. Я вважаю, що ти можеш зробити набагато краще.

Відповіді:


2

Оцінка: 10 ^ 202

Хочеться, щоб зараз у нас була підтримка LaTeX ...

Оскільки ніхто інший не відповів, я подумав, що спробую, хоча це не дуже ефективно. Я не впевнений, що це за великий "О".

Я думаю, що це працює. Принаймні, це робиться для єдиного тестового випадку, розміщеного на сайті.

Він потребує введення, як у запитанні, за винятком міток машин чи номерів завдань та з крапками з комою замість розривів рядків.

import itertools
time = [[int(j) for j in i.split()] for i in raw_input().split(";")]
cost = [[int(j) for j in i.split()] for i in raw_input().split(";")]
nmachines=len(time)
ntasks=len(time[0])
switchtime = [[int(j) for j in i.split()] for i in raw_input().split(";")]
switchcost = [[int(j) for j in i.split()] for i in raw_input().split(";")]
deadline = [int(i) for i in raw_input().split()]
d={}
m=itertools.product(range(nmachines),repeat=ntasks)
for i in m:
    t=-switchtime[i[-1]][i[0]]
    c=-switchcost[i[-1]][i[0]]
    e=0
    meetsdeadline=True
    for j in range(ntasks):
        t+=switchtime[i[e-1]][i[e]]+time[i[e]][j]
        c+=switchcost[i[e-1]][i[e]]+cost[i[e]][j]
        e+=1
        if t>deadline[j]:
            meetsdeadline=False
    if meetsdeadline:
        d[(c,t)]=i
print min(d.keys()),d[min(d.keys())]

Чи можете ви надати пояснення і сказати, яким ви вважаєте, що має бути ваш рахунок? Також ви могли б показати, що це дає для прикладу у запитанні?

Як я заявив у своїй відповіді, я спробував це, і це працює на прикладі. Я не впевнений, що таке великий О (про що я хотів сказати у своїй відповіді).
KSFT

В основному, приблизно, скільки операцій потрібно буде виконати. Схоже, це займає ntasks * m час приблизно (припустимо, що всі завдання в циклі займають постійний час), що змушує мене підозріло ставитися до його коректності. Чи можете ви сказати щось про те, чому ви думаєте, що це працює?

1
Ой! Я пропустив це. Тож m насправді розміром nmachines ^ ntasks. Гаразд зараз я вважаю, що це працює. Я думаю, що ваш бал (100 ^ 100) * 100.

4
@Lembik Це найкращий рахунок до цих пір!
KSFT

1

Перевірити все - Scala

Орієнтовна оцінка: 2м ^ н

Я починаю з кожної машини і перебираю всі завдання, щоб створити всі перестановки через завдання з різними машинами, які відповідають термінам. Значить, якщо все вчасно, я отримав би 9 можливих шляхів з 2 машинами та 3 завданнями. (m ^ n) Після цього я проходжу шлях з найменшими витратами.

Введення структуровано так (-> пояснює частини і, таким чином, не слід вводити):

M_1:5 3 5 4;M_2:4 2 7 5                 --> time
M_1:5 4 2 6;M_2:3 7 3 3                 --> cost
M_1:M_1}0 M_2}1;M_2:M_1}2 M_2}0         --> switch itme
M_1:M_1}0 M_2}2;M_2:M_1}1 M_2}0         --> switch cost
5 10 15 20                              --> deadlines

І ось код:

package Scheduling

import scala.io.StdIn.readLine

case class Cost(task: Map[String, List[Int]])
case class Switch(machine: Map[String, Map[String, Int]])
case class Path(time: Int, cost: Int, machine: List[String])

object Main {

    def main(args: Array[String]) {
        val (machines, cost_time, cost_money, switch_time, switch_money, deadlines) = getInput

        val s = new Scheduler(machines, cost_time, cost_money, switch_time, switch_money, deadlines)
        s.schedule
    }

    def getInput(): (List[String], Cost, Cost, Switch, Switch, List[Int]) = {
        val cost_time = Cost(readLine("time to complete task").split(";").map{s => 
                val parts = s.split(":")
                (parts(0) -> parts(1).split(" ").map(_.toInt).toList)
            }.toMap)

        val cost_money = Cost(readLine("cost to complete task").split(";").map{s => 
                val parts = s.split(":")
                (parts(0) -> parts(1).split(" ").map(_.toInt).toList)
            }.toMap)

        val switch_time = Switch(readLine("time to switch").split(";").map{s => 
                val parts = s.split(":")
                (parts(0) -> parts(1).split(" ").map{t =>
                        val entries = t.split("}")
                        (entries(0) -> entries(1).toInt)
                    }.toMap)
            }.toMap)

        val switch_money = Switch(readLine("time to switch").split(";").map{s => 
                val parts = s.split(":")
                (parts(0) -> parts(1).split(" ").map{t =>
                        val entries = t.split("}")
                        (entries(0) -> entries(1).toInt)
                    }.toMap)
            }.toMap)

        val deadlines = readLine("deadlines").split(" ").map(_.toInt).toList

        val machines = cost_time.task.keys.toList

        (machines, cost_time, cost_money, switch_time, switch_money, deadlines)
    }
}

class Scheduler(machines: List[String], cost_time: Cost, cost_money: Cost, switch_time: Switch, switch_money: Switch, deadlines: List[Int]) {

    def schedule() {
        var paths = List[Path]()
        var alternatives = List[(Int, Path)]()

        for (i <- machines) {
            if (cost_time.task(i)(0) <= deadlines(0)) {
                paths = paths ::: List(Path(cost_time.task(i)(0), cost_money.task(i)(0), List(i)))
            }
        }

        val allPaths = deadlines.zipWithIndex.tail.foldLeft(paths)((paths, b) => paths.flatMap(x => calculatePath(x, b._1, b._2)))

        if (allPaths.isEmpty) {
            println("It is not possible")
        } else {
            println(allPaths.minBy(p=>p.cost).machine)
        }
    }

    def calculatePath(prev: Path, deadline: Int, task: Int): List[Path] = {
        val paths = machines.map(m => calculatePath(prev, task, m))
        paths.filter(p => p.time <= deadline)
    }

    def calculatePath(prev: Path, task: Int, machine: String): Path = {
        val time = prev.time + switch_time.machine(prev.machine.last)(machine) + cost_time.task(machine)(task)
        val cost = prev.cost + switch_money.machine(prev.machine.last)(machine) + cost_money.task(machine)(task)

        Path(time, cost, prev.machine :+ machine)
    }
}

У мене також була ідея почати ззаду. Оскільки ви завжди можете вибрати машину з найменшими витратами, якщо час менший, то різниця від попереднього терміну до нового. Але це не зменшить максимальний час виконання, якщо завдання з кращими витратами займе більше часу, ніж приурочений останній термін.

Оновлення

======

Ось ще одна настройка. час:

M_1 2 2 2 7
M_2 1 8 5 10

вартість:

M_1 4 4 4 4
M_2 1 1 1 1

час перемикання:

    M_1 M_2
M_1  0   2
M_2  6   0

вартість комутатора:

    M_1 M_2
M_1  0   2
M_2  2   0

терміни:

5 10 15 20

Як вхід до моєї програми:

M_1:2 2 2 7;M_2:1 8 5 10
M_1:4 4 4 4;M_2:1 1 1 1
M_1:M_1}0 M_2}2;M_2:M_1}6 M_2}0
M_1:M_1}0 M_2}2;M_2:M_1}2 M_2}0
5 10 15 20

У цього є два рішення: час: 18, вартість: 15, шлях: список (M_1, M_1, M_1, M_2) час: 18, вартість: 15, шлях: список (M_2, M_1, M_1, M_1)

Що викликає питання, як з цим слід поводитися. Чи всі повинні бути надруковані або лише один? А що, якщо час був би іншим? Це той, хто має найменші витрати та недостатньо пропущений термін, або він також має бути найменшим?


Питання говорить про те, що мета - "[мінімізувати] загальну вартість". До речі, чи можете ви підсумувати, як працює ваш алгоритм? Я не знаю Scala, і я не можу зрозуміти, як це працює.
KSFT

Повторне проходження всіх шляхів вимагає O(m^n)часу. Ітерація над кожною машиною для всіх завдань вимагає O(n*m^n)часу.
KSFT

Чи не O(n*m^n)повторюється кожне завдання для кожного із шляхів? І повторення над кожною машиною для кожного завдання щось подібне O(n*m).
Домінік Мюллер

Ах, друкарня. Я хотів написати «Перебір кожної машини для всіх шляхів приймає O(n*m^n)».
KSFT

Зачекайте, ні, це так O(m*m^n)=O(m^n+1). Це все-таки той же бал, хоча.
KSFT
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.