Алгоритмы точного вычисления гиперобъема

Материал из Викиконспекты
Перейти к: навигация, поиск
Эта статья находится в разработке!

Постановка задачи[править]

[math]x = (x_1, x_2, ..., x_d; x_i \ge 0) \in \mathbb{R}^d[/math] - точка в [math]d[/math]-мерном пространстве.

Точка [math]x[/math] доминирует точку [math]y[/math] ([math]x \succ y[/math]), если [math]\forall i : x_i \ge y_i, \exists j : x_j \gt y_j[/math].

[math]X = \{x^1, x^2, ..., x^n\} \subset \mathbb{R}^d[/math] - множество из [math]n[/math] точек в [math]d[/math]-мерном пространстве таких, что [math]\nexists i \neq j : x_i \succ x_j[/math] - никакая точка не доминируется другой точкой из этого множества.

[math]S(X) = \mu (\bigcup \limits_{x \in X} \{y | x \succ y\}) [/math] - гиперобъем множества [math]X[/math], где [math]\mu[/math] - мера Лебега.

В частности, если [math]X = \{x\}[/math], то [math]S(X) = \prod \limits_{i=1}^{d} x_i[/math].

Задача: найти точное значение гиперобъема [math]S(X)[/math] множества из [math]n[/math] точек [math]d[/math]-мерного пространства.

Алгоритм включения-исключения (Inclusion-Exclusion Algorithm, IEA)[править]

Самый простой алгоритм нахождения гиперобъема базируется на идее комбинаторной формулы включения-искючения. Все множество [math]X[/math] представляется в виде объединения [math]n[/math] гиперпараллелепипедов ([math]X^i[/math]), соответствующих отдельным точкам [math]x^i[/math].

После этого объем всего множества вычисляется по формуле:
[math] S(X) = \sum \limits_{I \in 2^n} (-1)^{|I|+1} S(\bigcap \limits_{ j \in I} X^j) [/math]

Объем пересечения гиперпараллелепипедов легко считается как произведение по каждой координате минимального значения этой координаты среди всех точек, которым соответствуют гиперпараллелепипеды.

Таким образом, в этом алгоритме перебираются все подмножества точек множества [math]X[/math], для каждого множества находится гиперобъем пересечения соответствующих гиперпараллелепипедов, и он прибавляется с соответствующим знаком к ответу. Время работы этого алгоритма составляет [math]O(n 2^n)[/math].

Алгоритм LebMeasure[править]

Алгоритм LebMeasure[1] обрабатывает точки множества [math]X[/math] по очереди. Для каждой очередной точки [math]x[/math] находится объем некоторого максимального по включению гиперпараллелепипеда, доминируемого эксклюзивно только этой точкой [math]x[/math] и она заменяется на некоторое множество порожденных точек, которые доминируют оставшуюся область, доминировавшуюся до этого точкой [math]x[/math].

Например, если изначально было четыре точки в трехмерном пространстве [math](6, 7, 4), (9, 5, 5), (1, 9, 3), (4, 1, 9)[/math], то точка [math](6, 7, 4)[/math] эксклюзивно доминирует параллелепипед с одним концов в [math](6, 7, 4)[/math], а другим - в [math](4, 5, 3)[/math]. После добавления объема этого параллелепипеда к ответу, точка [math](6, 7, 4)[/math] порождает три точки: [math](4, 7, 4), (6, 5, 3), (6, 7, 3)[/math]. При этом точка [math](6, 5, 4)[/math] доминируется точкой [math](9, 5, 5)[/math] и сразу удаляется из множества [math]X[/math].

Обработка точек продолжается, пока все точки не будут обработаны. Таким образом, время работы алгоритма напрямую зависит от количества порожденных точек. Легко заметить, что таких точек не более, чем [math]n^d[/math], поскольку каждая координата каждой порожденной точки равна соответствующей координате некоторой точки исходного множества [math]X[/math].

К сожалению, эта верхняя оценка является достижимой. Например, если исходное множество [math]X[/math] имеет вид: [math](1, n, n, ..., n), (2, n - 1, n - 1, ..., n - 1), ..., (n, 1, 1, ..., 1)[/math], и точки обрабатываются именно в этом порядке, то всего будет обработано [math]n^{d-1}[/math] точка, что показано в [2]. Правда, если в этом примере точки обрабатываются в обратном порядке, то суммарное количество обработанных точек линейно зависит от [math]n[/math] и [math]d[/math]. Тем не менее, существуют примеры, для которых любой порядок обработки приводит к экспоненциальной зависимости числа порожденных точек от размерности пространства [math]d[/math] и эта зависимость близка к [math]n^d[/math] [2].

