Претрага са нехронолошким враћањем
Претрага са нехронолошким враћањем (енгл. Backjumping) је техника која повећава ефикасност бектрекинг алгоритама. Бектрекинг увек иде један ниво унатраг у стаблу претраге када су тестиране све вредности за променљиву, док се претрагом са нехронолошким враћањем може ићи више нивоа унатраг. У овом чланку се користи статички поредак променљивих , али се иста правила односе и на динамички.
-
Стабло претраге посећено регуларним бектрекингом
-
Скок унатраг: сиви чвор није посећен
Дефиниција
[уреди | уреди извор]Кад год су бектрекингом испробане све вредности за променљиву без проналаска решења, преиспитује се последња од раније додељених променљивих, мења јој се вредност или се наставља бектрекинг ако нема других вредности за доделу. Ако је тренутна делимична додела и све вредности за су испробане без проналаска решења, закључује се да решење са не постоји. Алгоритам потом "иде горе" на и мења јој вредност ако је могуће, у супротном поново врши бектрекинг.
Није увек неопходна цела делимична додела да би се доказало да ниједна вредност не води до решења. Префикс делимичне доделе може имати исте особине, то јест, постоји индекс тако да ни са једном вредношћу не води до решења. Ако алгоритам то може доказати, онда ће одмах разматрати друге вредности за уместо разматрања .
Ефикасност алгоритма претраге са нехронолошким враћањем зависи од тога колико далеко се може враћати. У идеалном случају, алгоритам би могао да се врати из до било које променљиве такве да не формира решење ни са једном вредношћу . Ако је то случај, се зове сигуран скок.
Није увек могуће утврдити да ли је скок сигуран, јер су сигурни скокови дефинисани у смислу скупа решења, а то је оно што алгоритам покушава да пронађе. У пракси, алгоритми претраге са нехронолошким враћањем користе најнижи индекс за који могу ефикасно доказати да је сигуран скок. Различити алгоритми користе различите методе за утврђивање да ли је скок сигран. Они имају различите трошкове, али се велика цена проналажења већег сигурног скока може смањити редукованом претрагом услед прескакања делова стабла претраге.
Претрага са нехронолошким враћањем на листовима
[уреди | уреди извор]Најједноставније стање у коме је могућа претрага са нехронолошким враћањем је када је за све вредности променљиве доказано да су неконзистентне без даљег гранања. Делимична евалуација је конзистентна ако и само ако задовољава сва ограничења додељених променљивих, а у супротном је неконзистентна. То може бити случај када се конзистентно делимично решење не може проширити до конзистентног комплетног решења јер неке од недодељених променљивих не могу бити додељене без нарушавања других ограничења.
Стање у коме су све вредности дате променљиве неконзистентне са тренутним делимичним решењем се зове лист ћорсокак. То се дешава управо када је променљива лист стабла претраге.
Gaschnig-ов алгоритам претраге са нехронолошким враћањем врши скок унатраг само у листу ћорсокаку. Другим речима, ради другачије од бектрекинга само када су све могуће вредности тестиране и неконзистентне без потребе за гранањем у другу променљиву.
Сигуран скок се може наћи једноставно, за сваку вредност , тражи се најкраћи префикс од неконзистентан са . Другим речима, ако је могућа вредност за , алгоритам проверава конзистентност следећих евалуација:
... | ||||
... | ||||
... | ||||
Најмањи индекс (најнижи унос) за који су евалуације неконзистентне би био сигуран скок да су једине могуће вредности за . Пошто свака променљива обично може имати више од једне вредности, максималан индекс који је добијен провером за сваку вредност је сигуран скок, и то је тачка у коју скаче Gaschnig-ов алгоритам.
У пракси, алгоритам може да испита евалуације изнад док проверава конзистентност .
Претрага са нехронолошким враћањем на унутрашњим чворовима
[уреди | уреди извор]Претходни алгоритам врши нехронолошко враћање само када се вредности променљиве могу показати неконзистентне са тренутним делимичним решењем без даљег гранања. Другим речима, дозвољава се нехронолошко враћање само на листовима у стаблу претраге.
Унутрашњи чвор стабла претраге представља додељену променљиву која је конзистентна са претходним. Ако та додела не даје ниједно решење, претходни алгоритам увек врши бектрекинг: ниједно нехронолошко враћање неће бити извршено у том случају.
Претрага са нехронолошким враћањем на унутрашњим чворовима не може да се изврши као на листовима. Заиста, ако неке евалуације од захтевају гранање, то је зато што су конзистентне са тренутном доделом. Као резултат, потрага за префиксом који је неконзистентан са овим вредностима последње променљиве није успешна.
У таквим случајевима, оно што доказује да неће бити део решења са тренутном делимичном евалуацијом је рекурзивна претрага. Посебно, алгоритам "зна" да ниједно решење не постоји од тог тренутка зато што се враћа у тај чвор уместо да се заустави након што је пронашао решење.
Овај повратак је изазван великим бројем ћорсокака, и указује где је алгоритам доказао да је делимично решење неконзистентно. Да би наставио нехроночошко враћање, алгоритам мора имати у виду да решења није могуће наћи због тих ћорсокака. Посебно, сигурни скокови су индекси префикса који и даље чине ћорсокаке неконзистентним делимичним решењима.
Другим речима, када су све вредности испробане, алгоритам може да се врати на под условом да је тренутна истинита евалуација од неконзистентна са свим истинитим евалуацијама од у листовима који су потомци чвора .
Поједностављења
[уреди | уреди извор]Због потенцијално великог броја чворова који су у подстаблу од , информација која је неопходна да би се безбедно нехронолошки вратило од , се прикупља за време проласка кроз његово подстабло. Проналажење сигурног скока може бити поједностављено помоћу два разматрања. Прво је да је алгоритму потребан сигуран скок, али и даље може да ради са скоком који није највиши могући сигуран скок.
Друго је то да чворови у подстаблу , који су били прескочени нехронолошким враћањем, могу бити занемарени за време тражења нехронолошког враћања за . Прецизније, сви чворови прескочени нехронолошким враћањем од чвора до чвора могу бити заменарени у односу на подстабло чији је корен у , као и њихова остала подстабла.
Заиста, ако се алгоритам спусти од чвора до али се нехронолошки врати до самог почетка, онда би уместо тога могао да прође директно од до . Заиста, нехронолошко враћање указује на то да су чворови између и стварно од мање важности подстаблу чији је корен у . Другим речима, нехронолошко враћање указује на то да је посећивање области стабла претраге била грешка. Овај део стабла претраге може бити занемарен узимајући у обзир могуће нехронолошко враћање од или једног од његових предака.
Ова чињеница може бити искоришћена прикуљањем, у сваком чвору, скупа од претходно додељених променљивих чија евалуација не може да докаже да не постоји решење у подстаблу чији је корен у чвору. Овај скуп се прави за време рада алгоритма. При повлачењу из чвора, овај скуп се брише заједно са променљивом чвора и прикупља се у скупу одредишта бектрекинга или нехронолошког враћања. Пошто се чворови који су прескочени нехронолошким враћањем не могу повући, њихови скупови се аутоматски игноришу.
Графовски засновано нехронолошко враћање
[уреди | уреди извор]Образложење графовски заснованог нехронолошког враћања је у томе да сигуран скок може бити пронађен провером да ли су променљиве конзистентне са променљивама које су инстанциране у листовима. За сваки леви лист и сваку променљиву за индекс који је инстанциран, индекси мањи или једнаки чија је променљива конзистентна са , могу бити коришћени за проналажење сигурног скока. Нарочито, када су све вредности за испробане, овај скуп садржи индексе свих променљивих чије евалуације успевају да докажу да не постоји решење које може бити пронађено посећивањем подстабла чији је корен у . Као резултат, алгоритам се може нехронолошки вратити у највећи индекс у скупу.
Чињеница је да чворови прескочени нехронолошким враћањем могу бити занемарени узимајући у обзир да даље нехронолошко враћање може бити експлоатисано наведеним алгоритмом. При повлачењу из листа, скуп променљивих које ограничене са њим бива креиран и "послат назад" до његовог родитеља, или претка у случају нехронолошког враћања. Скуп променљивих се одржава на сваком унутрашњем чвору. Сваки пут када се скуп променљивих добије од детета или потомка, њихове вредности се додају у одржавани скуп. При даљем бектрекингу или нехронолошком враћању од чвора, променљива чвора се уклања из скупа, и скуп се шаље до чвора одредишта бектрекинга или нехронолошког враћања. Овај алгоритам ради јер одржавани скуп у чвору скупља све променљиве битне за доказивање неправилности у листовама који су потомци чвора. Пошто се скупови променљивих шаљу само за време повлачења из чворова, скупови сакупљени на чворовима прескоченим нехронолошким враћањем бивају занемарени.
Нехронолошко враћање засновано на сукобима
[уреди | уреди извор]Прерађени алгоритам са нехронолошким враћањем, који може да постигне веће нехронолошко враћање, је базиран не само на проверавању присуства две променљиве у истом ограничењу већ и на проверавању да ли је ограничење изазвало неконзистентност. Нарочито, овај алгоритам прикупља једно од нарушених ограничења у сваком листу. У сваком чвору највећи индекс променљиве који је у једном од ограничења, прикупљен на листовима, представља сигуран скок.
Нарушено ограничење одабрано у сваком листу не утиче на безбедност резултујућег скока. Бирање ограничења највећег могућег индекса повећава висину скока. Из овог разлога, нехронолошко враћање засновано на сукобу нумерише ограничења на такав начин да су мањи индекси већег приоритета у односу на ограничења већих индекса.
Формално, ограничење је већег приоритета у односу на ако су највећи индекси променљиве у мањи у односу на највеће индексе променљиве у . Другим речима, изузимајући заједничке променљиве, ограничење које има све мање индексе има већи приоритет.
На листу, алгоритам бира најмањи индекс тако да су неконзистентни са последњном евалуираном променљивом на листу.
Међу ограничењима која су нарушена у евалуацији, алгоритам бира оно са највећим приоритетом, и прикупља све његове индексе мање од . На овај начин, када се алгоритам врати до променљиве , најмањи прикупљени индекс представља сигуран скок.
У пракси, алгоритам је поједностављен тако што прикупља све индексе у једнан скуп, уместо креирања скупа за сваку вредност . Нарочито, алгоритам прикупља, у сваком чвору, све скупове који долазе од њихових потомака који нису били прескочени нехронолошким враћањем. При повлачењу из овог чвора, скуп заједно са променљивом се брише из чвора и прикупља се у одредишту бектрекинга или нехронолшког враћања.
Литература
[уреди | уреди извор]- Dechter, Rina (2003). Constraint Processing. Morgan Kaufmann. ISBN 978-1-55860-890-0.
- Prosser, Patrick (1993). Hybrid Algorithms for the Constraint Satisfaction Problem (PDF). Computational Intelligence 9(3). Архивирано из оригинала (PDF) 06. 02. 2012. г. Приступљено 12. 05. 2016.