2 Sitoutukset d388b517f1 ... d4c0cd2a6d

Tekijä SHA1 Viesti Päivämäärä
  Pavel Zhigalov d4c0cd2a6d Initial commit 1 kuukausi sitten
  Pavel Zhigalov d388b517f1 Initial commit 1 kuukausi sitten

+ 2 - 2
src/graphs/abstract/DirectedEdge.ts

@@ -7,8 +7,8 @@ import Edge from "./Edge.js";
  * @abstract
  */
 export default abstract class DirectedEdge<V extends Vertex> extends Edge<V> {
-	protected constructor(source: V, target: V) {
-		super(source, target);
+	protected constructor(id: number, source: V, target: V) {
+		super(id, source, target);
 	}
 
 	/**

+ 7 - 1
src/graphs/abstract/Edge.ts

@@ -6,11 +6,17 @@ import Vertex from "./Vertex.js";
  * @abstract
  */
 export default abstract class Edge<V extends Vertex> {
+	private readonly _id: number;
 	protected _v1: V;
 	protected _v2: V;
 
-	protected constructor(v1: V, v2: V) {
+	protected constructor(id: number, v1: V, v2: V) {
+		this._id = id;
 		this._v1 = v1;
 		this._v2 = v2;
 	}
+
+	get id(): number {
+		return this._id;
+	}
 }

+ 18 - 7
src/graphs/abstract/Graph.ts

@@ -1,5 +1,6 @@
 import Vertex from "./Vertex.js";
 import Edge from "./Edge.js";
+import GraphStore from "./GraphStore.js";
 
 /**
  * Абстрактный класс, представляющий граф
@@ -8,25 +9,35 @@ import Edge from "./Edge.js";
  * @abstract
  */
 export default abstract class Graph<V extends Vertex, E extends Edge<V>> {
-	private readonly _vertices: V[];
-	private readonly _edges: E[];
+	private readonly _store: GraphStore<V, E>;
 
-	protected constructor(vertices: V[], edges: E[]) {
-		this._vertices = vertices;
-		this._edges = edges;
+	protected constructor(store: GraphStore<V, E>) {
+		this._store = store;
 	}
 
 	/**
      * Список вершин графа
      */
 	get vertices() : V[] {
-		return this._vertices;
+		return this._store.getAllVertices();
 	}
 
 	/**
      * Список рёбер графа
      */
 	get edges(): E[] {
-		return this._edges;
+		return this._store.getAllEdges();
+	}
+
+	get store(): GraphStore<V, E> {
+		return this._store;
+	}
+
+	public getAdjacentVertices(vertex: V) : V[] {
+		return this._store.getAdjacentVertices(vertex.id);
+	}
+
+	public getIncidentEdges(vertex: V): E[] {
+		return this._store.getIncidentEdges(vertex.id);
 	}
 }

+ 41 - 0
src/graphs/abstract/GraphStore.ts

@@ -0,0 +1,41 @@
+import Vertex from "./Vertex.js";
+import Edge from "./Edge.js";
+
+/**
+ * Класс, описывающий способ хранения графа
+ */
+export default interface GraphStore<V extends Vertex, E extends Edge<V>> {
+    /**
+     * Получить вершину из графа по её уникальному идентификатору
+     * @param id Уникальный идентификатор вершины
+     */
+    getVertex(id: V["id"]): V|null;
+
+    /**
+     * Получение всех списков вершин в графе
+     */
+    getAllVertices(): V[];
+
+    /**
+     * Получить ребро из графа по её уникальному идентификатору
+     * @param id Уникальный идентификатор ребра
+     */
+    getEdge(id: E["id"]): E|null;
+
+    /**
+     * Получение всех рёбер в графе
+     */
+    getAllEdges(): E[];
+
+    /**
+     * Получить вершины, смежные с указанной
+     * @param id Уникальый идентификатор вершины, для которой необходимо найти смежные вершины
+     */
+    getAdjacentVertices(id: V["id"]): V[];
+
+    /**
+     * Получить ребра, инцидентные вершине
+     * @param id Уникальный идентификатор вершины, для которой нужно получить инцидентные ребра
+     */
+    getIncidentEdges(id: V["id"]): E[];
+}

+ 47 - 0
src/graphs/types/SimpleGraphStore.ts

@@ -0,0 +1,47 @@
+import GraphStore from "../abstract/GraphStore.js";
+import XVertex from "./XVertex.js";
+import XDirectedEdge from "./XDirectedEdge.js";
+
+export default class SimpleGraphStore implements GraphStore<XVertex, XDirectedEdge> {
+	private readonly _vertices: XVertex[];
+	private readonly _edges: XDirectedEdge[];
+
+	public constructor(vertices: XVertex[], edges: XDirectedEdge[]) {
+		this._vertices = vertices;
+		this._edges = edges;
+	}
+
+	getVertex(id: number): XVertex | null {
+		return this._vertices.find((vertex) => vertex.id == id) || null;
+	}
+
+	getAllVertices(): XVertex[] {
+		return this._vertices;
+	}
+
+	getEdge(id: number): XDirectedEdge | null {
+		return this._edges.find((edge) => edge.id == id) || null;
+	}
+
+	getAllEdges(): XDirectedEdge[] {
+		return this._edges;
+	}
+
+	getAdjacentVertices(id: number): XVertex[] {
+		const v = this.getVertex(id);
+
+		if(!v)
+		// TODO Replace by throwing error
+			return []
+
+		return this._edges.filter((edge) => edge.start.id == v.id).map((edge) => edge.target);
+	}
+
+	getIncidentEdges(id: XVertex["id"]): XDirectedEdge[] {
+		const v = this.getVertex(id);
+		if(!v)
+			return [];
+
+		return this._edges.filter((edge) => edge.start.id == v.id);
+	}
+}

+ 2 - 2
src/graphs/types/XDirectedEdge.ts

@@ -5,7 +5,7 @@ import XVertex from "./XVertex.js";
  * Стандартная реализация направленного ребра графа, соединяющего две вершины типа {@link XVertex}
  */
 export default class XDirectedEdge extends DirectedEdge<XVertex> {
-	public constructor(start: XVertex, target: XVertex) {
-		super(start, target);
+	public constructor(id: number, start: XVertex, target: XVertex) {
+		super(id, start, target);
 	}
 }

+ 3 - 2
src/graphs/types/XDirectedGraph.ts

@@ -1,9 +1,10 @@
 import Graph from "../abstract/Graph.js";
 import XDirectedEdge from "./XDirectedEdge.js";
 import XVertex from "./XVertex.js";
+import GraphStore from "../abstract/GraphStore.js";
 
 export default class XDirectedGraph extends Graph<XVertex, XDirectedEdge> {
-	public constructor(vertices: XVertex[], edges: XDirectedEdge[]) {
-		super(vertices, edges);
+	public constructor(store: GraphStore<XVertex, XDirectedEdge>) {
+		super(store);
 	}
 }

+ 12 - 7
src/index.ts

@@ -1,12 +1,17 @@
 import XDirectedEdge from "./graphs/types/XDirectedEdge.js";
 import XVertex from "./graphs/types/XVertex.js";
 import XDirectedGraph from "./graphs/types/XDirectedGraph.js";
-import SugiyamaBaseOptimizer from "./optimizer/types/sugiyama-based/SugiyamaBaseOptimizer.js";
+import SimpleGraphStore from "./graphs/types/SimpleGraphStore.js";
+import SiguyamaOptimizer from "./optimizer/types/sugiyama-based/SiguyamaOptimizer.js";
 import CycleRemoverStep from "./optimizer/types/sugiyama-based/CycleRemoverStep.js";
-import LogStep from "./optimizer/types/sugiyama-based/LogStep.js";
+import LinearOptimizationStep from "./optimizer/types/sugiyama-based/LinearOptimizationStep.js";
 
-const v = [new XVertex(1), new XVertex(2)]
-const e = [new XDirectedEdge(v[0]!, v[1]!)]
-const g = new XDirectedGraph(v, e);
-const opt = new SugiyamaBaseOptimizer(g, [new LogStep(), new CycleRemoverStep((g) => { console.log(g) })]);
-opt.optimize();
+const v = [new XVertex(1), new XVertex(2), new XVertex(3), new XVertex(4)]
+const e = [new XDirectedEdge(1, v[0]!, v[1]!), new XDirectedEdge(2, v[1]!, v[2]!), new XDirectedEdge(3, v[2]!, v[0]!), new XDirectedEdge(4, v[0]!, v[3]!)]
+const g = new XDirectedGraph(new SimpleGraphStore(v, e));
+
+const opt = new SiguyamaOptimizer(new CycleRemoverStep().setNext(new LinearOptimizationStep()));
+
+opt.optimize(g)
+	.then((g) => console.log(`Result: ${JSON.stringify(g)}`))
+	.catch((err) => console.error(err));

+ 8 - 0
src/optimizer/abstract/Optimizer.ts

@@ -0,0 +1,8 @@
+import IOptimizer from "../interfaces/IOptimizer.js";
+import Vertex from "../../graphs/abstract/Vertex.js";
+import Edge from "../../graphs/abstract/Edge.js";
+import Graph from "../../graphs/abstract/Graph.js";
+
+export default abstract class Optimizer<V extends Vertex, E extends Edge<V>, G extends Graph<V, E>> implements IOptimizer<V, E, G> {
+    public abstract optimize(source: G): Promise<G>;
+}

+ 16 - 0
src/optimizer/abstract/OptimizerStep.ts

@@ -0,0 +1,16 @@
+import IOptimizerStep from "../interfaces/IOptimizerStep.js";
+
+export default abstract class OptimizerStep<Context> implements IOptimizerStep<Context> {
+	private _nextStep: IOptimizerStep<Context> | undefined;
+
+	public setNext(step: IOptimizerStep<Context>): OptimizerStep<Context> {
+		this._nextStep = step;
+		return this;
+	}
+
+	public process(context: Context): Context {
+		if(this._nextStep)
+			return this._nextStep.process(context);
+		return context;
+	}
+}

+ 0 - 18
src/optimizer/abstract/sugiyama-based/ISugiyamaBaseOptimizerStep.ts

@@ -1,18 +0,0 @@
-import IOptimizerStep from "../../interfaces/IOptimizerStep.js";
-import XDirectedGraph from "../../../graphs/types/XDirectedGraph.js";
-
-export default abstract class ISugiyamaBaseOptimizerStep implements IOptimizerStep<XDirectedGraph, XDirectedGraph> {
-	private _nextStep: IOptimizerStep<XDirectedGraph, XDirectedGraph> | undefined;
-
-	handle(data: XDirectedGraph): XDirectedGraph {
-		if(this._nextStep)
-			return this._nextStep.handle(data);
-
-		return data;
-	}
-
-	setNext(step: IOptimizerStep<XDirectedGraph, XDirectedGraph>): IOptimizerStep<XDirectedGraph, XDirectedGraph> {
-		this._nextStep = step;
-		return step;
-	}
-}

+ 11 - 0
src/optimizer/abstract/sugiyama-based/SugiyamaOptimizerStep.ts

@@ -0,0 +1,11 @@
+import XDirectedGraph from "../../../graphs/types/XDirectedGraph.js";
+import OptimizerStep from "../OptimizerStep.js";
+import XDirectedEdge from "../../../graphs/types/XDirectedEdge.js";
+
+export type Context = {
+    graph: XDirectedGraph,
+    acyclicGraph?: XDirectedGraph,
+    reversedEdges?: XDirectedEdge[]
+}
+
+export default abstract class SugiyamaOptimizerStep extends OptimizerStep<Context> {}

+ 1 - 1
src/optimizer/interfaces/IOptimizer.ts

@@ -3,5 +3,5 @@ import Vertex from "../../graphs/abstract/Vertex.js";
 import Edge from "../../graphs/abstract/Edge.js";
 
 export default interface IOptimizer<V extends Vertex, E extends Edge<V>, G extends Graph<V, E>> {
-    optimize(): Promise<G>
+    optimize(source: G): Promise<G>
 }

+ 3 - 3
src/optimizer/interfaces/IOptimizerStep.ts

@@ -1,4 +1,4 @@
-export default interface IOptimizerStep<Input, Output> {
-    handle(data: Input): Output;
-    setNext(step: IOptimizerStep<Input, Output>): IOptimizerStep<Input, Output>
+export default interface IOptimizerStep<Context> {
+    process(input: Context): Context;
+    setNext(step: IOptimizerStep<Context>): IOptimizerStep<Context>;
 }

+ 5 - 10
src/optimizer/types/sugiyama-based/CycleRemoverStep.ts

@@ -1,13 +1,8 @@
-import ISugiyamaBaseOptimizerStep from "../../abstract/sugiyama-based/ISugiyamaBaseOptimizerStep.js";
-import XDirectedGraph from "../../../graphs/types/XDirectedGraph.js";
+import SugiyamaOptimizerStep, { Context } from "../../abstract/sugiyama-based/SugiyamaOptimizerStep.js";
 
-export default class CycleRemoverStep extends ISugiyamaBaseOptimizerStep {
-	public handle(data: XDirectedGraph): XDirectedGraph {
-		this.dfs(data);
-		return super.handle(data);
-	}
-
-	private dfs(graph: XDirectedGraph): void {
-        
+export default class CycleRemoverStep extends SugiyamaOptimizerStep {
+	public process(context: Context): Context {
+		//TODO
+		return super.process(context);
 	}
 }

+ 8 - 0
src/optimizer/types/sugiyama-based/LinearOptimizationStep.ts

@@ -0,0 +1,8 @@
+import SugiyamaOptimizerStep, { Context } from "../../abstract/sugiyama-based/SugiyamaOptimizerStep.js";
+
+export default class LinearOptimizationStep extends SugiyamaOptimizerStep {
+	public process(context: Context): Context {
+		//TODO
+		return super.process(context);
+	}
+}

+ 0 - 11
src/optimizer/types/sugiyama-based/LogStep.ts

@@ -1,11 +0,0 @@
-import DirectedGraph from "../../../graphs/abstract/DirectedGraph.js";
-import XDirectedEdge from "../../../graphs/types/XDirectedEdge.js";
-import XVertex from "../../../graphs/types/XVertex.js";
-import ISugiyamaBaseOptimizerStep from "../../abstract/sugiyama-based/ISugiyamaBaseOptimizerStep.js";
-
-export default class LogStep extends ISugiyamaBaseOptimizerStep {
-	public handle(graph: DirectedGraph<XVertex, XDirectedEdge>): DirectedGraph<XVertex, XDirectedEdge> {
-		console.log(`log step: ${graph}`)
-		return super.handle(graph);
-	}
-}

+ 19 - 0
src/optimizer/types/sugiyama-based/SiguyamaOptimizer.ts

@@ -0,0 +1,19 @@
+import Optimizer from "../../abstract/Optimizer.js";
+import XVertex from "../../../graphs/types/XVertex.js";
+import XDirectedEdge from "../../../graphs/types/XDirectedEdge.js";
+import XDirectedGraph from "../../../graphs/types/XDirectedGraph.js";
+import SugiyamaOptimizerStep from "../../abstract/sugiyama-based/SugiyamaOptimizerStep.js";
+
+export default class SiguyamaOptimizer extends Optimizer<XVertex, XDirectedEdge, XDirectedGraph> {
+	private readonly _chain: SugiyamaOptimizerStep;
+
+	public constructor(chain: SugiyamaOptimizerStep) {
+		super();
+		this._chain = chain;
+	}
+
+	public async optimize(source: XDirectedGraph): Promise<XDirectedGraph> {
+		this._chain.process({ graph: source });
+		return source;
+	}
+}

+ 0 - 24
src/optimizer/types/sugiyama-based/SugiyamaBaseOptimizer.ts

@@ -1,24 +0,0 @@
-import IOptimizer from "../../interfaces/IOptimizer.js";
-import XVertex from "../../../graphs/types/XVertex.js";
-import XDirectedEdge from "../../../graphs/types/XDirectedEdge.js";
-import XDirectedGraph from "../../../graphs/types/XDirectedGraph.js";
-import DirectedGraph from "../../../graphs/abstract/DirectedGraph.js";
-import ISugiyamaBaseOptimizerStep from "../../abstract/sugiyama-based/ISugiyamaBaseOptimizerStep.js";
-
-export default class SugiyamaBaseOptimizer implements IOptimizer<XVertex, XDirectedEdge, DirectedGraph<XVertex, XDirectedEdge>> {
-	private readonly _graph: DirectedGraph<XVertex, XDirectedEdge>;
-	private readonly _startStep: ISugiyamaBaseOptimizerStep;
-
-	public constructor(graph: DirectedGraph<XVertex, XDirectedEdge>, steps: ISugiyamaBaseOptimizerStep[]) {
-		this._graph = graph;
-
-		for(let i = 0; i < steps.length; i++)
-            steps[i]!.setNext(steps[i+1]!);
-
-		this._startStep = steps[0]!;
-	}
-
-	async optimize(): Promise<XDirectedGraph> {
-		return this._startStep.handle(this._graph);
-	}
-}