powered by simpleCommunicator - 2.0.30     © 2024 Programmizd 02
Map
Форумы / Java [игнор отключен] [закрыт для гостей] / Java :: Пятничное схлопывание толстых графов.
25 сообщений из 71, страница 1 из 3
Java :: Пятничное схлопывание толстых графов.
    #39997802
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Привет.

В продолжне архивариуса https://www.sql.ru/forum/1282300/chetvergovyy-arhivarius

Возникла прикладная задача из двух частей.

Часть 1. Схлопывание мостов.

Дано: орграф произвольного вида. 50 тысяч вершин и примерно 260 тысяч рёбер.
По статистике которую я собирал каждая вершина имеет примерно 5 исходящих ребер.

Необходимо: программно удалить рёбра типа (4)->(5) как на картинке.
После удаления ребра - вершины (4) и (5) схлопываются и создаётся новая
вершина с новым идентификатором из свободных. Например (50000).


При этом входящие связи в (4) и исходящие из (5) сохраняются.

Часть 2. Разгон

Оптимизировать этот-же алгоритм с учотом мультипоточности.

Исходные данные.

Еще не готовы. Но я опубликую чуть позже набор ребер со связями в текстовом виде (CSV)

Картинке соотвествует примерно такой файл.
Код: sql
1.
2.
3.
4.
5.
6.
7.
1,4
2,4
3,4
4,5
5,6
5,7
....


Ребра имеют ориентацию поэтому 1,4 и 4,1 это разные рёбра.

Приветствуется

- любая реализация на Java / Kotlin / Scala.
- мультипоточка, стримы, коллекции
- примитивы синхронизации

Go-go писать код.
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39997811
Sergunka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

Схлопывать только вершины соединенные одной веткой? А какая скорость обработки должна быть по ТЗ? 50 тысяч вершин довольно небольшой объем там особо мультипоточность даром не упала так как все разместится в памяти все можно через хештейбл реализовать.
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39997813
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Попробуем.
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39997814
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Данные готовы. Первый том.
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39997815
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Второй
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39997816
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хопа.
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39997817
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39997818
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И еще
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39997820
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Фух. Последний.

Пробуйте.
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39997955
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
UP. Any updates?
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39998009
Sergunka
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton
UP. Any updates?


можно по подробней, какой файл финальный и сколько там данных?

На мой взгляд там довольно прозрачная структура данных намечается, все вершины где входящий один будут всхлопнуты, что довольно быстро определяется. по О натации алгоритм должен сработать за O(N+m) времени где m - число точек всхлапывания, N - все точки.

Не совсем ясно допускаются ли паралельные дуги и петли т.е. когда две точки графа соединены двумя одинаково ориентированными ребрами и когда дуга (ребро с направлением) делает петлю т.е. к примеру 4,4

Но вцелом очень козырная задача... редкая находка в наши дни борьбы за деньзнаки.
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39998042
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я опубликовал финальный файл. В нем 48955 вершин и 258215 связей между ними.

Я пытался решать эту задачу используя матрицу смежности. В родительском топике. Но мне не хватило
памяти для массива. Произведения 50000 на 50000 давало величину в штуках больше чем индекс
массива в Java. И это только первое ограничение. И если массив я просто преодолел разбивая
матрицу на слои как торт. То второе ограничение - медленная скорость поиска смежных вершин
по матрице - я не преодолел.

Это - слабое место структуры данных и я полностью отказался от матрицы. Заменил ее на список
вершин где для каждой вершины есть списки входящих и исходящих ребер.

Фрагмент вершины
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
public class Vertex implements Serializable {

    static final long serialVersionUID = 1L;

    // Key fields
    private String id;

    // Non-key fields
    private List<Edge> outgoingEdges = new ArrayList<>();
    private List<Edge> incomingEdges = new ArrayList<>();

    public Vertex(@NotNull String id) {
        this.id = id;
    }

    public Vertex() {
        // For serialization
    }

    // Incoming edges

