Кіріспе

Математикалық оптимизация мәселесі. Матрица тізбегін көбейту (немесе матрица тізбегін реттеу мәселесі) әр 2 ≤ k ≤ n үшін, k ұзындығындағы барлық кіші тізбектердің ең төменгі құнын, бұрын есептелген кішігірім кіші тізбектердің құнын пайдаланып есептейді. Оның асимптотикалық орындалу уақыты бірдей және рекурсия қажет емес. Псевдокод:
// A[i] матрицасының өлшемдері dims[i-1] x dims[i] үшін i = 1-ден n-ге дейін
MatrixChainOrder(int dims[])
{
// length[dims] = n + 1
n = dims.length - 1;
// m[i,j] = матрицаны есептеу үшін қажетті скалярлық көбейтулердің ең аз саны (яғни, құн)
// A[i]A[i+1]…A[j] = A[i…j]
// Бір матрицаны көбейту кезінде құн нөлге тең
for (i = 1; i <= n; i++)
m[i, i] = 0;

for (len = 2; len <= n; len++) { // Кіші тізбек ұзындықтары
for (i = 1; i <= n - len + 1; i++) {
j = i + len - 1;
m[i, j] = MAXINT;
for (k = i; k <= j - 1; k++) {
cost = m[i, k] + m[k+1, j] + dims[i-1]*dims[k]*dims[j];
if (cost < m[i, j]) {
m[i, j] = cost;
s[i, j] = k; // Ең төменгі құнға қол жеткізген кіші тізбек бөлінісінің индексі
}
}
}
}
}
Ескерту: dims үшін бірінші индекс 0, ал m және s үшін бірінші индекс 1. Стандартты кітапханадан мемоизация декораторын пайдаланатын Python іске асыруы:

from functools import cache

def matrixChainOrder(dims: list[int]) -> int:
@cache
def a(i, j):
return min((a(i, k) + dims[i] * dims[k] * dims[j] + a(k, j)
for k in range(i + 1, j)), default=0)

return a(0, len(dims) - 1)

Тиімді алгоритмдер

O(n³) динамикалық бағдарламалау алгоритмінен тиімдірек алгоритмдер бар, дегенмен олар көбірек күрделі.

Басқа O ((n log n) алгоритмдер

Ван, Чжу және Тянь жеңілдетілген O(n log m) алгоритмін жариялады, мұнда n – тізбектегі матрицалардың саны, ал m – берілген матрица тізбегінің өлшемдер тізбесіндегі жергілікті минимумдардың саны. Нимбарк, Гохел және Доши ашкөз O(n log n) алгоритмін жариялады, бірақ олардың оптималдық дәлелі дұрыс емес және олардың алгоритмі кейбір матрица тізбектері үшін ең тиімді жақшаларды тағайындауды қамтамасыз ете алмайды. Hu & Shing алгоритмі O(n) уақытта жұмыс істейді және оңтайлы таңдаудан ең көп дегенде 15,47%-ға нашаррақ жақшалауды тудырады. Көп жағдайда алгоритм оңтайлы шешімді немесе оңтайлы шешімнен тек 1-2 пайыз ғана нашар шешімді ұсынады. Бұның біршама қиын жағдайы – тізбектер тізімінің тізбекті біріктірілуі. Мысалы, C тілінде strcat функциясын пайдаланып, ұзындығы m және n екі тізбекті біріктірудің құны O(m + n) болады, себебі бірінші тізбектің соңына жету үшін O(m) уақыт, ал екінші тізбекті соңына көшіру үшін O(n) уақыт қажет. Бұл шығындар функциясын пайдаланып, тізбекті біріктірудің ең жылдам жолын табу үшін динамикалық бағдарламалау алгоритмін жазуға болады. Алайда, бұл оңтайландыру аса пайдалы емес, өйткені тізбектерді олардың ұзындықтарының қосындысына пропорционалды уақытта тікелей біріктіруге болады. Ұқсас мәселе жеке байланысты тізімдер үшін де туындайды. Тағы бір жалпылау – параллель процессорлар қолданылатын жағдайда мәселені шешу. Бұл жағдайда, матрица көбейтіндісінің әрбір факторын есептеу шығындарын қосудың орнына, біз максимумды таңдаймыз, өйткені оларды бір уақытта орындауға болады. Бұл ең төменгі шығындарға да, соңғы оңтайлы топтастыруға да әсер етуі мүмкін; барлық процессорларды жұмыспен қамтитын, тепе-теңдік сақталған топтастыруларға басымдық беріледі. Одан да күрделі тәсілдер бар.