Гость
Форумы / Java [игнор отключен] [закрыт для гостей] / Java :: Пятничное схлопывание толстых графов. / 25 сообщений из 71, страница 1 из 3
11.09.2020, 21:03
    #39997802
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java :: Пятничное схлопывание толстых графов.
Привет.

В продолжне архивариуса 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
11.09.2020, 21:48
    #39997811
Sergunka
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java :: Пятничное схлопывание толстых графов.
mayton,

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

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


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

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

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

Но вцелом очень козырная задача... редкая находка в наши дни борьбы за деньзнаки.
...
Рейтинг: 0 / 0
13.09.2020, 11:41
    #39998042
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java :: Пятничное схлопывание толстых графов.
Я опубликовал финальный файл. В нем 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
13.09.2020, 11:49
    #39998044
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java :: Пятничное схлопывание толстых графов.
По алгоритму. Что я еще не учел? Возможно кейсов схлопывания больше чем я нарисовал на картинке.
Возможно петли и циклы не запрещают нам это сделать. Я чуть позже приаттачу еще одну картинку
где есть частные случаи.
...
Рейтинг: 0 / 0
13.09.2020, 12:20
    #39998048
Alexander A. Sak
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java :: Пятничное схлопывание толстых графов.
Базистам эту задачу решать можно?

Сделать таблицу 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
13.09.2020, 12:27
    #39998049
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java :: Пятничное схлопывание толстых графов.
Да. Да. Базистам это решать можно. Всем можно. Но я просто по инерции продолжал тему оптимизации текстовых
литературных графов. Просто сама постановка была настолько интересно что я решил ее очистить от ненужной
шелухи и выдать отдельным топиком как чистую алгоритмизацию на Java.

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

Case (1)

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

Case (2)

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

Case (3)

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

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

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

Algorithm: GraphEdgeSimplification-alg-0.1

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

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

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

Сложность "тупого рекурсивного" поиска маршрута прикидочно может достигать 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
14.09.2020, 14:04
    #39998324
Leonid Kudryavtsev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java :: Пятничное схлопывание толстых графов.
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
14.09.2020, 14:15
    #39998328
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java :: Пятничное схлопывание толстых графов.
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
14.09.2020, 15:15
    #39998358
dimonz80
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Java :: Пятничное схлопывание толстых графов.
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
Форумы / Java [игнор отключен] [закрыт для гостей] / Java :: Пятничное схлопывание толстых графов. / 25 сообщений из 71, страница 1 из 3
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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