Даже описать эту проблему сложно, но я попробую.Я боролся с этим в течение нескольких дней и решил спросить здесь.
Хорошо, поэтому я пытаюсь смоделировать «понятия» или «вещи», как я их называю.Просто понятия в общем.Это связано с логикой обработки.
Итак, каждая «вещь» определяется ее отношением к другим вещам.Я храню это как набор из 5 битов на отношения.«Вещь» может быть такой:
class Thing {
char* Name;
HashTable<Thing*, int> Relationships;
}
Итак, я моделирую «Вещи» вот так.5 бит на отношения.Каждый бит обозначает одно возможное отношение.Примерно так: 1 равно, 2 внутри, 3 снаружи, 4 содержит, 5 перекрытий.Наличие всех 5 битов означает, что мы совершенно не знаем, каковы отношения.Наличие 2 бит означает, что мы думаем, что отношения могут быть одной из двух возможностей.Отношения начинаются как «неизвестно» (все 5 битов верны) и становятся более конкретными с течением времени.
Так вот, как я моделирую увеличение знаний со временем.Вещи начинаются в полностью неизвестном состоянии, могут проходить через частично известные состояния и могут достигать полностью известных состояний.
Немного больше предыстории:
Я пытаюсь добавить дополнительное определение в моё моделирование«концепций» (вещей), используя дополнительные классы.Например:
class ArrayDefinition {
Array<Thing> Items;
}
И мой класс Thing выглядит следующим образом:
class Thing {
char* Name;
HashTable<Thing*, int> Relationships;
ArrayDefinition* ArrayDef;
}
Этот «ArrayDef» НЕ ДОЛЖЕН использоваться.Это просто для использования, если это необходимо.Некоторые «вещи» не имеют массивов, некоторые имеют.Но все «вещи» имеют отношения.
Я могу обработать это «определение массива», чтобы выяснить отношения между двумя вещами!Например, если X = [ A B C D E ]
и Y = [ C D E ]
, мой код может обработать эти два массива и выяснить, что "Y inside X
".
ОК, так что достаточно фона.Я объяснил основную проблему, избегая моего реального кода, который содержит всевозможные отвлекающие детали.
Вот проблема:
Проблема в том, что это не работает смехотворно медленно.
Представь, есть 2000 "вещей".Допустим, 1000 из них имеют определения массивов.Теперь это дает 500 000 (ish) возможных «пар массивов», которые нам нужно сравнить друг с другом.
Я надеюсь, что теперь я наконец-то обретаю смысл.Как избежать обработки их всех друг против друга?Я уже понял, что если две «вещи» имеют полностью известные отношения, нет смысла сравнивать их «определения массивов», потому что это просто используется для выяснения дополнительных деталей об отношениях, но у нас есть точные отношения, поэтомунет никакого смысла.
Итак ... скажем, только 500 из этих "вещей с массивами" имеют неизвестные или частично известные отношения.Это все еще делает 250000 (ish) возможными «парами массивов» для сравнения!
Теперь ... для меня, наиболее очевидное место для начала, это понимание того, что, если отношения, используемые для определения двух массивов, не изменяются (становитсяболее конкретно), то нет смысла обрабатывать эту «пару-массив».
Например, скажем, у меня есть эти два массива:
X = [ A B C D E ]
Y = [ Q W R T ]
сейчас, если я скажу, что T=R
, это очень мило.Но это не влияет на отношения между X и Y. Так что только потому, что отношение T к R стало известно как «равное», тогда как прежде, чем оно могло быть полностью неизвестно, это не означает, что мне нужно снова сравнивать X и Y.
С другой стороны, если я скажу "T outside E
", это отношения между вещами, используемыми для определения двух массивов.Поэтому, сказав, что «T outside E
» означает, что мне нужно обработать массив X против массива Y.
Я действительно не хочу сравнивать 500 000 «пар-массивов» только для обработки логики на 1000 массивах, когда почтимежду ними ничего не изменилось!
Итак ... моя первая попытка упростить это - сохранить список всех массивов, которые используются для определения вещи.
Допустим, у меня есть3 массива:
A = [ X Y Z ]
B = [ X X X X ]
C = [ X Z X F ]
Ну, X используется в 3 массивах.Таким образом, X может хранить список всех массивов, внутри которых он используется.
Итак, если бы я сказал "X inside Y"
, это могло бы вызвать список всех массивов, которые Y используется для определения, и все массивы X используются для определения. Допустим, X используется в 3 массивах, а Y используется в 1 массиве. Из этого мы можем выяснить, что есть 2 «пары массивов», которые нам нужно сравнить (A против B и A против C).
Мы можем дополнительно урезать этот список, проверив, имеет ли какая-либо из пар массивов уже полностью известные отношения.
У меня проблема с этим, это все еще кажется чрезмерным.
Скажем, X - это действительно распространенная "вещь". Он используется в 10 000 массивов. И Y - действительно распространенная вещь, используемая в 10 000 массивов.
Я все еще получаю 100 000 000 пар массивов для сравнения. Итак, допустим, мне не нужно сравнивать их все, на самом деле, только 50 из них были частично известны или совершенно неизвестны.
Но ... Мне все равно пришлось просмотреть список из 100 000 000 пар массивов, чтобы выяснить, какая из них была частично известна. Так что это все еще неэффективно.
Мне действительно интересно, нет ли эффективного способа сделать это. И если на самом деле все, что я могу сделать, это сделать несколько эффективных "эвристических" стратегий. Мне еще не повезло, когда я придумал хорошие стратегии.
Я понимаю, что эта проблема очень узкая. И я понимаю, что чтение этого длинного поста может занять слишком много времени. Я просто не знаю, как уменьшить длину поста или описать это с точки зрения более распространенных проблем.
Если это поможет ... Моя лучшая попытка выразить это в общих терминах - это "как сравнить только те списки, которые были обновлены".
У кого-нибудь есть идеи? Это было бы прекрасно. Если нет ... возможно, только я, написав это, может помочь моему мыслительному процессу.
Дело в том, что я просто не могу помочь, но чувствую, что есть какой-то алгоритм или подход, который может сделать эту проблему быстрой и эффективной. Я просто не знаю, что это за алгоритм.
Спасибо всем