Алгоритм Hypervolume by Slicing Objectives (HSO)[править]

Под Objectives в названии данного алгоритма имеются в виду координаты пространства [math]\mathbb{R}^d[/math].

Если алгоритм LebMeasure по очереди рассматривает все точки, то алгоритм HSO[3] рассматривает по очереди все координаты, сводя задачу к меньшей на единицу размерности.

Изначально все точки сортируются по первой координате. Значения этой координаты используются для расслоения (разрезания) всего множества на [math]n[/math] частей, внутри каждой из которых при движении вдоль первой координаты форма разреза (гиперплоскости), проходящего перпендикулярно оси первой координаты, не меняется. Таким образом, для подсчета объема каждой части необходимо найти объем разреза, и умножить на длину части вдоль первой координаты. При этом получившийся разрез имеет на единицу меньшую размерность. Заметим, что после сортировки и расслоения первая часть содержит все исходные [math]n[/math] точек множества [math]X[/math], вторая - все, помимо точки с минимальной первой координатой, вдоль которой происходит расслоение, и т.д., а последняя часть содержит только одну точку с максимальной этой координатой.

После этого все полученные части расслаиваются уже по второй координате, далее все полученные - по третьей и т.д. В итоге исходное множество разбивается на несколько непересекающихся гиперпараллелепипедов и остается их найти суммарный гиперобъем. Заметим, что расслаивание части можно прекратить в тот момент, когда в нее входит только одна точка и посчитать объем гиперпараллелепипеда, образованного проекцией этой точки на оставшиеся координаты.

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

Время работы алгоритма напрямую зависит от суммарного количества частей, на которые будет разбито исходное множество. По аналогичным предыдущему алгоритму рассуждениям легко показывается, что частей не более [math]n^d[/math]. Тем не менее, существует более точная оценка.

Теорема:
Суммарное количество частей, полученных алгоритмом HSO, не превышает
[math]f(n, d) = {n + d - 2 \choose d - 1}[/math].
Доказательство:
[math]\triangleright[/math]
База:
[math]f(n, 1) = 1[/math].
Также, из алгоритма расслоения следует, что из части с [math]n[/math] точками будет получено по одной части для каждого [math]i = 1...n[/math], то есть:
[math]f(n, d) = \sum \limits_{i = 1}^{n}f(i, d - 1)[/math].

Докажем полезные леммы:

Лемма:
[math]{x \choose y} = {x - r \choose y} + \sum \limits_{i = 1}^{r} {x - i \choose y - 1}[/math].
Доказательство:
[math]\triangleright[/math]
Индукция по [math]r[/math]. База:
[math]{x \choose y} = {x - 1 \choose y} + {x - 1 \choose y - 1}[/math].

Переход: предполагаем, что утверждение верно для [math]r = j[/math]. Раскрываем первое слагаемое в правой части предположения аналогично базе и получаем:

[math]{x \choose y} = {x - j - 1 \choose y} + {x - (j + 1) \choose y - 1} + \sum \limits_{i = 1}^{j}{x - i \choose y - 1} = {x - (j + 1) \choose y} + \sum \limits_{i = 1}^{j}{x - i \choose y - 1}[/math].
[math]\triangleleft[/math]
Лемма:
[math]{x \choose y} = \sum \limits_{i = 1}^{x - y + 1} {x - i \choose y - 1}[/math].
Доказательство:
[math]\triangleright[/math]

Подставляем в предыдущую лемму [math]r = x - y[/math] и получаем:

[math]{x \choose y} = {y \choose y} + \sum \limits_{i = 1}^{x - y} {x - i \choose y - 1} = {x - (x - y + 1) \choose y - 1} + \sum \limits_{i = 1}^{x - y} {x - i \choose y - 1} = \sum \limits_{i = 1}^{x - y + 1} {x - i \choose y - 1}[/math].
[math]\triangleleft[/math]

продолжаем доказательство теоремы по индукции:

