| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > PHP: Для профи > находнение всех путей в графе |
| Автор: xber9 31.10.2012, 13:44 | ||
| народ привет не знаю насколько вопрос подходит теме (если что перенесет) и так есть граф описывающий метрополитен Москвы и функция которая ищет минимальный путь от а до б
я понимаю что эта функция ищет минимальное расстояние в зависимости от количества пройденных точек но мне нужно чтобы она искала ни минимальный путь, а путь с минимумом пересадок с ветки на ветку я вижу это так, что сначала мне надо получить все возможные пути из А в Б а потом их проверять на наличие пересадок как проверять я себе тоже представляю (сделать массив с пересадками и проверять соответствия ) но как заставить мою функцию вернуть все возможные пути я не знаю помогите изменить функцию чтобы она возвращала все возможные пути от А в Б заранее спасибо |
| Автор: skyboy 31.10.2012, 18:15 |
| если опишешь, как в настоящий момент находишь минимальный путь(название алгоритма, или словесное описание), перенесу в раздел "Алгоритмы" |
| Автор: xber9 1.11.2012, 12:53 |
| Алгоритмы можно вкратце описать так: для вершины, которую мы еще не посетили, нужно отыскать все еще не посещенные смежные вершины и повторить поиск для них то есть поиск в глубину |
| Автор: skyboy 1.11.2012, 15:49 | ||||
| тебе надо кастомизировать алгоритм добавлением весов. то есть, вместо
использовать
а path_length для станции на той же ветке добавляет +1, а для станции другой ветки(пересадка) — скажем, +3. |
| Автор: baldina 1.11.2012, 18:06 |
поищи в ширину. погляди алгоритм Дейкстры |
| Автор: xber9 1.11.2012, 19:08 |
искал но е понял как можно реализовать чтобы использовать такую запись данных как уменя ибо данные уже готовы а как все это интерпритировать в матрицу смежности не знаю |
| Автор: skyboy 1.11.2012, 20:58 | ||
во-первых, тебе нужно решить, какой вес будет у пересадки. то есть, начиная с какого количества "проехать лишние N станция без пересадок" предпочтительнее, чем совершить одну пересадку и не ехать эти самые N станций. во-вторых, count($newpath) — это простейший алгоритм рассчета "длины пути" — каждая станция считается за единицу. чем больше станций — тем больше сумма — тем больше длина. я ж предлагаю вместо count использовать самописную функцию, которая для заданного списка станций будет увеличивать значение длины пути на 1 для каждой станции, кроме пересадочных. А для станций пересадки — увеличивать сразу на N. |
| Автор: xber9 1.11.2012, 21:17 | ||
то есть мне надо сделать массив в котором будут все id станций с которых можно сделать пересадку "самописная" функция принимает в себя массив точек и для каждой из них проверяет принадлежит ли она массиву пересадок если принадлежит то возвращаемое значение увеличивается на какое то большое число если нет то увеличивается на 1 я правельно понимаю или что то не так |
| Автор: baldina 1.11.2012, 22:52 | ||
у тебя списки смежности. все реализуемо. Добавлено через 1 минуту и 18 секунд если задача требует, можно и по-другому приготовить, не правда ли? хотя в данном случае и так пойдет Добавлено через 5 минут и 23 секунды поглядел, вижу что не прав. но все равно реализуемо. требуемая для dfs и bfs информационная операция на графе всего лишь одна - для данного узла получить список узлов, в которые ведут исходящие ребра. |
| Автор: xber9 1.11.2012, 23:33 |
переделывать в матрицу не времени так что придктся юзать глубину |
| Автор: baldina 2.11.2012, 08:59 |
изучать калькулятор времени нет, поэтому будем считать в столбик. xber9, не решишь эту задачу поиском в глубину. поглядел еще раз, опять вижу списки смежности. вчера мозг устал. так вот, переделывать в матрицу необходимости нет. |
| Автор: xber9 2.11.2012, 13:04 | ||
смотрел вчера на вики реализацию на http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B#.D0.9F.D1.81.D0.B5.D0.B2.D0.B4.D0.BE.D0.BA.D0.BE.D0.B4 но моих мозгов не хватает чтобы понять как это померкнуть на php и использовать свои списки (нашел 1 реализацию на javasctript которую можно на php перекинуть но там матрица так что я в тупике увы |
| Автор: xber9 2.11.2012, 15:44 | ||
| вот та самая функция переведенная на пхп а как ее для моих данных адаптировать?
|
| Автор: Aliance 2.11.2012, 18:04 |
| |
| Автор: xber9 2.11.2012, 18:39 |
| увы но как я и говорил код не мой |
| Автор: baldina 2.11.2012, 18:58 | ||||||
обобщенный поиск в ширину
эта функция не зависит от представления графа, для адаптации к конкретному представлению служит функция get_adjacent (); реализация bfs не самая общая, но достаточная для наших целей: для каждой посещенной вершины вызывается пользовательская функция-посетитель $current(), куда передается ребро (текущая вершина и та, из которой мы сюда пришли). реализация функции-посетителя для алгоритма поиска кратчайщих путей по Дейкстре:
она почти тривиальна, в качестве веса любого ребра используется единица (в вашем графе веса не указаны, поэтому я не стал усложнять). в глобальных массивах $cost и $path хранятся стоимости(длины) путей и сами пути соответственно что бы применить это к вашей структуре нужен адаптер. в данном случае он тривиален:
ну вот и все, остальное самостоятельно допилите http://codepad.org/d2eGCrci |
| Автор: baldina 2.11.2012, 20:04 | ||
для минимизации пересадок измените вес для пересадки (уже говорили про это) кстати, вам нужно минимум пересадок или минимальное время? |
| Автор: xber9 2.11.2012, 20:05 |
| огромное спаисбо зхавтар буду разбираться если что надеюсь поможете но думаю все норм еще рас спс Добавлено @ 20:08 вообще то и то и то в зависимости от выбора пользователя кстати как правельно задать веса для пересадок? как отдельный массив ? и проверять принадлежит ли дуга VU этому массиву и если да то делатть не +1 а +много или как? |
| Автор: baldina 3.11.2012, 13:32 | ||
по разному можно. например, опциональным параметром (т.е. элемент массива смежности может быть массивом (станция, вес) более правильно, думаю, задавать веса для всех ребер (значения времени в минутах, например), включая время пересадок. но если вводить вес, программу придется немного переделать: мой dijkstra_visitor() по сути relax_visitor(), они совпадают для невзвешенного графа, а для взвешенного графа dfs bfs с обычной очередью недостаточно, нужно иметь очередь с приоритетами. Добавлено @ 13:39
можно и так, можно добавить явные пути для пересадок, можно, как я выше написал. зависит от желаемого результата и возможных расширений в будущем. если приоритет пересадки делать заведомо большим, чем время обычного проезда до следующей станции, пересадки будут выбираться, только если нет другого пути. для себя, например, я определил, что среднее время между станциями и среднее время одной пересадки - 2.5мин. это, конечно, не дает наименьшее число пересадок, но время предсказывает хорошо и дает быстрые пути. для бабушки, кторая не может бегать между станциями, пересадка может стоить и 10мин. |
| Автор: xber9 3.11.2012, 13:41 | ||||||
извиняюсь но я практически ничего не понял из этой фразы где об этом можно почитать или может если для вас это не слишком затруднительно покажете как изменить ваш пример ( конечно если не об очень многом прошу) еще рас прошу прощения если очень сильно напрягаю и туплю Добавлено @ 13:48
идея со временем кажется самое то тк время пути тоже надо будет подсчитывать я так понимаю вы предлагаете изменить исходные данные типа так
но тогда как менять фунцию ибо я как всегда не понимаю (не хватает математических знаний как я пологаю) |
| Автор: baldina 3.11.2012, 14:43 |
| да, фраза не очень понятная))) и с ошибкой: не dfs, а bfs - поиск в ширину в поиске в ширину в очередь заносятся смежные вершины, потом из очереди вынимаются и обрабатываются. если весов нет, длина пути соответствует числу проходимых вершин если веса есть, нужно из очереди выбирать вершину с наименьшим весом(приоритетом), поэтому требуется очередь с приоритетами (это и будет алгоритм дейкстры). в любом алгоритме поиска кратчайших путей (в т.ч. в простейшем на основе поиска в ширину) используется т.н. функция relax для релаксирования путей, т.е. поддержания списка кратчайших путей и их весов. для очередей с приоритетами в php можно использовать класс http://www.php.net/manual/ru/class.splminheap.php любая книга по алгоритмам, http://en.wikipedia.org/wiki/Breadth-first_search http://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%94%D0%B5%D0%B9%D0%BA%D1%81%D1%82%D1%80%D1%8B да, что-то типа этого. Добавлено через 1 минуту и 9 секунд будет время, попробую написать, но позже... |
| Автор: xber9 3.11.2012, 15:52 |
если будет возможность напишите плиз ибо сам я не уверен что до конца разберусь |
| Автор: baldina 4.11.2012, 12:24 | ||
| вот http://codepad.org/OoaxvDF9 это многословнее, чем раньше, но подходит для адаптации к разным представлениям графа и алгоритмам Добавлено через 8 минут и 34 секунды кстати, простейшая модификация первой реализации для работы с весами - просто перенести вызов $current:
Это будет некая разновидность алгоритма Беллмана-Форда. Для графов без отрицательных весов этот алгоритм менее эффективен, чем Дейкстры, но для пары сотен вершин и ребер думаю разница несущественная. |
| Автор: xber9 4.11.2012, 16:54 | ||
большое спасибо очень выручил- буду постепенно разбираться я правельно понимаю что для того чтобы считался путь с минимумом пересадок достаточно значительно увеличить вес пересадки а чтобы искал просто кратчайший путь то надо обратно уменьшить вес и еще вопрос ( так как еще не разобрался) как вывести на печать общий вес пути from - to |
| Автор: baldina 4.11.2012, 17:35 | ||||
да. кстати, минимум пересадок может давать очень плохие пути. например, динамо-савеловская через тверскую. даже бабушка так не поедет. содержится в
|
| Автор: xber9 4.11.2012, 18:03 | ||
я понимаю поэтому буду давать пользователю выбор как ему посчитать мин времени или мин пеерсадок >динамо-савеловская через тверскую я поеду так как инвалиду легче дальше проезхать чем ходить по переходам) еще рас спасибо |
| Автор: xber9 4.11.2012, 23:05 | ||||
| НЕ охото начинать новую тему поэтому спрошу тут переделал данные вот так
где t1....t4 времена ( веса) для пересадок далее при определнных условиях я делаю так
однако данные внутри описания графа ($graph) отсались прежними а не =100 вопрос как переинициализоваровать граф чтобы туда записались сотни ( надеюсь понятно обьяснил) |
| Автор: xber9 4.11.2012, 23:20 |
| или как по другому изменять веса для пересадок при определенных условиях |
| Автор: baldina 5.11.2012, 00:47 | ||||||||
ситуация аналогична такой:
варианты решения:
а самый простой и правильный вариант вероятно такой:
|
| Автор: xber9 5.11.2012, 10:49 |
| в моем случае удобней по ссылке спсибо |
| Автор: xber9 6.11.2012, 21:41 |
| tobaldina привет сново проблема загрузил твой код на хостинг от агвы и выяснилось что он не работает хотя у меня дома на денвере все норм на агаве при вызове скрипта ругается так Parse error: parse error, unexpected T_STRING, expecting T_OLD_FUNCTION or T_FUNCTION or T_VAR or '}' in /home/interes1/public_html/metro/ROTES.php on line 9 9ая строка это private $marks = array(); помоги плиз Добавлено через 14 минут и 44 секунды на хосте php 4 |
| Автор: xber9 6.11.2012, 22:06 |
| вопрос уже не срочный так как нашел где в агаве перекючить на php5 но если будет время напиши ) |
| Автор: baldina 6.11.2012, 22:24 | ||
я уже не помню, что было в php4, старье ведь. на php.net написано
так что неудивительно... последняя версия php - 5.4, там много интересных вещей, а поскольку я писал на codepad, использовались средства не выше 5.2.5 и spl на codepad нет, поэтому класс очереди на основе SplHeap закомментирован Добавлено через 1 минуту и 40 секунд видимо private не понравилось |
| Автор: xber9 13.11.2012, 22:36 | ||
| to baldina Привет сново я со своим метро и с проблемами) на основе твоего кода(поменял только формат вывода) сделал схему метро ( еще не все ветка описаны но все же) http://interesnayamoskva.ru/maps.php в результате выяснилось что не всегда выдает самый короткий ( по времени=весу) маршрут (тоесть посылает через ж...) конкретный пример начальная точка - театральная ( темно зеленая ветка), конечная -красные ворота (красная ветка), в данном случае функция посылает через третьяковку вместо Охотного ряда хотя если начальную и конечную точки поменять местами то посылает нормально то же самое если начальная =боровицкая ( серая ветка) конечная = красные ворота ( или любая станция за ними вверх) я не могу понять в чем проблемап очень прошу помогите ЗЫ при клике по станции на сайте вылезает окошко с id станции в графе вот описание графа
|
| Автор: xber9 13.11.2012, 23:23 |
| офтоп ошибочное сообщение |
| Автор: xber9 13.11.2012, 23:55 |
такое ощущение что выбирает первый попавшийся путь а не путь с наименьшим весом |
| Автор: baldina 14.11.2012, 11:21 |
| Весь код покажите |
| Автор: xber9 14.11.2012, 11:42 | ||||
| весь код ваш же полносью вот
то что инклюдит это те данные что привел выще если надо то от страницы делаю запрос на jquary так
|
| Автор: baldina 15.11.2012, 17:08 |
| да, у меня ошибка. не тот приоритет передавался в очередь. поглядите http://codepad.org/qB803rhG |
| Автор: xber9 15.11.2012, 22:04 |
| работает отлично - большое спс но хотелось бы понять что было не так - я все еще пытаюсь разобраться как это все работает |
| Автор: baldina 16.11.2012, 15:12 |
| не так был приоритет узла в очереди: передавался вес последнего ребра, а надо было передавать вес всего пути. сравните код, поймете Добавлено через 9 минут и 49 секунд теперь вам надо очередь перевести на SplHeap или свою пирамиду написать: http://ru.wikipedia.org/wiki/%D0%94%D0%B2%D0%BE%D0%B8%D1%87%D0%BD%D0%B0%D1%8F_%D0%BA%D1%83%D1%87%D0%B0 |