Представьте себе функциональный язык программирования, единственными типами данных которого являются числовые скаляры и произвольные вложения массивов. В языке отсутствуют какие-либо средства неограниченной итерации, поэтому запрещено следующее:
- явные циклы (во всяком случае, без побочных эффектов)
- рекурсия
- произвольные функции первого класса (без y-комбинатора)
Язык, однако, имеет:
- функции верхнего уровня
- лексически ограниченные пусть привязки
- ветвление потока управления
- общие скалярные математические и логические функции
- некоторый простой конструктор массива, такой как fill (n, x), который создает массив из n элементов с одинаковыми значениями x
- самое главное: ограниченный набор операторов высшего порядка, которые выполняют параллельные структурированные итерации (такие как отображение, уменьшение, сканирование, все пары).
Чтобы быть более конкретным о параллельных операторах данных:
- y = map (f, x) => y [i] = f [i]
- y = уменьшить (f, a, x) => y = f (a, f (y [p [0]], f (y [p [1]], ...))) для некоторой перестановки p
- y = scan (f, a, x) => y [i] = уменьшить (f, a, y [0 ... i-1])
- y = allpairs (f, x, y) => y [i, j] = f (x [i], y [j])
У нас могут быть и другие операторы, но для квалификации они должны иметь полиномиальное время выполнения, быть реализуемыми в рамках некоторой разумной модели параллельных вычислений данных и использовать не более чем полиномиальное пространство.
Очевидно, есть некоторые конструкции, которые не могут быть выражены на этом языке, такие как:
while f(x) > tol:
x <- update(x)
Что мы можем выразить в этой системе? Мы ограничены только проблемами поиска в FP? Можем ли мы охватить все алгоритмы полиномиального времени? Кроме того, есть ли минимальный набор операторов для этого класса?