[math]f(n, d) = {n + d - 2 \choose d - 1} = \sum \limits_{i = 1}^{n} {n + d - 2 - i \choose d - 2} = \sum \limits_{k = n}^{1} {n + d + 2 - (n - k + 1) \choose d - 2} = \sum \limits_{k = 1}^{n} {k + d - 3 \choose d - 2} = \sum \limits_{k = 1}^{n}{k + (d - 1) - 2 \choose (d - 1) - 1} = \sum \limits_{k = 1}^{n}{f(k, d - 1)}[/math]
[math]\triangleleft[/math]

Таким образом, на этот алгоритм получена более низкая оценка времени работы, чем на предыдущий, и это подтверждается на практике [2].

Сведение к задаче KMP (Klee's Measure Problem)[править]

Задача KMP состоит в нахождении объема объединения прямоугольных гиперпараллелепипедов в [math]d[/math]-мерном пространстве. Как показано в описании алгоритма IEA, исходная задача легко сводится к этой, если каждой точке поставить в соответствие гиперпараллелепипед с одной вершиной в центре координат, а противоположной - в этой точке.

Существует несколько алгоритмов решения задачи KMP[4][5][6], самый оптимальный из которых использует идеи сканирующей гиперплоскости, корневой эвристики и КД-дерево, и позволяет решать задачу за время [math]O(n^{d/2}\log n)[/math]. Рассмотрим его.

Для начала изложим идею сканирующей гиперплоскости. Рассмотрим всевозможные значения [math]d[/math]-ой координаты у точек множества [math]X[/math]. Возьмем гиперплоскость, перпендикулярную оси [math]d[/math]-ой координаты, будем ее двигать по этим значениям от минимального до максимального и рассматривать проекцию всех гиперпараллелепипедов на эту гиперплоскость. Заметим, что между точками проекция меняться не будет, а в каждой точке будут появляться или исчезать проекции некоторых гиперпараллелепипедов. Поэтому, если уметь эффективно пересчитывать объем проекции при каждом появлении/исчезновении и прибавлять это значение, умноженное на расстояние между последовательными значениями [math]d[/math]-ой координаты, то можно легко посчитать суммарный гиперобъем. Как раз для эффективного пересчета используется такая структура, как КД-дерево.

Теперь изложим идею алгоритма на примере трехмерного пространства. В трехмерном пространстве сканирующая гиперплоскость превращается в обычную плоскость. Будем считать, что она всегда располагается перпендикулярно оси [math]OZ[/math] и двигается от минимальных значений по этой оси до максимальных. В каждый момент проекция всех параллелепипедов на эту плоскость представляет собой множество прямоугольников и необходимо уметь обрабатывать следующие три запроса:

  1. добавить прямоугольник
  2. удалить прямоугольник
  3. посчитать площадь объединения всех прямоугольников


Определение:
КД-деревом называется сбалансированное двоичное дерево, где каждой вершине [math]\alpha[/math] соответствует некоторая область [math]C_{\alpha}[/math] [math]d[/math]-мерного пространства, удовлетворяющая следующим свойствам:
  1. Корневой вершине [math]root[/math] соответствует [math]C_{root}[/math] - все пространство.
  2. Каждое [math]C_{\alpha}[/math] является гиперпараллелепипедом (возможно бесконечным в некоторых направлениях).
  3. Для каждой вершины [math]\alpha[/math] с детьми [math]\beta[/math] и [math]\gamma[/math] верно, что области [math]C_{\beta}[/math] и [math]C_{\gamma}[/math] не пересекаются и [math]C_{\alpha} = C_{\beta} \cup C_{\gamma}[/math].


Будем хранить прямоугольники в КД-дереве следующим образом:

  1. Для каждого листа [math]\alpha[/math] будем хранить все прямоугольники, которые пересекают внутреннюю часть области [math]C_{\alpha}[/math].
  2. Для каждой внутренней вершины [math]\alpha[/math] будем считать число [math]Cover_{\alpha}[/math] - количество прямоугольников, которые полностью покрывают область [math]C_{\alpha}[/math], но не полностью покрывают область родителя этой вершины [math]C_{father(\alpha)}[/math].

Также для каждой вершины будем хранить значение площади пересечения области этой вершины со всеми прямоугольниками [math]M[/math], которое определяется следующим образом:

  1. Для каждого листа [math]M[/math] равно площади пересечения всех прямоугольников с областью этого листа.
  2. Для каждой внутренней вершины [math]\alpha[/math] если [math]Cover_{\alpha} \gt 0[/math], тогда [math]M[/math] равно площади всей области [math]C_{\alpha}[/math], иначе [math]M[/math] равно сумме этих значений для двух сыновей этой вершины.

Таким образом, значение для корневой вершины [math]M_{root}[/math] и является искомой площадью объединения всех прямоугольников.

Рассмотрим операцию добавления прямоугольника (box) в КД-дерево.

 procedure Insert(box, [math]\alpha[/math])
 if [math]\alpha[/math] - лист then
   добавить box в эту вершину
   пересчитать [math]M_{\alpha}[/math]
 elseif box покрывает область [math]C_{\alpha}[/math] then
   [math]Cover_{\alpha} = Cover_{\alpha} + 1[/math]
   [math]M_{\alpha} = [/math] объем области [math]C_{\alpha}[/math]
 elseif box пересекает область [math]C_{\alpha}[/math] then
   Insert(box, leftson([math]\alpha[/math]))
   Insert(box, rightson([math]\alpha[/math]))
   if [math]Cover_{\alpha} \gt  0 [/math] then
     [math]M_{\alpha} = [/math] объем области [math]C_{\alpha}[/math]
   else
     [math]M_{\alpha} = M_{leftson(\alpha)} + M_{rightson(\alpha)}[/math]

Аналогично устроена операция удаления прямоугольника - она выполняет обратные действия.

Рассмотрим теперь как именно будет устроено разделение пространства на области КД-деревом для эффективного его использования. Возьмем проекции всех параллелепипедов на плоскость, перпендикулярную оси [math]OZ[/math] - множество прямоугольников [math]V[/math]. Рассмотрим все [math]x[/math]-координаты границ прямоугольников и разобьем ось [math]OX[/math] на [math]2\sqrt{n}[/math] промежутков так, чтобы в каждом из них было не более [math]\sqrt{n}[/math] границ. Получившиеся [math]2\sqrt{n}[/math] полос разобьем горизонтальными линиями на итоговые области по отдельности следующим образом. Для каждой полосы у всех прямоугольников, имеющих вертикальную границу в этой полосе, возьмем все горизонтальные границы (их будет не более [math]2\sqrt{n}[/math]), а среди всех горизонтальных границ, пересекающих область, возьмем каждую [math]\sqrt{n}[/math]-ую. Таким образом, в итоге получим не более [math]4\sqrt{n}[/math] областей в каждой вертикальной полосе.

Полученные области обладают следующими свойствами:

  1. Всего [math]O(n)[/math] областей.
  2. Каждый прямоугольник частично покрывает не более [math]O(\sqrt{n})[/math] областей.
  3. Никакая вершина прямоугольника не лежит внутри какой-нибудь области.
  4. Для каждой области есть не более [math]O(\sqrt{n})[/math] частично покрывающих ее прямоугольников.

Все эти утверждения несложно следуют из алгоритма разбиения на области.

Каждая из этих областей будет одним из листов КД-дерева. Для построения всего дерева сначала объединим все области для одной вертикальной полосы, сливая соседние области в одну вершину дерева. После этого аналогично будем сливать соседние вертикальные области и в итоге получим корневую вершину, представляющую всю плоскость.

Построенное КД-дерево обладает следующими свойствами:

  1. В нем [math]O(n)[/math] вершин.
  2. Каждый прямоугольник хранится в [math]O(\sqrt{n})[/math] листьях.
  3. Каждый прямоугольник влияет на [math]O(\sqrt{n} \log n)[/math] значений [math]Cover[/math].
  4. Никакая вершина прямоугольника не лежит внутри области какого-нибудь листа.
  5. Для области каждого листа есть не более [math]O(\sqrt{n})[/math] частично покрывающих ее прямоугольников.

Все эти свойства следуют из свойств разбиения на области и логарифмической высоты дерева.

Наконец, получаем итоговый алгоритм. Идем сканирующей плоскостью, перпендикулярной оси [math]OZ[/math], добавляя или удаляя прямоугольники из КД-дерева. При этом каждый раз пересчитываем площадь объединения всех текущих прямоугольников и, складывая эти величины, умноженные на соответствующую разницу [math]z[/math]-координат, получаем общий объем.

Каждая операция добавления или удаления прямоугольников требует изменения [math]O(\sqrt{n} \log n)[/math] полей [math]Cover[/math], а также операций добавления или удаления прямоугольника в [math]O(\sqrt{n})[/math] листьев, каждая из которых требует [math]O(\log n)[/math] времени. Итого, на одну операцию добавления или удаления требуется [math]O(\sqrt{n} \log n)[/math] времени, суммарно таких операций [math]O(n)[/math], и получается, что весь алгоритм работает за [math]O(n \sqrt{n} \log n)[/math]. При этом на хранение всей информации требуется [math]O(n\sqrt{n}) [/math] памяти - каждый лист может хранить [math]O(\sqrt{n})[/math] прямоугольников.

Все идеи этого алгоритма обобщаются с трехмерного пространства на [math]d[/math]-мерное следующим образом.

Построение разбиения на области в [math]d[/math]-мерном пространстве вместо двухмерного ведется сначала аналогичным образом, только после того, как в двухмерном пространстве получаются итоговые прямоугольные области, здесь продолжаются аналогичные разбиения вдоль третьей координаты - берутся все границы третьей координаты гиперпараллелепипедов, имеющие границу по первой или второй координате строго внутри области (их получается не более [math]O(\sqrt{n})[/math]), а также каждую [math]O(\sqrt{n})[/math]-ую границу по третьей координате гиперепараллелепипедов, пересекающих эту область, и так далее.

Это разбиение на области имеет следующие аналогичные свойства:

  1. Всего [math]O(n^{d/2})[/math] областей.
  2. Каждый гиперпараллелепипед частично покрывает не более [math]O(n^{(d-1)/2})[/math] областей.
  3. Никакая вершина гиперпараллелепипеда не лежит внутри какой-нибудь области.
  4. Для каждой области есть не более [math]O(\sqrt{n})[/math] частично покрывающих ее гиперпараллелепипедов.

Общее дерево строится аналогичным образом и оно в итоге состоит из [math]d[/math] уровней, каждый из которых имеет высоту [math]O(\log n)[/math] в дереве - самый верхний уровень содержит разбиение по первой координате, следующий - по второй и так далее.

Построенное КД-дерево обладает следующими свойствами:

  1. В нем [math]O(n^{d/2})[/math] вершин.
  2. Каждый гиперпараллелепипед хранится в [math]O(n^{(d-1)/2})[/math] листьях.
  3. Каждый гиперпараллелепипед влияет на [math]O(n^{(d-1)/2} \log n)[/math] значений [math]Cover[/math].
  4. Никакая вершина гиперпараллелепипеда не лежит внутри области какого-нибудь листа.
  5. Для области каждого листа есть не более [math]O(\sqrt{n})[/math] частично покрывающих ее гиперпараллелепипедов.

Операции в этом дереве выполняются аналогично трехмерному случаю и каждая операция добавления или удаления в КД-дерево размерности [math]d[/math] занимает [math]O(n^{(d-1)/2} \log n)[/math] времени. Выполняя сканирование гиперплоскостью вдоль одной из координат получаем КД-дерево размерности [math]d-1[/math], в котором необходимо провести [math]O(n)[/math] операций, то есть суммарное время работы алгоритма равно: [math]O(n \times n^{(d-1-1)/2} \log n) = O(n^{d/2} \log n)[/math]. При этом хранение КД-дерева требует [math]O(n^{d/2})[/math] памяти.

Источники[править]

  1. Bringmann K., Friedrich. T.: An Efficient Algorithm for Computing Hypervolume Contributions. Evolutionary Computation, Vol. 18, No. 3, MIT Press, pp 383-402. (2010)
  2. 2,0 2,1 2,2 While, L., Hingston, P., Barone, L., Huband, S.: A Faster Algorithm for Calculating Hypervolume. IEEE Transaction on Evolutionary Computation, Vol.10, No. 1, pp 29–38. (2006)
  3. Zhou X., Sun C., Mao N., Li W.: Generalization of HSO algortihms for computing hypervolume for mutiobjective optimization problems, IEEE Congress on Evolutionary Computation. (2007)
  4. Overmars M.H., Yap C.K.: New upper bounds in Klee’s measure problem. SIAM Journal on Computing 20(6), pp 1034–1045. (1991)
  5. Beume N.: S-Metric calculation by considering dominated hypervolume as Klee’s measure problem. Evolutionary Computation, 17(4), pp 477–492. (2009)
  6. Beume N., Rudolph G.: Faster S-metric calculation by considering dominated hypervolume as Klee’s measure problem. In Proc. Second International Conference on Computational Intelligence (IASTED ’06), pp 233–238. (2006)