Может ли кто-нибудь продемонстрировать мне более эффективный алгоритм декартовых произведений, чем тот, который я использую в настоящее время (при условии, что он есть). Я посмотрел вокруг и немного погуглил, но не вижу ничего очевидного, поэтому я мог что-то упустить.
foreach (int i in is) {
foreach (int j in js) {
//Pair i and j
}
}
Это очень упрощенная версия того, что я делаю в своем коде. Два целых числа являются ключами поиска, которые используются для извлечения одного / нескольких объектов, и все объекты из двух поисков объединяются в новые объекты.
Этот небольшой блок кода в гораздо более крупной и сложной системе становится основным узким местом производительности, поскольку набор данных работает в масштабах. Некоторое из этого, вероятно, можно было бы смягчить, улучшив структуры данных, используемые для хранения объектов и соответствующих поисков, но я считаю, что главная проблема по-прежнему заключается в вычислении самого декартова произведения.
Редактировать
Итак, еще немного предыстории моего конкретного использования этого алгоритма, чтобы увидеть, могут ли быть какие-то уловки, которые я могу использовать в ответ на комментарий Марка. Вся система представляет собой механизм запросов SPARQL, который обрабатывает запросы SPARQL по наборам данных Graph, SPARQL - это язык, основанный на шаблонах, поэтому каждый запрос состоит из серии шаблонов, сопоставляемых с графиками. В случае, когда два последующих шаблона не имеют общих переменных (они не пересекаются), необходимо вычислить декартово произведение решений, полученных этими двумя шаблонами, чтобы получить набор возможных решений для общего запроса. Может быть любое количество шаблонов, и мне, возможно, придется вычислять декартовы произведения несколько раз, что может привести к довольно экспоненциальному расширению возможных решений, если запрос состоит из серии непересекающихся шаблонов.
Почему-то из существующих ответов я сомневаюсь, есть ли какие-нибудь хитрости, которые могли бы применить
Обновление
Поэтому я подумал, что опубликую обновленную информацию о том, что я реализовал, чтобы минимизировать потребность в декартовых продуктах и, таким образом, оптимизировать механизм запросов в целом. Обратите внимание, что не всегда возможно полностью устранить потребность в продуктах, но почти всегда можно оптимизировать, так что размер двух соединяемых комплектов намного меньше.
Поскольку каждый BGP (базовый шаблон графика), который представляет собой набор тройных шаблонов, выполняется как блок (по сути), механизм может свободно изменять порядок шаблонов в BGP для достижения оптимальной производительности. Например, рассмотрим следующий BGP:
?a :someProperty ?b .
?c :anotherProperty ?d .
?b a :Class .
Выполнение запроса в виде запроса требует декартового произведения, поскольку результаты первого шаблона не пересекаются со вторым шаблоном, поэтому результаты первых двух шаблонов являются декартовым произведением их отдельных результатов. Этот результат будет содержать гораздо больше результатов, чем нам нужно на самом деле, поскольку третий шаблон ограничивает возможные результаты первого шаблона, но мы не применяем это ограничение до тех пор. Но если мы изменим порядок так:
?b a :Class .
?a :someProperty ?b .
?c :anotherProperty ?d .
Нам все еще понадобится декартово произведение, чтобы получить окончательные результаты, так как 2-й и 3-й паттерны все еще не пересекаются, но при переупорядочении мы ограничиваем размер результатов 2-го паттерна, что означает, что размер нашего декартового произведения будет намного меньше .
Есть несколько других оптимизаций, которые мы делаем, но я не собираюсь публиковать их здесь, поскольку они начинают довольно подробно обсуждать внутреннюю часть механизма SPARQL. Если кому-то интересно узнать подробности, просто оставьте комментарий или отправьте мне твит @ RobVesse