    void addIncomingEdge(@NotNull Edge edge) {
        checkArgument(edge.getV2() != this, "Unable to link edge " + edge.toString() + " because of illegal V2 value");
        incomingEdges.add(edge);
    }
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39998044
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
По алгоритму. Что я еще не учел? Возможно кейсов схлопывания больше чем я нарисовал на картинке.
Возможно петли и циклы не запрещают нам это сделать. Я чуть позже приаттачу еще одну картинку
где есть частные случаи.
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39998048
Alexander A. Sak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Базистам эту задачу решать можно?

Сделать таблицу WAR_AND_SEC(A number, B number), залить туда CSV, наделать апдейтов и выгрузить обратно.

Для H2 DB создание+загрузка выглядит так:
Код: plsql
1.
create table WAR_AND_SEC(a bigint, b bigint) as select * from csvread('PATH_TO_CSV', 'a,b')



Кандидаты на схлопывание:
Код: plsql
1.
select a, b from WAR_AND_SEC where a in (select a from WAR_AND_SEC group by a having count(*)=1)



Схлопывание - это обновление A и B новыми значениями плюс удаление записи.
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39998049
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да. Да. Базистам это решать можно. Всем можно. Но я просто по инерции продолжал тему оптимизации текстовых
литературных графов. Просто сама постановка была настолько интересно что я решил ее очистить от ненужной
шелухи и выдать отдельным топиком как чистую алгоритмизацию на Java.

Реляционки обычно плохо справляются с графовыми задачами но если вы это сделаете - то у нас будет
еще и повод просто сравнить время отклика для двух одинаковых исходных данных в Pure-Java и H2-Java.
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39998062
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще несколько кейсов. На картинке.

Case (1)

Одно-направленная цепочка смежных вершин (chain) должна быть схлопнута в 1 вершину если нет
прочих входящих и исходящих ребер в середине этой цепочки.

Case (2)

Дву-направленная цепочка не схлопыватеся.

Case (3)

Вот такой вод ориентированный подграф схлопывает цепочки { 1->2->3 } и создает новую вершину 9
Это простой случай.

А вот с {3 -> 4 -> 5 -> 6 } несмотря на то что образуют цикл тем не менее могут быть схлопнуты в части
{4 -> 5-> 6 } т.к. топологически мы не нарушаем структуру которая была. Просто выбрасываем лишнее.

И на рисунке (4) - результат.
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39998135
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну что. Идей нету? Брейншторм?

Algorithm: GraphEdgeSimplification-alg-0.1

1.Дано. Орграф. G(V,E),
2.Для всех ребер. Ei={Vin,Vout}, удалить ребро если вершины входящие
в Vin и исходящие из Vout дают в пересечении пустое множество.
3.Повторять пункт (2) для всех ребер пока граф изменяется.
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39998152
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сидение на этом форуме несет два смысла. Первое - это решать продуктовые проблемы. Чем ты занят.

И второе - это просто for fun. То чем занят я.
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39998162
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Zzz79,

Тебя просто к нормальным задачам не подпускают. Хотя ты прав в том что такие задачи достаются меньшинству. Но чтобы их получить нужно иметь некий уровень знаний.
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39998181
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Zzz79
и охота тебе этой дичью заниматься)
Повторю ещё раз: "Сорок лет ума нет и не будет". И это - не про mayton
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39998182
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
забыл ник
просто к нормальным задачам не подпускают.
Просто фигни больше и кто-то должен делать и её.
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39998323
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Может я чего не понял, но если ноды схлопываются только в том случае, когда между ними единственный маршрут, то для каждой пары нод нужно искать путь из одной ноды в другую.

Сложность "тупого рекурсивного" поиска маршрута прикидочно может достигать 50 000 (кол-во нод) x 5 (путей из каждой ноды) => до 50 - 250 тысяч рекурсий/циклов, и отжирать примерно столько же стека. Теоретически возможно тут нужно было бы 50 000 возводить в степень 5-ки, но это если искать все маршруты. Нам же нужен только факт, что такой маршрут есть, т.е. если мы повторно входим в ноду, то поиск сразу же прекрашаем.

Результат работы массив из 5 ячеек, есть ли (сколько) маршрутов в соседние ячейки. Плюс временный массив на 50 000 элементов, где хранится были ли мы уже в этой ноде.

Таких поисков нужно запускать 50 000 раз.

Поскольку схлопывание может быть рекурсивным (например граф вырождается в банальное кольцо), алгоритм возможно рекурсивно запускать до 50 000 раз.

Время работы одного прогона на Java (при оптимизации), я бы оценил от 10 000 секунд, т.е. где-то 3-10 часов (железо уровня AWS tiny instance) для одного прогона. Но это без рекурсивного схлопывания. При многопроцессорности кратно меньше.

Для рекурсивном схлопывание, наверное, нужно посчитать один раз матрицу N x N ( 50 x 50 = 2 500 000 000 элементов) кол-во маршрутов из A в B. Т.к. при схлопывание кол-во марщрутов из A и B изменится не должно (мне так кажется), то не нужно будет перевычислять маршруты.

Кол-во маршрутов из A в B нам интересно только 0 - нет маршрута, 1 - толкьо один маршрут, 2 - два и _более_ маршрута (схлопывать нельзя).
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39998324
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton

...
Фрагмент вершины
Код: java
1.
2.
3.
4.
5.
public class Vertex implements Serializable {
...
    private List<Edge> outgoingEdges = new ArrayList<>();
    private List<Edge> incomingEdges = new ArrayList<>();
...




Крайне не оптимально. Я бы вершины кодировал бы просто целым числом в массиве (т.е. до 2 млр. вершин), сответственно outgoingEdges, incomingEdges можно сделать просто

int[] outgoingVertex;

Аналогично и хранение результатов в стеке, все возвраты - тупо int. Объекты даром не нужны. Коллекции - только оптимизированные (не стандартные!) для работы с примитивными типами.
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39998328
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Leonid Kudryavtsev
mayton

...
Фрагмент вершины
Код: java
1.
2.
3.
4.
5.
public class Vertex implements Serializable {
...
    private List<Edge> outgoingEdges = new ArrayList<>();
    private List<Edge> incomingEdges = new ArrayList<>();
...




Крайне не оптимально. Я бы вершины кодировал бы просто целым числом в массиве (т.е. до 2 млр. вершин), сответственно outgoingEdges, incomingEdges можно сделать просто

int[] outgoingVertex;

Аналогично и хранение результатов в стеке, все возвраты - тупо int. Объекты даром не нужны. Коллекции - только оптимизированные (не стандартные!) для работы с примитивными типами.

Разумно. Согласен. Я сейчас сразу менять код не буду. Иначе у меня 80% кода надо будет срочно переписать.

Но я ставлю.

Код: java
1.
TODO: Leonid proposes to get rid of Edges instead of primitives.



В чем был поинт хранения ребер как объектов. В базовой постановке https://www.sql.ru/forum/1282300/chetvergovyy-arhivarius
ребро хранило вес. Тоесть количество пробегов по нему. И здесь в этой задаче оптимизации оно стало рудиментом.
Хотя я планировал и вертексы и рёбра сделать генериками чтобы внутрь еще что-то кодкладывать. Разные метки
для алгоритмов типа дейсктры и возможно признак блокировки для мультипоточки.

При объектах (references) накладные расходы на храение - одинаковы что для вершин что для ребер.

Идентификатор vertex у меня был строковый. String. Он хранил токен. Или строку из литературного произведения.
А для данной постановки я просто искусственно очистил все id-шники и заменил их на sequence целых чисел.
...
Рейтинг: 0 / 0
Java :: Пятничное схлопывание толстых графов.
    #39998358
dimonz80
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
mayton,


На скорую рука как-то так. Правда цепочки типа 1->2->3->4 коллапсируют в пустое множество

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
import scala.annotation.tailrec

val data = {
  scala.io.Source.fromFile("war-and-society-1-2-3-4-simple-edges.sorted.csv").getLines()
    .map { l =>
      val arr = l.split(",").map(_.toInt)
      arr(0) -> arr(1)
    }.toArray
}



@tailrec
def processGraph(data: Array[(Int, Int)]): Array[(Int, Int)] = {
  val inputs = data.groupBy(_._2).map { case (k, v) => k -> v.map(_._1) }
  val outputs = data.groupBy(_._1).map { case (k, v) => k -> v.map(_._2) }

  val singleLinks = outputs.filter(_._2.length == 1).filter{case (from,Array(to)) => Array(from).toList == inputs(to).toList }.map { case (from, Array(to)) => from -> to}

  if (singleLinks.isEmpty) {
    return data
  }

  val newData = collection.mutable.HashSet[(Int, Int)]()

  data.foreach { case (from, to) =>
    // нашли связь 1вых->1вх
    if (singleLinks.get(from) == Option(to)) {
      // перенести исходящие узлы удаляемго узла к преды дущему
      outputs.get(to).foreach { outs =>
        outs.foreach { out =>
          newData.add((from, out))
        }
      }
    } else {
      if (!singleLinks.exists { case (f, t) => (t == from)} ) {
        newData.add((from, to))
      }
    }
  }

  processGraph(newData.toArray)

}

processGraph(data)
...
Рейтинг: 0 / 0
25 сообщений из 71, страница 1 из 3
Форумы / Java [игнор отключен] [закрыт для гостей] / Java :: Пятничное схлопывание толстых графов.
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]