Эффективный алгоритм Декартова произведения

Удостоверьтесь редактирование корректного конфигурационного файла для VIM. Особенно при использовании окон где файл можно было назвать _vimrc вместо .vimrc как на других платформах.

В типе

:help vimrc

энергии и проверке Ваш путь к _vimrc/.vimrc файлу с

:echo $HOME

:echo $VIM

Удостоверяется, что Вы только используете один файл. Если Вы хотите разделить свою конфигурацию на меньшие блоки, можно получить другие файлы из _vimrc файла.

:help source

15
задан RobV 21 January 2010 в 14:23
поделиться

5 ответов

Сложность декартового произведения равна O ( n 2 ), ярлыка нет.

В определенных случаях порядок итерации двух осей является важным. Например, если ваш код посещает каждый слот в массиве - или каждый пиксель в изображении, - вам следует попытаться посещать слоты в естественном порядке. Изображение обычно размещается в «строках развертки», поэтому пиксели на любом Y являются смежными. Следовательно, вы должны перебирать Y во внешнем цикле и X во внутреннем.

Нужен ли вам декартово произведение или более эффективный алгоритм зависит от проблема, которую вы решаете.

32
ответ дан 1 December 2019 в 00:23
поделиться

Вы не можете действительно изменить производительность вложенного цикла без дополнительных знаний, но это будет зависеть от конкретного пользователя. Если у вас есть n элементов в это и m элементов в js , это всегда будет O (n * m) .

Вы можете изменить его вид :

var qry = from i in is
          from j in js
          select /*something involving i/j */;

Это все еще O (n * m), но с номинальными дополнительными накладными расходами LINQ (вы не будете заметьте это при обычном использовании).

Что вы делаете в вашем случае? Могут быть уловки ...

Единственное, чего определенно следует избегать - это всего, что заставляет перекрестное соединение буферизоваться - подход foreach хорош и не буферизируется - но если вы добавляете каждый элемент в Список <> , то остерегайтесь последствий для памяти.

10
ответ дан 1 December 2019 в 00:23
поделиться

Я не могу предложить ничего лучше, чем O (n ^ 2), потому что это размер вывода , и поэтому алгоритм может ' Быть быстрее.

Я могу предложить другой подход к тому, нужно ли вам вычислять продукт. Например, вам может даже не понадобиться набор продуктов P , если только вы собираетесь запросить, принадлежат ли ему определенные элементы. Вам нужна только информация о наборах, из которых он состоит.

Действительно (псевдокод)

bool IsInSet(pair (x,y), CartesianProductSet P)
{
   return IsInHash(x,P.set[1]) && IsInHash(y,P.set[2])
}

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

// Cartesian product of A and B is
P.set[1]=A; P.set[2]=B;

Если вы реализуете наборы как хеши, то ищите в декартовом произведении m sets - это просто поиск в m хэшах, которые вы получаете бесплатно.

3
ответ дан 1 December 2019 в 00:23
поделиться

К вопросу была добавлена ​​дополнительная информация.

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

Среда выполнения C # действительно очень быстрая, но для очень тяжелой работы вы можете перейти на собственный код.

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

2
ответ дан 1 December 2019 в 00:23
поделиться

Если локальность кеша (или локальная память, необходимая для поддержки j) представляет собой проблему, вы можете сделать свой алгоритм более дружественным к кэшу, рекурсивно разделив входные массивы пополам. Что-то вроде:

cartprod(is,istart,ilen, js,jstart,jlen) {
  if(ilen <= IMIN && jlen <= JMIN) { // base case
    for(int i in is) {
      for(int j in js) {
        // pair i and j
      }
    }
    return;
  }
  if(ilen > IMIN && jlen > JMIN) { // divide in 4
    ilen2= ilen>>1;
    jlen2= jlen>>1;
    cartprod(is,istart,ilen2,            js,jstart,jlen2);
    cartprod(is,istart+ilen2,ilen-ilen2, js,jstart,jlen2);
    cartprod(is,istart+ilen2,ilen-ilen2, js,jstart+jlen2,jlen-jlen2);
    cartprod(is,istart,ilen2,            js,jstart+jlen2,jlen-jlen2);
    return;
  }
  // handle other cases...
}

Обратите внимание, что этот шаблон доступа автоматически будет достаточно хорошо использовать все уровни автоматического кеширования; Этот вид техники называется алгоритмом без учета кеша .

1
ответ дан 1 December 2019 в 00:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: