From 56fcbf4ece4d72adb1e5c8a83ace85492d1b72ae Mon Sep 17 00:00:00 2001 From: AnastasiiaRazheva <43729980+AnastasiiaRazheva@users.noreply.github.com> Date: Tue, 9 Apr 2019 02:14:46 +0300 Subject: [PATCH 01/17] Add files via upload Test comit. Aadded a short description of the future module in ToolButtonList.prototype.help --- src/App.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/App.tsx b/src/App.tsx index 26c6cdf..ed309a3 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,16 @@ import * as React from 'react'; -import {TaskTemplate} from 'graphlabs.core.template'; +import { store, TaskTemplate, TaskToolbar, ToolButtonList } from 'graphlabs.core.template'; class App extends TaskTemplate { + + getTaskToolbar() { + TaskToolbar.prototype.getButtonList = () => { + ToolButtonList.prototype.help = () => `В данном задании будет выполняться проверка + планарности графа.`; + return ToolButtonList; + }; + return TaskToolbar; + } } export default App; From 4a05356fde24f153a61e527922667afb428b3e2d Mon Sep 17 00:00:00 2001 From: AnastasiiaRazheva Date: Tue, 7 May 2019 03:52:50 +0300 Subject: [PATCH 02/17] Fail try to use DFS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Исправила Замечания по синтаксису. Пыталась подключить для поиска циклов функцию dfs - но это не так просто. Пока оставлю так. --- src/App.tsx | 183 +++++++++++++++++++++++++++++++++++++++++++++++++- src/Cycle.tsx | 23 +++++++ tsconfig.json | 2 +- 3 files changed, 205 insertions(+), 3 deletions(-) create mode 100644 src/Cycle.tsx diff --git a/src/App.tsx b/src/App.tsx index ed309a3..8d6402d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,9 +1,145 @@ import * as React from 'react'; import { store, TaskTemplate, TaskToolbar, ToolButtonList } from 'graphlabs.core.template'; +import { IEdgeView, IVertexView } from 'graphlabs.core.template/build/models/graph'; +import { Graph, Vertex, Edge } from 'graphlabs.core.graphs'; +import { Cycle } from './Cycle'; +import { element } from 'prop-types'; + +var private_log_6549H: string = ""; + +enum Color { + White = 0, + Grey = 1, + Black = 2 +} + +function graph_optimize(){ + let beta_graph = Object.assign({}, store.getState().graph); + + beta_graph.vertices = beta_graph.vertices.filter((v: Vertex) => beta_graph.edges.find((e: IEdgeView) => e.vertexOne === v.name || e.vertexTwo === v.name )); + + let num_vertices_deleted: number = 0; + let vertices_mig; + + do{ + vertices_mig = beta_graph.vertices.filter((v: Vertex) => beta_graph.edges.filter((e: IEdgeView) => e.vertexOne === v.name || e.vertexTwo === v.name).length >= 2 ); + num_vertices_deleted = beta_graph.vertices.length - vertices_mig.length; + beta_graph.vertices = vertices_mig; + + beta_graph.edges = beta_graph.edges.filter((e: IEdgeView) => beta_graph.vertices.find((v: Vertex) => v.name === e.vertexOne) && beta_graph.vertices.find((v: Vertex) => v.name === e.vertexTwo)); + + } while(num_vertices_deleted != 0) + + return beta_graph; +} + +/* function dfs(vertex: IVertexView, c_graph_vertices: IVertexView[], c_graph_edges: IEdgeView[], colored: Color[]) { + colored[Number(vertex.name)] = Color.Grey; + + c_graph_edges.filter((element: IEdgeView) => (element.vertexOne == vertex.name && colored[Number(element.vertexOne)] != Color.Black) + || (element.vertexTwo == vertex.name && colored[Number(element.vertexTwo)] != Color.Black)) + .forEach((element: IEdgeView) => { + if (element.vertexOne == vertex.name){ + if (colored[Number(element.vertexTwo)] == Color.White){ + dfs(c_graph_vertices.find((v: IVertexView) => v.name == element.vertexTwo), c_graph_vertices, c_graph_edges, colored); + } + else if(colored[Number(element.vertexTwo)] == Color.Grey){ + private_log_6549H += "___" + "I find the cycle" + colored + "___"; + } + } + else if(element.vertexTwo == vertex.name){ + if (colored[Number(element.vertexOne)] == Color.White){ + dfs(c_graph_vertices.find((v: IVertexView) => v.name == element.vertexOne), c_graph_vertices, c_graph_edges, colored); + } + else if(colored[Number(element.vertexOne)] == Color.Grey){ + private_log_6549H += "___" + "I find the cycle" + colored + "___"; + } + } + colored[Number(vertex.name)] = Color.Black; + }); + + return colored; +} + + +function find_cycle_dfs(c_graph_vertices: IVertexView[], c_graph_edges: IEdgeView[]) { + + //if(c_graph_vertices.length === 0){ + // return null; + //} + + let result_cycle:Cycle[] = []; + + const graph = store.getState().graph; + let colored = new Array(graph.vertices.length).fill(Color.White); + + private_log_6549H += "___" + colored + "___"; + + colored = dfs(c_graph_vertices[0], c_graph_vertices, c_graph_edges, colored); + + private_log_6549H += "___" + colored + "___"; + + return result_cycle; +} */ + +function find_cycle(c_graph_vertices: IVertexView[], c_graph_edges: IEdgeView[] ) { + + + if(c_graph_vertices.length === 0){ + return null; + } + + var result_cycles:Cycle = new Cycle("G0", [c_graph_vertices[0]]); + + //private_log_6549H += result_cycles.toString() + " v0 = " + c_graph_vertices[0].name + "_"; + + // var v2_list_of_edges_beta: string = ""; + // c_graph_edges.forEach((element: IEdgeView) => { + // v2_list_of_edges_beta+=element.vertexOne + element.vertexTwo + ", "; + // }); + // private_log_6549H += v2_list_of_edges_beta; + + let colored:IVertexView[] = []; + + let c_edge = c_graph_edges.find((e: IEdgeView) => e.vertexOne === result_cycles.vertices[0].name || e.vertexTwo === result_cycles.vertices[0].name); + + if (c_edge!=null){ + //private_log_6549H += "_____________new vertex i take from edge: " + c_edge.vertexOne + c_edge.vertexTwo; + if (c_edge.vertexOne === result_cycles.vertices[0].name){ + result_cycles.vertices = result_cycles.vertices.concat([c_graph_vertices.find((v: IVertexView) => v.name === c_edge.vertexTwo)]); + colored = colored.concat([c_graph_vertices.find((v: IVertexView) => v.name === c_edge.vertexTwo)]); + } else + { + result_cycles.vertices = result_cycles.vertices.concat([c_graph_vertices.find((v: IVertexView) => v.name === c_edge.vertexOne)]); + colored = colored.concat([c_graph_vertices.find((v: IVertexView) => v.name === c_edge.vertexOne)]); + } + } + + //private_log_6549H += result_cycles.toString() + " v0 = " + c_graph_vertices[0].name + "_"; + + while (result_cycles.vertices[0] !== result_cycles.vertices[result_cycles.vertices.length - 1]){ + c_edge = c_graph_edges.find((e: IEdgeView) => e.vertexOne === result_cycles.vertices[result_cycles.vertices.length - 1].name && e.vertexTwo !== result_cycles.vertices[result_cycles.vertices.length - 2].name && (colored.find((cv: IVertexView) => cv.name === e.vertexTwo) == null) + || e.vertexTwo === result_cycles.vertices[result_cycles.vertices.length - 1].name && e.vertexOne !== result_cycles.vertices[result_cycles.vertices.length - 2].name && (colored.find((cv: IVertexView) => cv.name === e.vertexOne) == null)); + if (c_edge!=null){ + //private_log_6549H += "_____________new vertes i take from edge: " + c_edge.vertexOne + c_edge.vertexTwo + "_____________colored is:"; + //colcored.forEach(( e: IVertexView) => private_log_6549H += e.name); + if (c_edge.vertexOne === result_cycles.vertices[result_cycles.vertices.length - 1].name){ + result_cycles.vertices = result_cycles.vertices.concat([c_graph_vertices.find((v: IVertexView) => v.name === c_edge.vertexTwo)]); + colored = colored.concat([c_graph_vertices.find((v: IVertexView) => v.name === c_edge.vertexTwo)]); + } else + { + result_cycles.vertices = result_cycles.vertices.concat([c_graph_vertices.find((v: IVertexView) => v.name === c_edge.vertexOne)]); + colored = colored.concat([c_graph_vertices.find((v: IVertexView) => v.name === c_edge.vertexOne)]); + } + } + } + + return result_cycles; +} class App extends TaskTemplate { - getTaskToolbar() { + public getTaskToolbar() { TaskToolbar.prototype.getButtonList = () => { ToolButtonList.prototype.help = () => `В данном задании будет выполняться проверка планарности графа.`; @@ -11,6 +147,49 @@ class App extends TaskTemplate { }; return TaskToolbar; } + + public task() { + const graph = store.getState().graph; + + var list_of_vertices: string = ""; + graph.vertices.forEach((element: Vertex) => { + list_of_vertices += element.name; + }) + + var list_of_edges: string = ""; + graph.edges.forEach((element: IEdgeView) => { + list_of_edges+=element.vertexOne + element.vertexTwo + " , "; + }); + + var beta_graph = graph_optimize(); + + var list_of_vertices_beta: string = ""; + beta_graph.vertices.forEach((element: Vertex) => { + list_of_vertices_beta += element.name; + }) + + var list_of_edges_beta: string = ""; + beta_graph.edges.forEach((element: IEdgeView) => { + list_of_edges_beta+=element.vertexOne + element.vertexTwo + ", "; + }); + + var res_cycl = find_cycle(beta_graph.vertices, beta_graph.edges); + var res_cycl_string = res_cycl==null? "Граф Планарен! Цикла нет.": res_cycl.toString(); + + //find_cycle_dfs(beta_graph.vertices, beta_graph.edges); + + return () => ( +
+ В данном графе {graph.vertices.length} вершин.
В данном графе {graph.edges.length} связей.
+

Точки в данном графе: {list_of_vertices}
+
Связи в данном графе: {list_of_edges}
+

Точки в графе_beta: {list_of_vertices_beta}
+
Связи в графе_beta: {list_of_edges_beta}
+

Найденный цикл: {res_cycl_string}
+

Лог: {private_log_6549H}
+
+ ); + } } -export default App; +export default App; \ No newline at end of file diff --git a/src/Cycle.tsx b/src/Cycle.tsx new file mode 100644 index 0000000..03439c6 --- /dev/null +++ b/src/Cycle.tsx @@ -0,0 +1,23 @@ +import * as React from 'react'; +import { Graph, Vertex, Edge } from 'graphlabs.core.graphs'; +import { IEdgeView, IVertexView } from 'graphlabs.core.template/build/models/graph'; + +export class Cycle { + + name: string; + vertices: IVertexView[]; + + constructor(name: string, vertices: IVertexView[]) { + + this.name = name; + this.vertices = vertices; + } + + toString(): string{ + let str:string = ""; + this.vertices.forEach((element: IVertexView) => { + str += element.name; + }); + return this.name + " : " + str; + } +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 295b7dd..08cd836 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,7 +16,7 @@ "noImplicitReturns": true, "noImplicitThis": true, "noImplicitAny": true, - "strictNullChecks": true, + "strictNullChecks": false, "suppressImplicitAnyIndexErrors": true, "esModuleInterop": true, From 9ac7d49292a0c583a030a9de5feb534802b5df12 Mon Sep 17 00:00:00 2001 From: AnastasiiaRazheva Date: Sat, 11 May 2019 18:45:01 +0300 Subject: [PATCH 03/17] It work! MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Я все выходные на это убила, но оно начало работать. Интерфейс и оптимизация кода завтра. --- src/App.tsx | 218 +++++++++++++++++++++++++++++++++++++++++----- src/BetaGraph.tsx | 120 +++++++++++++++++++++++++ src/Cycle.tsx | 6 +- src/Segment.tsx | 26 ++++++ 4 files changed, 348 insertions(+), 22 deletions(-) create mode 100644 src/BetaGraph.tsx create mode 100644 src/Segment.tsx diff --git a/src/App.tsx b/src/App.tsx index 8d6402d..33de04a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,9 +1,12 @@ import * as React from 'react'; +import { BetaGraph } from './BetaGraph'; import { store, TaskTemplate, TaskToolbar, ToolButtonList } from 'graphlabs.core.template'; import { IEdgeView, IVertexView } from 'graphlabs.core.template/build/models/graph'; import { Graph, Vertex, Edge } from 'graphlabs.core.graphs'; import { Cycle } from './Cycle'; -import { element } from 'prop-types'; +import { element, number } from 'prop-types'; +import { Segment } from './Segment'; +import { IVertexVisualizer } from 'graphlabs.core.visualizer'; var private_log_6549H: string = ""; @@ -15,6 +18,7 @@ enum Color { function graph_optimize(){ let beta_graph = Object.assign({}, store.getState().graph); + beta_graph.vertices = beta_graph.vertices.filter((v: Vertex) => beta_graph.edges.find((e: IEdgeView) => e.vertexOne === v.name || e.vertexTwo === v.name )); @@ -33,6 +37,40 @@ function graph_optimize(){ return beta_graph; } +function find_way(graph_vertices: IVertexView[], graph_edges: IEdgeView[], start_point: IVertexView, finish_point: IVertexView[]) : Segment{ + + var resultSegment : Segment = new Segment([], [start_point], start_point, null); + var blackList : IEdgeView[] = []; + + do { + var nextEdge = graph_edges.find( edge => !resultSegment.body_edges.find(e => e == edge) && !blackList.find(e => e == edge) + && (edge.vertexOne == resultSegment.body_vertices[resultSegment.body_vertices.length - 1].name + || edge.vertexTwo == resultSegment.body_vertices[resultSegment.body_vertices.length - 1].name)); + + if (nextEdge == null){ + if (resultSegment.body_edges.length == 0){ + return null; + } + blackList.push(resultSegment.body_edges.pop()); + resultSegment.body_vertices.pop(); + continue; + } + + resultSegment.body_edges.push(nextEdge); + + if (nextEdge.vertexOne == resultSegment.body_vertices[resultSegment.body_vertices.length - 1].name){ + resultSegment.body_vertices.push(graph_vertices.find(v => v.name == nextEdge.vertexTwo)); + resultSegment.contactPointTwo = graph_vertices.find(v => v.name ==nextEdge.vertexTwo); + } else { + resultSegment.body_vertices.push(graph_vertices.find(v => v.name == nextEdge.vertexOne)); + resultSegment.contactPointTwo = graph_vertices.find(v => v.name == nextEdge.vertexOne); + } + + } while (!finish_point.find(v => resultSegment.contactPointTwo.name == v.name)) + + return resultSegment +} + /* function dfs(vertex: IVertexView, c_graph_vertices: IVertexView[], c_graph_edges: IEdgeView[], colored: Color[]) { colored[Number(vertex.name)] = Color.Grey; @@ -84,27 +122,19 @@ function find_cycle_dfs(c_graph_vertices: IVertexView[], c_graph_edges: IEdgeVie function find_cycle(c_graph_vertices: IVertexView[], c_graph_edges: IEdgeView[] ) { - if(c_graph_vertices.length === 0){ return null; } - var result_cycles:Cycle = new Cycle("G0", [c_graph_vertices[0]]); - - //private_log_6549H += result_cycles.toString() + " v0 = " + c_graph_vertices[0].name + "_"; - - // var v2_list_of_edges_beta: string = ""; - // c_graph_edges.forEach((element: IEdgeView) => { - // v2_list_of_edges_beta+=element.vertexOne + element.vertexTwo + ", "; - // }); - // private_log_6549H += v2_list_of_edges_beta; + var result_cycles:Cycle = new Cycle("G0", [c_graph_vertices[0]], null); let colored:IVertexView[] = []; let c_edge = c_graph_edges.find((e: IEdgeView) => e.vertexOne === result_cycles.vertices[0].name || e.vertexTwo === result_cycles.vertices[0].name); if (c_edge!=null){ - //private_log_6549H += "_____________new vertex i take from edge: " + c_edge.vertexOne + c_edge.vertexTwo; + result_cycles.edges = [c_edge]; + if (c_edge.vertexOne === result_cycles.vertices[0].name){ result_cycles.vertices = result_cycles.vertices.concat([c_graph_vertices.find((v: IVertexView) => v.name === c_edge.vertexTwo)]); colored = colored.concat([c_graph_vertices.find((v: IVertexView) => v.name === c_edge.vertexTwo)]); @@ -115,14 +145,12 @@ function find_cycle(c_graph_vertices: IVertexView[], c_graph_edges: IEdgeView[] } } - //private_log_6549H += result_cycles.toString() + " v0 = " + c_graph_vertices[0].name + "_"; - while (result_cycles.vertices[0] !== result_cycles.vertices[result_cycles.vertices.length - 1]){ c_edge = c_graph_edges.find((e: IEdgeView) => e.vertexOne === result_cycles.vertices[result_cycles.vertices.length - 1].name && e.vertexTwo !== result_cycles.vertices[result_cycles.vertices.length - 2].name && (colored.find((cv: IVertexView) => cv.name === e.vertexTwo) == null) || e.vertexTwo === result_cycles.vertices[result_cycles.vertices.length - 1].name && e.vertexOne !== result_cycles.vertices[result_cycles.vertices.length - 2].name && (colored.find((cv: IVertexView) => cv.name === e.vertexOne) == null)); if (c_edge!=null){ - //private_log_6549H += "_____________new vertes i take from edge: " + c_edge.vertexOne + c_edge.vertexTwo + "_____________colored is:"; - //colcored.forEach(( e: IVertexView) => private_log_6549H += e.name); + result_cycles.edges = result_cycles.edges.concat([c_edge]); + if (c_edge.vertexOne === result_cycles.vertices[result_cycles.vertices.length - 1].name){ result_cycles.vertices = result_cycles.vertices.concat([c_graph_vertices.find((v: IVertexView) => v.name === c_edge.vertexTwo)]); colored = colored.concat([c_graph_vertices.find((v: IVertexView) => v.name === c_edge.vertexTwo)]); @@ -133,10 +161,155 @@ function find_cycle(c_graph_vertices: IVertexView[], c_graph_edges: IEdgeView[] } } } - + return result_cycles; } +function find_segments(faces: Cycle[], graph_vertices: IVertexView[], graph_edges: IEdgeView[], used_edges: IEdgeView[], used_vertices: IVertexView[]): Segment[]{ + + var resultSegments: Segment[] = []; + + //Search segments. + graph_edges.filter(nonUsedEdge => !used_edges.find(e => e == nonUsedEdge)).forEach(nonUsedEdge => { + if (used_vertices.find(v => nonUsedEdge.vertexOne == v.name) && used_vertices.find(v => nonUsedEdge.vertexTwo == v.name)){ + resultSegments.push(new Segment([nonUsedEdge], + [graph_vertices.find(v => v.name == nonUsedEdge.vertexOne), + graph_vertices.find(v => v.name == nonUsedEdge.vertexTwo)], + graph_vertices.find(v => v.name == nonUsedEdge.vertexOne), + graph_vertices.find(v => v.name == nonUsedEdge.vertexTwo))); + + } else if (used_vertices.find(v => nonUsedEdge.vertexOne == v.name)){ + resultSegments.push(find_way(graph_vertices, graph_edges.filter(edge => !used_edges.find(e => e == edge)), graph_vertices.find(v => v.name == nonUsedEdge.vertexOne), used_vertices)); + + } else if (used_vertices.find(v => nonUsedEdge.vertexTwo == v.name)){ + resultSegments.push(find_way(graph_vertices, graph_edges.filter(edge => !used_edges.find(e => e == edge)), graph_vertices.find(v => v.name == nonUsedEdge.vertexTwo), used_vertices)); + } + }); + + //Calculate value of each found segment + resultSegments.forEach(s => s.value = faces.filter( f=> f.vertices.find(v => v.name == s.contactPointOne.name) && f.vertices.find(v => v.name == s.contactPointTwo.name)).length); + + return resultSegments; +} + +function planarity(graph_vertices: IVertexView[], graph_edges: IEdgeView[], zero_cycle: Cycle ) : boolean { + + if(zero_cycle == null){ + return true; + } + if(zero_cycle.vertices.length === 0){ + return true; + } + + var faces: Cycle[] = [zero_cycle, new Cycle("G1", zero_cycle.vertices, zero_cycle.edges)]; + var used_edges: IEdgeView[] = zero_cycle.edges; + var used_vertices: IVertexView[] = zero_cycle.vertices; + + faces.forEach((c: Cycle) => private_log_6549H += c.name + ", ") + private_log_6549H += "_e0^" + used_edges.length + ":"; + used_edges.forEach((element: IEdgeView) => private_log_6549H += element.vertexOne + element.vertexTwo + ", "); + private_log_6549H += "___"; + + var segments : Segment[] = find_segments(faces, graph_vertices, graph_edges, used_edges, used_vertices); + segments.forEach(s => private_log_6549H += s.toString() + "_"); + + var counter = 0; + + while (segments.length != 0 && !segments.find(s => s.value == 0) && counter < 10){ + counter++; + segments.sort(function(a, b) { return b.value - a.value; }); //segments.find( segment => segment.value == segments.reduce((min, s) => s.value < min ? s.value : min, segments[0].value)); + + var minValueSegment = segments.pop(); + var cutFace = faces.splice(faces.findIndex( f => f.vertices.find(v => v.name == minValueSegment.contactPointOne.name) != null && f.vertices.find(v => v.name == minValueSegment.contactPointTwo.name) != null), 1)[0]; + var contactPointOneIndex = cutFace.vertices.findIndex(v => v.name == minValueSegment.contactPointOne.name); + var contactPointTwoIndex = cutFace.vertices.findIndex(v => v.name == minValueSegment.contactPointTwo.name); + + used_vertices = used_vertices.concat(minValueSegment.body_vertices.slice(1, minValueSegment.body_vertices.length - 1)); + used_edges = used_edges.concat(minValueSegment.body_edges.slice()); + + private_log_6549H += "Cutting Face : __ " + cutFace.toString(); + private_log_6549H += "___" + contactPointOneIndex + "^" + contactPointTwoIndex + "---"; + + var newVertices1 : IVertexView[]; + var newVertices2 : IVertexView[]; + var newEdges1 : IEdgeView[]; + var newEdges2 : IEdgeView[]; + + if (contactPointOneIndex < contactPointTwoIndex){ + newVertices1 = cutFace.vertices.slice(0, contactPointOneIndex); + newVertices1 = newVertices1.concat(minValueSegment.body_vertices.slice()); + newVertices1 = newVertices1.concat(cutFace.vertices.slice(contactPointTwoIndex + 1)); + + newEdges1 = cutFace.edges.slice(0, contactPointOneIndex); + newEdges1 = newEdges1.concat(minValueSegment.body_edges.slice()); + newEdges1 = newEdges1.concat(cutFace.edges.slice(contactPointTwoIndex)); + + newVertices2 = minValueSegment.body_vertices.slice(); + newVertices2 = newVertices2.concat(cutFace.vertices.slice(contactPointOneIndex, contactPointTwoIndex).reverse()); + + newEdges2 = minValueSegment.body_edges.slice(); + newEdges2 = newEdges2.concat(cutFace.edges.slice(contactPointOneIndex, contactPointTwoIndex).reverse()); + + } else if (contactPointOneIndex > contactPointTwoIndex){ + newVertices1 = cutFace.vertices.slice(0, contactPointTwoIndex); + newVertices1 = newVertices1.concat(minValueSegment.body_vertices.slice().reverse()); + newVertices1 = newVertices1.concat(cutFace.vertices.slice(contactPointOneIndex + 1)); + + newEdges1 = cutFace.edges.slice(0, contactPointTwoIndex); + newEdges1 = newEdges1.concat(minValueSegment.body_edges.slice().reverse()); + newEdges1 = newEdges1.concat(cutFace.edges.slice(contactPointOneIndex)); + + newVertices2 = minValueSegment.body_vertices.slice().reverse(); + newVertices2 = newVertices2.concat(cutFace.vertices.slice(contactPointTwoIndex, contactPointOneIndex).reverse()); + + newEdges2 = minValueSegment.body_edges.slice().reverse(); + newEdges2 = newEdges2.concat(cutFace.edges.slice(contactPointTwoIndex, contactPointOneIndex).reverse()); + + } else if (contactPointOneIndex == contactPointTwoIndex){ + newVertices1 = cutFace.vertices.slice(); + newEdges1 = cutFace.edges.slice(); + newVertices2 = minValueSegment.body_vertices.slice(); + newEdges2 = minValueSegment.body_edges.slice(); + } + + faces.push(new Cycle(cutFace.name + "0", newVertices1.slice(), newEdges1.slice()), new Cycle(cutFace.name + "1", newVertices2.slice(), newEdges2.slice())); + segments = find_segments(faces, graph_vertices, graph_edges, used_edges, used_vertices); + + private_log_6549H += "__ ||||___________|||| __ "; + + private_log_6549H += "__ vert cutFace: __ "; + cutFace.vertices.forEach(v => private_log_6549H += v.name); + private_log_6549H += "__ edge cutFace: __ "; + cutFace.edges.forEach(e => private_log_6549H += e.vertexOne + e.vertexTwo + "-"); + + private_log_6549H += "__ ||||___________|||| __ "; + + private_log_6549H += "Segment vert: __ "; + minValueSegment.body_vertices.forEach(v => private_log_6549H += v.name); + private_log_6549H += "Segment edge: __ "; + minValueSegment.body_edges.forEach(e => private_log_6549H += e.vertexOne + e.vertexTwo + "-"); + + private_log_6549H += "__ ||||___________|||| __ "; + + private_log_6549H += "__ vert newVertices1: __ "; + newVertices1.forEach(v => private_log_6549H += v.name); + private_log_6549H += "__ vert newVertices2: __ "; + newVertices2.forEach(v => private_log_6549H += v.name); + private_log_6549H += "__ vert edges1 : __ "; + newEdges1.forEach(e => private_log_6549H += e.vertexOne + e.vertexTwo + "-"); + private_log_6549H += "__ vert edges2 : __ "; + newEdges2.forEach(e => private_log_6549H += e.vertexOne + e.vertexTwo + "-"); + } + + if (segments.length == 0){ + return true; + } else if (segments.find(s => s.value == 0)){ + return false; + } + + return null; +} + class App extends TaskTemplate { public getTaskToolbar() { @@ -173,11 +346,15 @@ class App extends TaskTemplate { list_of_edges_beta+=element.vertexOne + element.vertexTwo + ", "; }); - var res_cycl = find_cycle(beta_graph.vertices, beta_graph.edges); - var res_cycl_string = res_cycl==null? "Граф Планарен! Цикла нет.": res_cycl.toString(); + var res_cycle = find_cycle(beta_graph.vertices, beta_graph.edges); + var res_cycle_string = res_cycle==null? "Граф Планарен! Цикла нет.": res_cycle.toString(); //find_cycle_dfs(beta_graph.vertices, beta_graph.edges); + var planarity_result = planarity(beta_graph.vertices, beta_graph.edges, res_cycle); + + + return () => (
В данном графе {graph.vertices.length} вершин.
В данном графе {graph.edges.length} связей.
@@ -185,7 +362,8 @@ class App extends TaskTemplate {
Связи в данном графе: {list_of_edges}


Точки в графе_beta: {list_of_vertices_beta}

Связи в графе_beta: {list_of_edges_beta}
-

Найденный цикл: {res_cycl_string}
+

Найденный цикл: {res_cycle_string}
+

Результат исследования на планарность: {planarity_result.toString()}


Лог: {private_log_6549H}
); diff --git a/src/BetaGraph.tsx b/src/BetaGraph.tsx new file mode 100644 index 0000000..1a87984 --- /dev/null +++ b/src/BetaGraph.tsx @@ -0,0 +1,120 @@ +import { IEdgeView, IVertexView } from 'graphlabs.core.template/build/models/graph'; +import { Cycle } from './Cycle'; +import { Graph, Vertex, Edge } from 'graphlabs.core.graphs'; +import { Segment } from './Segment'; +import { store } from 'graphlabs.core.template'; + +export class BetaGraph { + + vertices: Vertex[]; + edges: IEdgeView[]; + used_vertices: IVertexView[]; + used_edges: IEdgeView[]; + faces: Cycle[]; + planarity: Boolean = null; + segments: Segment[] = []; + +/* constructor(){ + this.vertices = Object.assign({}, store.getState().graph.vertices); + this.edges = Object.assign({}, store.getState().graph.edges); + this.OptimizeGraph() + } + + OptimizeGraph(){ + + this.vertices = this.vertices.filter((v: Vertex) => this.edges.find((e: IEdgeView) => e.vertexOne == v.name || e.vertexTwo == v.name ) ); + + let num_vertices_deleted: number = 0; + let vertices_mig; + + do{ + vertices_mig = this.vertices.filter((v: Vertex) => this.edges.filter((e: IEdgeView) => e.vertexOne === v.name || e.vertexTwo === v.name).length >= 2 ); + num_vertices_deleted = this.vertices.length - vertices_mig.length; + this.vertices = vertices_mig; + + this.edges = this.edges.filter((e: IEdgeView) => this.vertices.find((v: Vertex) => v.name === e.vertexOne ) && this.vertices.find((v: Vertex) => v.name === e.vertexTwo )); + + } while(num_vertices_deleted != 0) + } + */ + findCycle() : Cycle { + + if(this.vertices.length === 0){ + return null; + } + + var result_cycles:Cycle = new Cycle("G0", [this.vertices[0]], null); + + let colored:IVertexView[] = []; + + let c_edge = this.edges.find((e: IEdgeView) => e.vertexOne === result_cycles.vertices[0].name || e.vertexTwo === result_cycles.vertices[0].name); + + if (c_edge!=null){ + result_cycles.edges = [c_edge]; + + if (c_edge.vertexOne === result_cycles.vertices[0].name){ + result_cycles.vertices = result_cycles.vertices.concat([this.vertices.find((v: IVertexView) => v.name === c_edge.vertexTwo)]); + colored = colored.concat([this.vertices.find((v: IVertexView) => v.name === c_edge.vertexTwo)]); + } else + { + result_cycles.vertices = result_cycles.vertices.concat([this.vertices.find((v: IVertexView) => v.name === c_edge.vertexOne)]); + colored = colored.concat([this.vertices.find((v: IVertexView) => v.name === c_edge.vertexOne)]); + } + } + + while (result_cycles.vertices[0] !== result_cycles.vertices[result_cycles.vertices.length - 1]){ + c_edge = this.edges.find((e: IEdgeView) => e.vertexOne === result_cycles.vertices[result_cycles.vertices.length - 1].name && e.vertexTwo !== result_cycles.vertices[result_cycles.vertices.length - 2].name && (colored.find((cv: IVertexView) => cv.name === e.vertexTwo) == null) + || e.vertexTwo === result_cycles.vertices[result_cycles.vertices.length - 1].name && e.vertexOne !== result_cycles.vertices[result_cycles.vertices.length - 2].name && (colored.find((cv: IVertexView) => cv.name === e.vertexOne) == null)); + if (c_edge!=null){ + result_cycles.edges = result_cycles.edges.concat([c_edge]); + + if (c_edge.vertexOne === result_cycles.vertices[result_cycles.vertices.length - 1].name){ + result_cycles.vertices = result_cycles.vertices.concat([this.vertices.find((v: IVertexView) => v.name === c_edge.vertexTwo)]); + colored = colored.concat([this.vertices.find((v: IVertexView) => v.name === c_edge.vertexTwo)]); + } else + { + result_cycles.vertices = result_cycles.vertices.concat([this.vertices.find((v: IVertexView) => v.name === c_edge.vertexOne)]); + colored = colored.concat([this.vertices.find((v: IVertexView) => v.name === c_edge.vertexOne)]); + } + } + } + + return result_cycles; + } + + StartFaces(zero_cycle: Cycle) { + + if (zero_cycle == null){ + zero_cycle = this.findCycle(); + } + + if(zero_cycle == null || zero_cycle.vertices.length === 0){ + this.used_vertices = null; + this.used_edges = null; + this.faces = null; + this.planarity = true; + + return; + } + + this.faces = [zero_cycle, new Cycle("G1", zero_cycle.vertices, zero_cycle.edges)]; + this.used_edges = zero_cycle.edges; + this.used_vertices = zero_cycle.vertices; + } + + find_segments() : string{ + var private_log_6549H : string = ""; + + private_log_6549H += "___I start find segments_________"; + + return private_log_6549H; + } + + toString(): string{ + let str:string = ""; + this.faces.forEach((element: Cycle) => { + str += element.toString() + "__"; + }); + return str; + } +} \ No newline at end of file diff --git a/src/Cycle.tsx b/src/Cycle.tsx index 03439c6..d3d580b 100644 --- a/src/Cycle.tsx +++ b/src/Cycle.tsx @@ -5,12 +5,14 @@ import { IEdgeView, IVertexView } from 'graphlabs.core.template/build/models/gra export class Cycle { name: string; - vertices: IVertexView[]; + vertices: IVertexView[]; + edges: IEdgeView[]; - constructor(name: string, vertices: IVertexView[]) { + constructor(name: string, vertices: IVertexView[], edges: IEdgeView[]) { this.name = name; this.vertices = vertices; + this.edges = edges; } toString(): string{ diff --git a/src/Segment.tsx b/src/Segment.tsx new file mode 100644 index 0000000..7980d12 --- /dev/null +++ b/src/Segment.tsx @@ -0,0 +1,26 @@ +import * as React from 'react'; +import { Graph, Vertex, Edge } from 'graphlabs.core.graphs'; +import { IEdgeView, IVertexView } from 'graphlabs.core.template/build/models/graph'; + +export class Segment { + + body_edges: IEdgeView[]; + body_vertices: IVertexView[]; + value: number; + contactPointOne: IVertexView; + contactPointTwo: IVertexView; + + constructor(body_edges: IEdgeView[], body_vertices : IVertexView[], contactPointOne: IVertexView, contactPointTwo: IVertexView) { + + this.body_edges = body_edges; + this.body_vertices = body_vertices; + this.contactPointOne = contactPointOne; + this.contactPointTwo = contactPointTwo; + } + + toString(): string{ + var str = "segment(" + this.body_vertices.length + ")(" + this.value + "): "; + this.body_vertices.forEach( n => str += n.name ) + return str; + } +} \ No newline at end of file From d5ab3a72a0a66f8f2daaa97699eb8f2b68b2bec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=B0=D1=80=D0=BF=D0=BE=D0=B2=20=D0=95=D0=B3=D0=BE?= =?UTF-8?q?=D1=80=20=D0=90=D0=BD=D0=B4=D1=80=D0=B5=D0=B5=D0=B2=D0=B8=D1=87?= Date: Sun, 12 May 2019 16:48:32 +0300 Subject: [PATCH 04/17] radio button check --- src/App.tsx | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 7e3eb22..a8a1fb9 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,6 +6,7 @@ import { Graph, Vertex, Edge, VertexJSON } from 'graphlabs.core.graphs'; import { Cycle } from './Cycle'; import { element, number } from 'prop-types'; import { Segment } from './Segment'; +import {ChangeEvent, SyntheticEvent} from "react"; function graph_optimize(){ let betaGraph = Object.assign({}, store.getState().graph); @@ -272,6 +273,14 @@ function mainCheck(){ class App extends TaskTemplate { + private studentAnswer?: boolean; + + constructor(props: {}) { + super(props); + this.checkAnswer = this.checkAnswer.bind(this); + } + + public getTaskToolbar() { TaskToolbar.prototype.getButtonList = () => { ToolButtonList.prototype.help = () => `В данном задании будет выполняться проверка @@ -299,13 +308,23 @@ class App extends TaskTemplate { Ответьте на вопрос:
Данный граф является планарным ?
@@ -313,7 +332,12 @@ class App extends TaskTemplate {

{devstring}
); - } + } + + private checkAnswer(value: ChangeEvent) { + this.studentAnswer = value.target.value === '0'; + super.forceUpdate(); + } } -export default App; \ No newline at end of file +export default App; From 50750cf802574b44177822d9866a66c989482c59 Mon Sep 17 00:00:00 2001 From: AnastasiiaRazheva Date: Sun, 12 May 2019 19:52:35 +0300 Subject: [PATCH 05/17] reName + radiobutton MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Удалила отладочные строки. Переименовала, чтобы было без "_". Добавила RadioButton - пока толком не работают ((. --- src/App.tsx | 374 ++++++++++++++++++++-------------------------- src/BetaGraph.tsx | 113 +++----------- src/Segment.tsx | 14 +- 3 files changed, 185 insertions(+), 316 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 33de04a..7e3eb22 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,187 +2,128 @@ import * as React from 'react'; import { BetaGraph } from './BetaGraph'; import { store, TaskTemplate, TaskToolbar, ToolButtonList } from 'graphlabs.core.template'; import { IEdgeView, IVertexView } from 'graphlabs.core.template/build/models/graph'; -import { Graph, Vertex, Edge } from 'graphlabs.core.graphs'; +import { Graph, Vertex, Edge, VertexJSON } from 'graphlabs.core.graphs'; import { Cycle } from './Cycle'; import { element, number } from 'prop-types'; import { Segment } from './Segment'; -import { IVertexVisualizer } from 'graphlabs.core.visualizer'; - -var private_log_6549H: string = ""; - -enum Color { - White = 0, - Grey = 1, - Black = 2 -} function graph_optimize(){ - let beta_graph = Object.assign({}, store.getState().graph); - + let betaGraph = Object.assign({}, store.getState().graph); - beta_graph.vertices = beta_graph.vertices.filter((v: Vertex) => beta_graph.edges.find((e: IEdgeView) => e.vertexOne === v.name || e.vertexTwo === v.name )); + betaGraph.vertices = betaGraph.vertices.filter((v: Vertex) => betaGraph.edges.find((e: IEdgeView) => e.vertexOne === v.name || e.vertexTwo === v.name )); - let num_vertices_deleted: number = 0; - let vertices_mig; + let numVerticesDeleted: number = 0; + let verticesMig; do{ - vertices_mig = beta_graph.vertices.filter((v: Vertex) => beta_graph.edges.filter((e: IEdgeView) => e.vertexOne === v.name || e.vertexTwo === v.name).length >= 2 ); - num_vertices_deleted = beta_graph.vertices.length - vertices_mig.length; - beta_graph.vertices = vertices_mig; + verticesMig = betaGraph.vertices.filter((v: Vertex) => betaGraph.edges.filter((e: IEdgeView) => e.vertexOne === v.name || e.vertexTwo === v.name).length >= 2 ); + numVerticesDeleted = betaGraph.vertices.length - verticesMig.length; + betaGraph.vertices = verticesMig; - beta_graph.edges = beta_graph.edges.filter((e: IEdgeView) => beta_graph.vertices.find((v: Vertex) => v.name === e.vertexOne) && beta_graph.vertices.find((v: Vertex) => v.name === e.vertexTwo)); + betaGraph.edges = betaGraph.edges.filter((e: IEdgeView) => betaGraph.vertices.find((v: Vertex) => v.name === e.vertexOne) && betaGraph.vertices.find((v: Vertex) => v.name === e.vertexTwo)); - } while(num_vertices_deleted != 0) + } while(numVerticesDeleted != 0) - return beta_graph; + return betaGraph; } -function find_way(graph_vertices: IVertexView[], graph_edges: IEdgeView[], start_point: IVertexView, finish_point: IVertexView[]) : Segment{ +function findWay(graphVertices: IVertexView[], graphEdges: IEdgeView[], startPoint: IVertexView, finishPoint: IVertexView[]) : Segment{ - var resultSegment : Segment = new Segment([], [start_point], start_point, null); + var resultSegment : Segment = new Segment([], [startPoint], startPoint, null); var blackList : IEdgeView[] = []; do { - var nextEdge = graph_edges.find( edge => !resultSegment.body_edges.find(e => e == edge) && !blackList.find(e => e == edge) - && (edge.vertexOne == resultSegment.body_vertices[resultSegment.body_vertices.length - 1].name - || edge.vertexTwo == resultSegment.body_vertices[resultSegment.body_vertices.length - 1].name)); + var nextEdge = graphEdges.find( edge => !resultSegment.bodyEdges.find(e => e == edge) && !blackList.find(e => e == edge) + && (edge.vertexOne == resultSegment.bodyVertices[resultSegment.bodyVertices.length - 1].name + || edge.vertexTwo == resultSegment.bodyVertices[resultSegment.bodyVertices.length - 1].name)); if (nextEdge == null){ - if (resultSegment.body_edges.length == 0){ + if (resultSegment.bodyEdges.length == 0){ return null; } - blackList.push(resultSegment.body_edges.pop()); - resultSegment.body_vertices.pop(); + blackList.push(resultSegment.bodyEdges.pop()); + resultSegment.bodyVertices.pop(); continue; } - resultSegment.body_edges.push(nextEdge); + resultSegment.bodyEdges.push(nextEdge); - if (nextEdge.vertexOne == resultSegment.body_vertices[resultSegment.body_vertices.length - 1].name){ - resultSegment.body_vertices.push(graph_vertices.find(v => v.name == nextEdge.vertexTwo)); - resultSegment.contactPointTwo = graph_vertices.find(v => v.name ==nextEdge.vertexTwo); + if (nextEdge.vertexOne == resultSegment.bodyVertices[resultSegment.bodyVertices.length - 1].name){ + resultSegment.bodyVertices.push(graphVertices.find(v => v.name == nextEdge.vertexTwo)); + resultSegment.contactPointTwo = graphVertices.find(v => v.name ==nextEdge.vertexTwo); } else { - resultSegment.body_vertices.push(graph_vertices.find(v => v.name == nextEdge.vertexOne)); - resultSegment.contactPointTwo = graph_vertices.find(v => v.name == nextEdge.vertexOne); + resultSegment.bodyVertices.push(graphVertices.find(v => v.name == nextEdge.vertexOne)); + resultSegment.contactPointTwo = graphVertices.find(v => v.name == nextEdge.vertexOne); } - } while (!finish_point.find(v => resultSegment.contactPointTwo.name == v.name)) + } while (!finishPoint.find(v => resultSegment.contactPointTwo.name == v.name)) return resultSegment } -/* function dfs(vertex: IVertexView, c_graph_vertices: IVertexView[], c_graph_edges: IEdgeView[], colored: Color[]) { - colored[Number(vertex.name)] = Color.Grey; - - c_graph_edges.filter((element: IEdgeView) => (element.vertexOne == vertex.name && colored[Number(element.vertexOne)] != Color.Black) - || (element.vertexTwo == vertex.name && colored[Number(element.vertexTwo)] != Color.Black)) - .forEach((element: IEdgeView) => { - if (element.vertexOne == vertex.name){ - if (colored[Number(element.vertexTwo)] == Color.White){ - dfs(c_graph_vertices.find((v: IVertexView) => v.name == element.vertexTwo), c_graph_vertices, c_graph_edges, colored); - } - else if(colored[Number(element.vertexTwo)] == Color.Grey){ - private_log_6549H += "___" + "I find the cycle" + colored + "___"; - } - } - else if(element.vertexTwo == vertex.name){ - if (colored[Number(element.vertexOne)] == Color.White){ - dfs(c_graph_vertices.find((v: IVertexView) => v.name == element.vertexOne), c_graph_vertices, c_graph_edges, colored); - } - else if(colored[Number(element.vertexOne)] == Color.Grey){ - private_log_6549H += "___" + "I find the cycle" + colored + "___"; - } - } - colored[Number(vertex.name)] = Color.Black; - }); - - return colored; -} - - -function find_cycle_dfs(c_graph_vertices: IVertexView[], c_graph_edges: IEdgeView[]) { - - //if(c_graph_vertices.length === 0){ - // return null; - //} - - let result_cycle:Cycle[] = []; - - const graph = store.getState().graph; - let colored = new Array(graph.vertices.length).fill(Color.White); - - private_log_6549H += "___" + colored + "___"; - - colored = dfs(c_graph_vertices[0], c_graph_vertices, c_graph_edges, colored); - - private_log_6549H += "___" + colored + "___"; - - return result_cycle; -} */ - -function find_cycle(c_graph_vertices: IVertexView[], c_graph_edges: IEdgeView[] ) { +function findCycle(graphVertices: IVertexView[], graphEdges: IEdgeView[] ) { - if(c_graph_vertices.length === 0){ + if(graphVertices.length === 0){ return null; } - var result_cycles:Cycle = new Cycle("G0", [c_graph_vertices[0]], null); + var resultCycle:Cycle = new Cycle("G0", [graphVertices[0]], null); let colored:IVertexView[] = []; - let c_edge = c_graph_edges.find((e: IEdgeView) => e.vertexOne === result_cycles.vertices[0].name || e.vertexTwo === result_cycles.vertices[0].name); + let nextEdge = graphEdges.find((e: IEdgeView) => e.vertexOne === resultCycle.vertices[0].name || e.vertexTwo === resultCycle.vertices[0].name); - if (c_edge!=null){ - result_cycles.edges = [c_edge]; + if (nextEdge!=null){ + resultCycle.edges = [nextEdge]; - if (c_edge.vertexOne === result_cycles.vertices[0].name){ - result_cycles.vertices = result_cycles.vertices.concat([c_graph_vertices.find((v: IVertexView) => v.name === c_edge.vertexTwo)]); - colored = colored.concat([c_graph_vertices.find((v: IVertexView) => v.name === c_edge.vertexTwo)]); + if (nextEdge.vertexOne === resultCycle.vertices[0].name){ + resultCycle.vertices = resultCycle.vertices.concat([graphVertices.find((v: IVertexView) => v.name === nextEdge.vertexTwo)]); + colored = colored.concat([graphVertices.find((v: IVertexView) => v.name === nextEdge.vertexTwo)]); } else { - result_cycles.vertices = result_cycles.vertices.concat([c_graph_vertices.find((v: IVertexView) => v.name === c_edge.vertexOne)]); - colored = colored.concat([c_graph_vertices.find((v: IVertexView) => v.name === c_edge.vertexOne)]); + resultCycle.vertices = resultCycle.vertices.concat([graphVertices.find((v: IVertexView) => v.name === nextEdge.vertexOne)]); + colored = colored.concat([graphVertices.find((v: IVertexView) => v.name === nextEdge.vertexOne)]); } } - while (result_cycles.vertices[0] !== result_cycles.vertices[result_cycles.vertices.length - 1]){ - c_edge = c_graph_edges.find((e: IEdgeView) => e.vertexOne === result_cycles.vertices[result_cycles.vertices.length - 1].name && e.vertexTwo !== result_cycles.vertices[result_cycles.vertices.length - 2].name && (colored.find((cv: IVertexView) => cv.name === e.vertexTwo) == null) - || e.vertexTwo === result_cycles.vertices[result_cycles.vertices.length - 1].name && e.vertexOne !== result_cycles.vertices[result_cycles.vertices.length - 2].name && (colored.find((cv: IVertexView) => cv.name === e.vertexOne) == null)); - if (c_edge!=null){ - result_cycles.edges = result_cycles.edges.concat([c_edge]); + while (resultCycle.vertices[0] !== resultCycle.vertices[resultCycle.vertices.length - 1]){ + nextEdge = graphEdges.find((e: IEdgeView) => e.vertexOne === resultCycle.vertices[resultCycle.vertices.length - 1].name && e.vertexTwo !== resultCycle.vertices[resultCycle.vertices.length - 2].name && (colored.find((cv: IVertexView) => cv.name === e.vertexTwo) == null) + || e.vertexTwo === resultCycle.vertices[resultCycle.vertices.length - 1].name && e.vertexOne !== resultCycle.vertices[resultCycle.vertices.length - 2].name && (colored.find((cv: IVertexView) => cv.name === e.vertexOne) == null)); + if (nextEdge!=null){ + resultCycle.edges = resultCycle.edges.concat([nextEdge]); - if (c_edge.vertexOne === result_cycles.vertices[result_cycles.vertices.length - 1].name){ - result_cycles.vertices = result_cycles.vertices.concat([c_graph_vertices.find((v: IVertexView) => v.name === c_edge.vertexTwo)]); - colored = colored.concat([c_graph_vertices.find((v: IVertexView) => v.name === c_edge.vertexTwo)]); + if (nextEdge.vertexOne === resultCycle.vertices[resultCycle.vertices.length - 1].name){ + resultCycle.vertices = resultCycle.vertices.concat([graphVertices.find((v: IVertexView) => v.name === nextEdge.vertexTwo)]); + colored = colored.concat([graphVertices.find((v: IVertexView) => v.name === nextEdge.vertexTwo)]); } else { - result_cycles.vertices = result_cycles.vertices.concat([c_graph_vertices.find((v: IVertexView) => v.name === c_edge.vertexOne)]); - colored = colored.concat([c_graph_vertices.find((v: IVertexView) => v.name === c_edge.vertexOne)]); + resultCycle.vertices = resultCycle.vertices.concat([graphVertices.find((v: IVertexView) => v.name === nextEdge.vertexOne)]); + colored = colored.concat([graphVertices.find((v: IVertexView) => v.name === nextEdge.vertexOne)]); } } } - return result_cycles; + return resultCycle; } -function find_segments(faces: Cycle[], graph_vertices: IVertexView[], graph_edges: IEdgeView[], used_edges: IEdgeView[], used_vertices: IVertexView[]): Segment[]{ +function findSegments(faces: Cycle[], graphVertices: IVertexView[], graphEdges: IEdgeView[], usedEdges: IEdgeView[], usedVertices: IVertexView[]): Segment[]{ var resultSegments: Segment[] = []; //Search segments. - graph_edges.filter(nonUsedEdge => !used_edges.find(e => e == nonUsedEdge)).forEach(nonUsedEdge => { - if (used_vertices.find(v => nonUsedEdge.vertexOne == v.name) && used_vertices.find(v => nonUsedEdge.vertexTwo == v.name)){ + graphEdges.filter(nonUsedEdge => !usedEdges.find(e => e == nonUsedEdge)).forEach(nonUsedEdge => { + if (usedVertices.find(v => nonUsedEdge.vertexOne == v.name) && usedVertices.find(v => nonUsedEdge.vertexTwo == v.name)){ resultSegments.push(new Segment([nonUsedEdge], - [graph_vertices.find(v => v.name == nonUsedEdge.vertexOne), - graph_vertices.find(v => v.name == nonUsedEdge.vertexTwo)], - graph_vertices.find(v => v.name == nonUsedEdge.vertexOne), - graph_vertices.find(v => v.name == nonUsedEdge.vertexTwo))); + [graphVertices.find(v => v.name == nonUsedEdge.vertexOne), + graphVertices.find(v => v.name == nonUsedEdge.vertexTwo)], + graphVertices.find(v => v.name == nonUsedEdge.vertexOne), + graphVertices.find(v => v.name == nonUsedEdge.vertexTwo))); - } else if (used_vertices.find(v => nonUsedEdge.vertexOne == v.name)){ - resultSegments.push(find_way(graph_vertices, graph_edges.filter(edge => !used_edges.find(e => e == edge)), graph_vertices.find(v => v.name == nonUsedEdge.vertexOne), used_vertices)); + } else if (usedVertices.find(v => nonUsedEdge.vertexOne == v.name)){ + resultSegments.push(findWay(graphVertices, graphEdges.filter(edge => !usedEdges.find(e => e == edge)), graphVertices.find(v => v.name == nonUsedEdge.vertexOne), usedVertices)); - } else if (used_vertices.find(v => nonUsedEdge.vertexTwo == v.name)){ - resultSegments.push(find_way(graph_vertices, graph_edges.filter(edge => !used_edges.find(e => e == edge)), graph_vertices.find(v => v.name == nonUsedEdge.vertexTwo), used_vertices)); + } else if (usedVertices.find(v => nonUsedEdge.vertexTwo == v.name)){ + resultSegments.push(findWay(graphVertices, graphEdges.filter(edge => !usedEdges.find(e => e == edge)), graphVertices.find(v => v.name == nonUsedEdge.vertexTwo), usedVertices)); } }); @@ -192,43 +133,32 @@ function find_segments(faces: Cycle[], graph_vertices: IVertexView[], graph_edge return resultSegments; } -function planarity(graph_vertices: IVertexView[], graph_edges: IEdgeView[], zero_cycle: Cycle ) : boolean { +function checkPlanarity(graphVertices: IVertexView[], graphEdges: IEdgeView[], zeroCycle: Cycle ) : boolean { - if(zero_cycle == null){ + if(zeroCycle == null){ return true; } - if(zero_cycle.vertices.length === 0){ + if(zeroCycle.vertices.length === 0){ return true; } - var faces: Cycle[] = [zero_cycle, new Cycle("G1", zero_cycle.vertices, zero_cycle.edges)]; - var used_edges: IEdgeView[] = zero_cycle.edges; - var used_vertices: IVertexView[] = zero_cycle.vertices; - - faces.forEach((c: Cycle) => private_log_6549H += c.name + ", ") - private_log_6549H += "_e0^" + used_edges.length + ":"; - used_edges.forEach((element: IEdgeView) => private_log_6549H += element.vertexOne + element.vertexTwo + ", "); - private_log_6549H += "___"; - - var segments : Segment[] = find_segments(faces, graph_vertices, graph_edges, used_edges, used_vertices); - segments.forEach(s => private_log_6549H += s.toString() + "_"); - + var faces: Cycle[] = [zeroCycle, new Cycle("G1", zeroCycle.vertices, zeroCycle.edges)]; + var usedEdges: IEdgeView[] = zeroCycle.edges; + var usedVertices: IVertexView[] = zeroCycle.vertices; + var segments : Segment[] = findSegments(faces, graphVertices, graphEdges, usedEdges, usedVertices); var counter = 0; - while (segments.length != 0 && !segments.find(s => s.value == 0) && counter < 10){ + while (segments.length != 0 && !segments.find(s => s.value == 0) && counter < 100){ counter++; - segments.sort(function(a, b) { return b.value - a.value; }); //segments.find( segment => segment.value == segments.reduce((min, s) => s.value < min ? s.value : min, segments[0].value)); + segments.sort(function(a, b) { return b.value - a.value; }); var minValueSegment = segments.pop(); var cutFace = faces.splice(faces.findIndex( f => f.vertices.find(v => v.name == minValueSegment.contactPointOne.name) != null && f.vertices.find(v => v.name == minValueSegment.contactPointTwo.name) != null), 1)[0]; var contactPointOneIndex = cutFace.vertices.findIndex(v => v.name == minValueSegment.contactPointOne.name); var contactPointTwoIndex = cutFace.vertices.findIndex(v => v.name == minValueSegment.contactPointTwo.name); - used_vertices = used_vertices.concat(minValueSegment.body_vertices.slice(1, minValueSegment.body_vertices.length - 1)); - used_edges = used_edges.concat(minValueSegment.body_edges.slice()); - - private_log_6549H += "Cutting Face : __ " + cutFace.toString(); - private_log_6549H += "___" + contactPointOneIndex + "^" + contactPointTwoIndex + "---"; + usedVertices = usedVertices.concat(minValueSegment.bodyVertices.slice(1, minValueSegment.bodyVertices.length - 1)); + usedEdges = usedEdges.concat(minValueSegment.bodyEdges.slice()); var newVertices1 : IVertexView[]; var newVertices2 : IVertexView[]; @@ -237,68 +167,43 @@ function planarity(graph_vertices: IVertexView[], graph_edges: IEdgeView[], zero if (contactPointOneIndex < contactPointTwoIndex){ newVertices1 = cutFace.vertices.slice(0, contactPointOneIndex); - newVertices1 = newVertices1.concat(minValueSegment.body_vertices.slice()); + newVertices1 = newVertices1.concat(minValueSegment.bodyVertices.slice()); newVertices1 = newVertices1.concat(cutFace.vertices.slice(contactPointTwoIndex + 1)); newEdges1 = cutFace.edges.slice(0, contactPointOneIndex); - newEdges1 = newEdges1.concat(minValueSegment.body_edges.slice()); + newEdges1 = newEdges1.concat(minValueSegment.bodyEdges.slice()); newEdges1 = newEdges1.concat(cutFace.edges.slice(contactPointTwoIndex)); - newVertices2 = minValueSegment.body_vertices.slice(); + newVertices2 = minValueSegment.bodyVertices.slice(); newVertices2 = newVertices2.concat(cutFace.vertices.slice(contactPointOneIndex, contactPointTwoIndex).reverse()); - newEdges2 = minValueSegment.body_edges.slice(); + newEdges2 = minValueSegment.bodyEdges.slice(); newEdges2 = newEdges2.concat(cutFace.edges.slice(contactPointOneIndex, contactPointTwoIndex).reverse()); } else if (contactPointOneIndex > contactPointTwoIndex){ newVertices1 = cutFace.vertices.slice(0, contactPointTwoIndex); - newVertices1 = newVertices1.concat(minValueSegment.body_vertices.slice().reverse()); + newVertices1 = newVertices1.concat(minValueSegment.bodyVertices.slice().reverse()); newVertices1 = newVertices1.concat(cutFace.vertices.slice(contactPointOneIndex + 1)); newEdges1 = cutFace.edges.slice(0, contactPointTwoIndex); - newEdges1 = newEdges1.concat(minValueSegment.body_edges.slice().reverse()); + newEdges1 = newEdges1.concat(minValueSegment.bodyEdges.slice().reverse()); newEdges1 = newEdges1.concat(cutFace.edges.slice(contactPointOneIndex)); - newVertices2 = minValueSegment.body_vertices.slice().reverse(); + newVertices2 = minValueSegment.bodyVertices.slice().reverse(); newVertices2 = newVertices2.concat(cutFace.vertices.slice(contactPointTwoIndex, contactPointOneIndex).reverse()); - newEdges2 = minValueSegment.body_edges.slice().reverse(); + newEdges2 = minValueSegment.bodyEdges.slice().reverse(); newEdges2 = newEdges2.concat(cutFace.edges.slice(contactPointTwoIndex, contactPointOneIndex).reverse()); } else if (contactPointOneIndex == contactPointTwoIndex){ newVertices1 = cutFace.vertices.slice(); newEdges1 = cutFace.edges.slice(); - newVertices2 = minValueSegment.body_vertices.slice(); - newEdges2 = minValueSegment.body_edges.slice(); + newVertices2 = minValueSegment.bodyVertices.slice(); + newEdges2 = minValueSegment.bodyEdges.slice(); } faces.push(new Cycle(cutFace.name + "0", newVertices1.slice(), newEdges1.slice()), new Cycle(cutFace.name + "1", newVertices2.slice(), newEdges2.slice())); - segments = find_segments(faces, graph_vertices, graph_edges, used_edges, used_vertices); - - private_log_6549H += "__ ||||___________|||| __ "; - - private_log_6549H += "__ vert cutFace: __ "; - cutFace.vertices.forEach(v => private_log_6549H += v.name); - private_log_6549H += "__ edge cutFace: __ "; - cutFace.edges.forEach(e => private_log_6549H += e.vertexOne + e.vertexTwo + "-"); - - private_log_6549H += "__ ||||___________|||| __ "; - - private_log_6549H += "Segment vert: __ "; - minValueSegment.body_vertices.forEach(v => private_log_6549H += v.name); - private_log_6549H += "Segment edge: __ "; - minValueSegment.body_edges.forEach(e => private_log_6549H += e.vertexOne + e.vertexTwo + "-"); - - private_log_6549H += "__ ||||___________|||| __ "; - - private_log_6549H += "__ vert newVertices1: __ "; - newVertices1.forEach(v => private_log_6549H += v.name); - private_log_6549H += "__ vert newVertices2: __ "; - newVertices2.forEach(v => private_log_6549H += v.name); - private_log_6549H += "__ vert edges1 : __ "; - newEdges1.forEach(e => private_log_6549H += e.vertexOne + e.vertexTwo + "-"); - private_log_6549H += "__ vert edges2 : __ "; - newEdges2.forEach(e => private_log_6549H += e.vertexOne + e.vertexTwo + "-"); + segments = findSegments(faces, graphVertices, graphEdges, usedEdges, usedVertices); } if (segments.length == 0){ @@ -310,6 +215,61 @@ function planarity(graph_vertices: IVertexView[], graph_edges: IEdgeView[], zero return null; } +function addK5Edges(){ + const graph = store.getState().graph; + + var newEdge : IEdgeView = graph.edges.slice(0,1); + + graph.vertices.forEach((v1: Vertex) => { + graph.vertices.forEach((v2: Vertex) => { + newEdge.vertexOne = v1.name; + newEdge.vertexTwo = v2.name; + graph.edges.push(Object.assign({}, newEdge)); + }) + }); +} + +function graphСheck(){ + const graph = store.getState().graph; + + /** Сheck graph state for defects. */ + + //Duplicates + + graph.vertices.forEach((element: Vertex, index: Number) => { + if (graph.vertices.filter((v: Vertex) => v.name == element.name).length > 1){ + graph.vertices.splice(index, 1); + } + }); + + // + 2 edges from same vertices + graph.edges.forEach((element: IEdgeView, index: Number) => { + if (graph.edges.filter((e: IEdgeView) => e.vertexOne == element.vertexOne && e.vertexTwo == element.vertexTwo + || e.vertexOne == element.vertexTwo && e.vertexTwo == element.vertexOne).length > 1){ + graph.edges.splice(index, 1); + } + }); + + //Edges to nonexistent vertex + graph.edges.forEach((element: IEdgeView, index: Number) => { + if (!graph.vertices.find((v: Vertex) => v.name == element.vertexOne || v.name == element.vertexTwo)){ + graph.edges.splice(index, 1); + } + }); + + //Zero value edges + graph.edges.forEach((element: IEdgeView, index: Number) => { + if (element.vertexOne == element.vertexTwo){ + graph.edges.splice(index, 1); + } + }); +} + +function mainCheck(){ + var beta_graph = graph_optimize(); + return checkPlanarity(beta_graph.vertices, beta_graph.edges, findCycle(beta_graph.vertices, beta_graph.edges)); +} + class App extends TaskTemplate { public getTaskToolbar() { @@ -322,49 +282,35 @@ class App extends TaskTemplate { } public task() { - const graph = store.getState().graph; - - var list_of_vertices: string = ""; - graph.vertices.forEach((element: Vertex) => { - list_of_vertices += element.name; - }) - - var list_of_edges: string = ""; - graph.edges.forEach((element: IEdgeView) => { - list_of_edges+=element.vertexOne + element.vertexTwo + " , "; - }); - - var beta_graph = graph_optimize(); - - var list_of_vertices_beta: string = ""; - beta_graph.vertices.forEach((element: Vertex) => { - list_of_vertices_beta += element.name; - }) - - var list_of_edges_beta: string = ""; - beta_graph.edges.forEach((element: IEdgeView) => { - list_of_edges_beta+=element.vertexOne + element.vertexTwo + ", "; - }); - - var res_cycle = find_cycle(beta_graph.vertices, beta_graph.edges); - var res_cycle_string = res_cycle==null? "Граф Планарен! Цикла нет.": res_cycle.toString(); - - //find_cycle_dfs(beta_graph.vertices, beta_graph.edges); - - var planarity_result = planarity(beta_graph.vertices, beta_graph.edges, res_cycle); + //addK5Edges(); + graphСheck(); + var planarity_result = mainCheck(); + + var devstring = ""; + if (planarity_result == null){ + devstring += "Пожалуйста сообщите об этом преподавателю или лаборанту. Результат проверки на планарность = null"; + } return () => (
- В данном графе {graph.vertices.length} вершин.
В данном графе {graph.edges.length} связей.
-

Точки в данном графе: {list_of_vertices}
-
Связи в данном графе: {list_of_edges}
-

Точки в графе_beta: {list_of_vertices_beta}
-
Связи в графе_beta: {list_of_edges_beta}
-

Найденный цикл: {res_cycle_string}
-

Результат исследования на планарность: {planarity_result.toString()}
-

Лог: {private_log_6549H}
+
+ Ответьте на вопрос:
Данный граф является планарным ?
+
+ +
+
+ +
+
+

{devstring}
); } diff --git a/src/BetaGraph.tsx b/src/BetaGraph.tsx index 1a87984..b0870f3 100644 --- a/src/BetaGraph.tsx +++ b/src/BetaGraph.tsx @@ -6,115 +6,38 @@ import { store } from 'graphlabs.core.template'; export class BetaGraph { - vertices: Vertex[]; + vertices: IVertexView[]; edges: IEdgeView[]; - used_vertices: IVertexView[]; - used_edges: IEdgeView[]; + usedVertices: IVertexView[]; + usedEdges: IEdgeView[]; faces: Cycle[]; - planarity: Boolean = null; - segments: Segment[] = []; + planarity: Boolean; + segments: Segment[]; -/* constructor(){ - this.vertices = Object.assign({}, store.getState().graph.vertices); - this.edges = Object.assign({}, store.getState().graph.edges); - this.OptimizeGraph() + constructor( vertices: IVertexView[], edges: IEdgeView[]){ + this.vertices = vertices.slice(); + this.edges = edges.slice(); } - OptimizeGraph(){ + OptimizeGraph() { - this.vertices = this.vertices.filter((v: Vertex) => this.edges.find((e: IEdgeView) => e.vertexOne == v.name || e.vertexTwo == v.name ) ); + if (!this.vertices || !this.edges){ return null; } + if (this.vertices.length == 0 || this.edges.length == 0){ return false; } + + this.vertices = this.vertices.filter((v: IVertexView) => this.edges.find((e: IEdgeView) => e.vertexOne == v.name || e.vertexTwo == v.name )); let num_vertices_deleted: number = 0; let vertices_mig; do{ - vertices_mig = this.vertices.filter((v: Vertex) => this.edges.filter((e: IEdgeView) => e.vertexOne === v.name || e.vertexTwo === v.name).length >= 2 ); + vertices_mig = this.vertices.filter((v: IVertexView) => this.edges.filter((e: IEdgeView) => e.vertexOne === v.name || e.vertexTwo === v.name).length >= 2 ); num_vertices_deleted = this.vertices.length - vertices_mig.length; this.vertices = vertices_mig; - this.edges = this.edges.filter((e: IEdgeView) => this.vertices.find((v: Vertex) => v.name === e.vertexOne ) && this.vertices.find((v: Vertex) => v.name === e.vertexTwo )); + this.edges = this.edges.filter((e: IEdgeView) => this.vertices.find((v: IVertexView) => v.name === e.vertexOne ) && this.vertices.find((v: IVertexView) => v.name === e.vertexTwo )); - } while(num_vertices_deleted != 0) - } - */ - findCycle() : Cycle { - - if(this.vertices.length === 0){ - return null; - } - - var result_cycles:Cycle = new Cycle("G0", [this.vertices[0]], null); - - let colored:IVertexView[] = []; - - let c_edge = this.edges.find((e: IEdgeView) => e.vertexOne === result_cycles.vertices[0].name || e.vertexTwo === result_cycles.vertices[0].name); - - if (c_edge!=null){ - result_cycles.edges = [c_edge]; - - if (c_edge.vertexOne === result_cycles.vertices[0].name){ - result_cycles.vertices = result_cycles.vertices.concat([this.vertices.find((v: IVertexView) => v.name === c_edge.vertexTwo)]); - colored = colored.concat([this.vertices.find((v: IVertexView) => v.name === c_edge.vertexTwo)]); - } else - { - result_cycles.vertices = result_cycles.vertices.concat([this.vertices.find((v: IVertexView) => v.name === c_edge.vertexOne)]); - colored = colored.concat([this.vertices.find((v: IVertexView) => v.name === c_edge.vertexOne)]); - } - } - - while (result_cycles.vertices[0] !== result_cycles.vertices[result_cycles.vertices.length - 1]){ - c_edge = this.edges.find((e: IEdgeView) => e.vertexOne === result_cycles.vertices[result_cycles.vertices.length - 1].name && e.vertexTwo !== result_cycles.vertices[result_cycles.vertices.length - 2].name && (colored.find((cv: IVertexView) => cv.name === e.vertexTwo) == null) - || e.vertexTwo === result_cycles.vertices[result_cycles.vertices.length - 1].name && e.vertexOne !== result_cycles.vertices[result_cycles.vertices.length - 2].name && (colored.find((cv: IVertexView) => cv.name === e.vertexOne) == null)); - if (c_edge!=null){ - result_cycles.edges = result_cycles.edges.concat([c_edge]); - - if (c_edge.vertexOne === result_cycles.vertices[result_cycles.vertices.length - 1].name){ - result_cycles.vertices = result_cycles.vertices.concat([this.vertices.find((v: IVertexView) => v.name === c_edge.vertexTwo)]); - colored = colored.concat([this.vertices.find((v: IVertexView) => v.name === c_edge.vertexTwo)]); - } else - { - result_cycles.vertices = result_cycles.vertices.concat([this.vertices.find((v: IVertexView) => v.name === c_edge.vertexOne)]); - colored = colored.concat([this.vertices.find((v: IVertexView) => v.name === c_edge.vertexOne)]); - } - } - } - - return result_cycles; - } + } while(num_vertices_deleted != 0); - StartFaces(zero_cycle: Cycle) { - - if (zero_cycle == null){ - zero_cycle = this.findCycle(); - } - - if(zero_cycle == null || zero_cycle.vertices.length === 0){ - this.used_vertices = null; - this.used_edges = null; - this.faces = null; - this.planarity = true; - - return; - } - - this.faces = [zero_cycle, new Cycle("G1", zero_cycle.vertices, zero_cycle.edges)]; - this.used_edges = zero_cycle.edges; - this.used_vertices = zero_cycle.vertices; - } - - find_segments() : string{ - var private_log_6549H : string = ""; - - private_log_6549H += "___I start find segments_________"; - - return private_log_6549H; - } - - toString(): string{ - let str:string = ""; - this.faces.forEach((element: Cycle) => { - str += element.toString() + "__"; - }); - return str; - } + return true; + } } \ No newline at end of file diff --git a/src/Segment.tsx b/src/Segment.tsx index 7980d12..0bb550e 100644 --- a/src/Segment.tsx +++ b/src/Segment.tsx @@ -4,23 +4,23 @@ import { IEdgeView, IVertexView } from 'graphlabs.core.template/build/models/gra export class Segment { - body_edges: IEdgeView[]; - body_vertices: IVertexView[]; + bodyEdges: IEdgeView[]; + bodyVertices: IVertexView[]; value: number; contactPointOne: IVertexView; contactPointTwo: IVertexView; - constructor(body_edges: IEdgeView[], body_vertices : IVertexView[], contactPointOne: IVertexView, contactPointTwo: IVertexView) { + constructor(bodyEdges: IEdgeView[], bodyVertices : IVertexView[], contactPointOne: IVertexView, contactPointTwo: IVertexView) { - this.body_edges = body_edges; - this.body_vertices = body_vertices; + this.bodyEdges = bodyEdges; + this.bodyVertices = bodyVertices; this.contactPointOne = contactPointOne; this.contactPointTwo = contactPointTwo; } toString(): string{ - var str = "segment(" + this.body_vertices.length + ")(" + this.value + "): "; - this.body_vertices.forEach( n => str += n.name ) + var str = "segment(" + this.bodyVertices.length + ")(" + this.value + "): "; + this.bodyVertices.forEach( n => str += n.name ) return str; } } \ No newline at end of file From 5bcb3bd9e434a1499f1d0a666ff15583e377d59d Mon Sep 17 00:00:00 2001 From: AnastasiiaRazheva Date: Mon, 13 May 2019 01:10:52 +0300 Subject: [PATCH 06/17] OOP + splitGraphByBridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Перенесла всё в класс BetaGraph. Добавила разбиение Графа в случае наличия моста. --- src/App.tsx | 277 ++++++++++--------------------------------- src/BetaGraph.tsx | 296 +++++++++++++++++++++++++++++++++++++++++++--- src/Cycle.tsx | 6 +- src/Segment.tsx | 10 +- 4 files changed, 348 insertions(+), 241 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 7e3eb22..1684b88 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -7,214 +7,6 @@ import { Cycle } from './Cycle'; import { element, number } from 'prop-types'; import { Segment } from './Segment'; -function graph_optimize(){ - let betaGraph = Object.assign({}, store.getState().graph); - - betaGraph.vertices = betaGraph.vertices.filter((v: Vertex) => betaGraph.edges.find((e: IEdgeView) => e.vertexOne === v.name || e.vertexTwo === v.name )); - - let numVerticesDeleted: number = 0; - let verticesMig; - - do{ - verticesMig = betaGraph.vertices.filter((v: Vertex) => betaGraph.edges.filter((e: IEdgeView) => e.vertexOne === v.name || e.vertexTwo === v.name).length >= 2 ); - numVerticesDeleted = betaGraph.vertices.length - verticesMig.length; - betaGraph.vertices = verticesMig; - - betaGraph.edges = betaGraph.edges.filter((e: IEdgeView) => betaGraph.vertices.find((v: Vertex) => v.name === e.vertexOne) && betaGraph.vertices.find((v: Vertex) => v.name === e.vertexTwo)); - - } while(numVerticesDeleted != 0) - - return betaGraph; -} - -function findWay(graphVertices: IVertexView[], graphEdges: IEdgeView[], startPoint: IVertexView, finishPoint: IVertexView[]) : Segment{ - - var resultSegment : Segment = new Segment([], [startPoint], startPoint, null); - var blackList : IEdgeView[] = []; - - do { - var nextEdge = graphEdges.find( edge => !resultSegment.bodyEdges.find(e => e == edge) && !blackList.find(e => e == edge) - && (edge.vertexOne == resultSegment.bodyVertices[resultSegment.bodyVertices.length - 1].name - || edge.vertexTwo == resultSegment.bodyVertices[resultSegment.bodyVertices.length - 1].name)); - - if (nextEdge == null){ - if (resultSegment.bodyEdges.length == 0){ - return null; - } - blackList.push(resultSegment.bodyEdges.pop()); - resultSegment.bodyVertices.pop(); - continue; - } - - resultSegment.bodyEdges.push(nextEdge); - - if (nextEdge.vertexOne == resultSegment.bodyVertices[resultSegment.bodyVertices.length - 1].name){ - resultSegment.bodyVertices.push(graphVertices.find(v => v.name == nextEdge.vertexTwo)); - resultSegment.contactPointTwo = graphVertices.find(v => v.name ==nextEdge.vertexTwo); - } else { - resultSegment.bodyVertices.push(graphVertices.find(v => v.name == nextEdge.vertexOne)); - resultSegment.contactPointTwo = graphVertices.find(v => v.name == nextEdge.vertexOne); - } - - } while (!finishPoint.find(v => resultSegment.contactPointTwo.name == v.name)) - - return resultSegment -} - -function findCycle(graphVertices: IVertexView[], graphEdges: IEdgeView[] ) { - - if(graphVertices.length === 0){ - return null; - } - - var resultCycle:Cycle = new Cycle("G0", [graphVertices[0]], null); - - let colored:IVertexView[] = []; - - let nextEdge = graphEdges.find((e: IEdgeView) => e.vertexOne === resultCycle.vertices[0].name || e.vertexTwo === resultCycle.vertices[0].name); - - if (nextEdge!=null){ - resultCycle.edges = [nextEdge]; - - if (nextEdge.vertexOne === resultCycle.vertices[0].name){ - resultCycle.vertices = resultCycle.vertices.concat([graphVertices.find((v: IVertexView) => v.name === nextEdge.vertexTwo)]); - colored = colored.concat([graphVertices.find((v: IVertexView) => v.name === nextEdge.vertexTwo)]); - } else - { - resultCycle.vertices = resultCycle.vertices.concat([graphVertices.find((v: IVertexView) => v.name === nextEdge.vertexOne)]); - colored = colored.concat([graphVertices.find((v: IVertexView) => v.name === nextEdge.vertexOne)]); - } - } - - while (resultCycle.vertices[0] !== resultCycle.vertices[resultCycle.vertices.length - 1]){ - nextEdge = graphEdges.find((e: IEdgeView) => e.vertexOne === resultCycle.vertices[resultCycle.vertices.length - 1].name && e.vertexTwo !== resultCycle.vertices[resultCycle.vertices.length - 2].name && (colored.find((cv: IVertexView) => cv.name === e.vertexTwo) == null) - || e.vertexTwo === resultCycle.vertices[resultCycle.vertices.length - 1].name && e.vertexOne !== resultCycle.vertices[resultCycle.vertices.length - 2].name && (colored.find((cv: IVertexView) => cv.name === e.vertexOne) == null)); - if (nextEdge!=null){ - resultCycle.edges = resultCycle.edges.concat([nextEdge]); - - if (nextEdge.vertexOne === resultCycle.vertices[resultCycle.vertices.length - 1].name){ - resultCycle.vertices = resultCycle.vertices.concat([graphVertices.find((v: IVertexView) => v.name === nextEdge.vertexTwo)]); - colored = colored.concat([graphVertices.find((v: IVertexView) => v.name === nextEdge.vertexTwo)]); - } else - { - resultCycle.vertices = resultCycle.vertices.concat([graphVertices.find((v: IVertexView) => v.name === nextEdge.vertexOne)]); - colored = colored.concat([graphVertices.find((v: IVertexView) => v.name === nextEdge.vertexOne)]); - } - } - } - - return resultCycle; -} - -function findSegments(faces: Cycle[], graphVertices: IVertexView[], graphEdges: IEdgeView[], usedEdges: IEdgeView[], usedVertices: IVertexView[]): Segment[]{ - - var resultSegments: Segment[] = []; - - //Search segments. - graphEdges.filter(nonUsedEdge => !usedEdges.find(e => e == nonUsedEdge)).forEach(nonUsedEdge => { - if (usedVertices.find(v => nonUsedEdge.vertexOne == v.name) && usedVertices.find(v => nonUsedEdge.vertexTwo == v.name)){ - resultSegments.push(new Segment([nonUsedEdge], - [graphVertices.find(v => v.name == nonUsedEdge.vertexOne), - graphVertices.find(v => v.name == nonUsedEdge.vertexTwo)], - graphVertices.find(v => v.name == nonUsedEdge.vertexOne), - graphVertices.find(v => v.name == nonUsedEdge.vertexTwo))); - - } else if (usedVertices.find(v => nonUsedEdge.vertexOne == v.name)){ - resultSegments.push(findWay(graphVertices, graphEdges.filter(edge => !usedEdges.find(e => e == edge)), graphVertices.find(v => v.name == nonUsedEdge.vertexOne), usedVertices)); - - } else if (usedVertices.find(v => nonUsedEdge.vertexTwo == v.name)){ - resultSegments.push(findWay(graphVertices, graphEdges.filter(edge => !usedEdges.find(e => e == edge)), graphVertices.find(v => v.name == nonUsedEdge.vertexTwo), usedVertices)); - } - }); - - //Calculate value of each found segment - resultSegments.forEach(s => s.value = faces.filter( f=> f.vertices.find(v => v.name == s.contactPointOne.name) && f.vertices.find(v => v.name == s.contactPointTwo.name)).length); - - return resultSegments; -} - -function checkPlanarity(graphVertices: IVertexView[], graphEdges: IEdgeView[], zeroCycle: Cycle ) : boolean { - - if(zeroCycle == null){ - return true; - } - if(zeroCycle.vertices.length === 0){ - return true; - } - - var faces: Cycle[] = [zeroCycle, new Cycle("G1", zeroCycle.vertices, zeroCycle.edges)]; - var usedEdges: IEdgeView[] = zeroCycle.edges; - var usedVertices: IVertexView[] = zeroCycle.vertices; - var segments : Segment[] = findSegments(faces, graphVertices, graphEdges, usedEdges, usedVertices); - var counter = 0; - - while (segments.length != 0 && !segments.find(s => s.value == 0) && counter < 100){ - counter++; - segments.sort(function(a, b) { return b.value - a.value; }); - - var minValueSegment = segments.pop(); - var cutFace = faces.splice(faces.findIndex( f => f.vertices.find(v => v.name == minValueSegment.contactPointOne.name) != null && f.vertices.find(v => v.name == minValueSegment.contactPointTwo.name) != null), 1)[0]; - var contactPointOneIndex = cutFace.vertices.findIndex(v => v.name == minValueSegment.contactPointOne.name); - var contactPointTwoIndex = cutFace.vertices.findIndex(v => v.name == minValueSegment.contactPointTwo.name); - - usedVertices = usedVertices.concat(minValueSegment.bodyVertices.slice(1, minValueSegment.bodyVertices.length - 1)); - usedEdges = usedEdges.concat(minValueSegment.bodyEdges.slice()); - - var newVertices1 : IVertexView[]; - var newVertices2 : IVertexView[]; - var newEdges1 : IEdgeView[]; - var newEdges2 : IEdgeView[]; - - if (contactPointOneIndex < contactPointTwoIndex){ - newVertices1 = cutFace.vertices.slice(0, contactPointOneIndex); - newVertices1 = newVertices1.concat(minValueSegment.bodyVertices.slice()); - newVertices1 = newVertices1.concat(cutFace.vertices.slice(contactPointTwoIndex + 1)); - - newEdges1 = cutFace.edges.slice(0, contactPointOneIndex); - newEdges1 = newEdges1.concat(minValueSegment.bodyEdges.slice()); - newEdges1 = newEdges1.concat(cutFace.edges.slice(contactPointTwoIndex)); - - newVertices2 = minValueSegment.bodyVertices.slice(); - newVertices2 = newVertices2.concat(cutFace.vertices.slice(contactPointOneIndex, contactPointTwoIndex).reverse()); - - newEdges2 = minValueSegment.bodyEdges.slice(); - newEdges2 = newEdges2.concat(cutFace.edges.slice(contactPointOneIndex, contactPointTwoIndex).reverse()); - - } else if (contactPointOneIndex > contactPointTwoIndex){ - newVertices1 = cutFace.vertices.slice(0, contactPointTwoIndex); - newVertices1 = newVertices1.concat(minValueSegment.bodyVertices.slice().reverse()); - newVertices1 = newVertices1.concat(cutFace.vertices.slice(contactPointOneIndex + 1)); - - newEdges1 = cutFace.edges.slice(0, contactPointTwoIndex); - newEdges1 = newEdges1.concat(minValueSegment.bodyEdges.slice().reverse()); - newEdges1 = newEdges1.concat(cutFace.edges.slice(contactPointOneIndex)); - - newVertices2 = minValueSegment.bodyVertices.slice().reverse(); - newVertices2 = newVertices2.concat(cutFace.vertices.slice(contactPointTwoIndex, contactPointOneIndex).reverse()); - - newEdges2 = minValueSegment.bodyEdges.slice().reverse(); - newEdges2 = newEdges2.concat(cutFace.edges.slice(contactPointTwoIndex, contactPointOneIndex).reverse()); - - } else if (contactPointOneIndex == contactPointTwoIndex){ - newVertices1 = cutFace.vertices.slice(); - newEdges1 = cutFace.edges.slice(); - newVertices2 = minValueSegment.bodyVertices.slice(); - newEdges2 = minValueSegment.bodyEdges.slice(); - } - - faces.push(new Cycle(cutFace.name + "0", newVertices1.slice(), newEdges1.slice()), new Cycle(cutFace.name + "1", newVertices2.slice(), newEdges2.slice())); - segments = findSegments(faces, graphVertices, graphEdges, usedEdges, usedVertices); - } - - if (segments.length == 0){ - return true; - } else if (segments.find(s => s.value == 0)){ - return false; - } - - return null; -} - function addK5Edges(){ const graph = store.getState().graph; @@ -229,6 +21,50 @@ function addK5Edges(){ }); } +function addBridge(){ + const graph = store.getState().graph; + + var newVertex = graph.vertices.slice(0,1); + newVertex.name = "5"; + graph.vertices.push(newVertex); + + graph.edges.length = 1; + + var newEdge0 = graph.edges[0]; + newEdge0.vertexOne = "0"; + newEdge0.vertexTwo = "1"; + + var newEdge1 = graph.edges.slice(0,1); + newEdge1.vertexOne = "1"; + newEdge1.vertexTwo = "2"; + graph.edges.push(Object.assign({}, newEdge1)); + + var newEdge2 = graph.edges.slice(0,1); + newEdge2.vertexOne = "0"; + newEdge2.vertexTwo = "2"; + graph.edges.push(Object.assign({}, newEdge2)); + + var newEdge3 = graph.edges.slice(0,1); + newEdge3.vertexOne = "1"; + newEdge3.vertexTwo = "3"; + graph.edges.push(Object.assign({}, newEdge3)); + + var newEdge01 = graph.edges.slice(0,1); + newEdge01.vertexOne = "3"; + newEdge01.vertexTwo = "5"; + graph.edges.push(Object.assign({}, newEdge01)); + + var newEdge11 = graph.edges.slice(0,1); + newEdge11.vertexOne = "3"; + newEdge11.vertexTwo = "4"; + graph.edges.push(Object.assign({}, newEdge11)); + + var newEdge21 = graph.edges.slice(0,1); + newEdge21.vertexOne = "5"; + newEdge21.vertexTwo = "4"; + graph.edges.push(Object.assign({}, newEdge21)); +} + function graphСheck(){ const graph = store.getState().graph; @@ -265,11 +101,6 @@ function graphСheck(){ }); } -function mainCheck(){ - var beta_graph = graph_optimize(); - return checkPlanarity(beta_graph.vertices, beta_graph.edges, findCycle(beta_graph.vertices, beta_graph.edges)); -} - class App extends TaskTemplate { public getTaskToolbar() { @@ -284,19 +115,30 @@ class App extends TaskTemplate { public task() { //addK5Edges(); + //addBridge(); graphСheck(); - var planarity_result = mainCheck(); - + var betaGraph = new BetaGraph(store.getState().graph.vertices, store.getState().graph.edges); + var planarityResult = betaGraph.checkPlanarity().toString(); + var devstring = ""; - if (planarity_result == null){ + + /* + var listBetaGraph = betaGraph.splitGraphByBridge(); + + devstring+=betaGraph; + devstring+= "____ После разбиенеия _______"; + listBetaGraph.forEach( g => devstring += g.toString()); + */ + + if (planarityResult == null){ devstring += "Пожалуйста сообщите об этом преподавателю или лаборанту. Результат проверки на планарность = null"; } return () => (
- Ответьте на вопрос:
Данный граф является планарным ?
+ Ответьте на вопрос:

Данный граф является планарным ?
+

{planarityResult}


{devstring}
); diff --git a/src/BetaGraph.tsx b/src/BetaGraph.tsx index b0870f3..cd3ba71 100644 --- a/src/BetaGraph.tsx +++ b/src/BetaGraph.tsx @@ -3,41 +3,305 @@ import { Cycle } from './Cycle'; import { Graph, Vertex, Edge } from 'graphlabs.core.graphs'; import { Segment } from './Segment'; import { store } from 'graphlabs.core.template'; +import { findDOMNode } from 'react-dom'; export class BetaGraph { - vertices: IVertexView[]; - edges: IEdgeView[]; - usedVertices: IVertexView[]; - usedEdges: IEdgeView[]; - faces: Cycle[]; - planarity: Boolean; - segments: Segment[]; + public vertices: IVertexView[] = []; + public edges: IEdgeView[] = []; + + private usedVertices: IVertexView[] = []; + private usedEdges: IEdgeView[] = []; + private faces: Cycle[] = []; + private segments: Segment[] = []; constructor( vertices: IVertexView[], edges: IEdgeView[]){ this.vertices = vertices.slice(); this.edges = edges.slice(); + + if (!this.vertices || !this.edges){ + return null; + } + + this.optimizeGraph(); } - OptimizeGraph() { + public findWay(startPoint: IVertexView, finishPoint: IVertexView[], graphEdges?: IEdgeView[], blockedWay?: Segment): Segment{ + + if (!graphEdges){ + graphEdges = this.edges; + } + + var resultSegment: Segment = new Segment([], [startPoint], startPoint, null); + let blackList: IEdgeView[] = []; - if (!this.vertices || !this.edges){ return null; } - if (this.vertices.length == 0 || this.edges.length == 0){ return false; } + let nameOfBlockedVertex: string = null; + + do { + let nameOfLastVertex = resultSegment.bodyVertices[resultSegment.bodyVertices.length - 1].name; + + if (blockedWay){ + nameOfBlockedVertex = blockedWay.bodyVertices[blockedWay.bodyVertices.findIndex(v => v.name == nameOfLastVertex) + 1].name; + } + + let nextEdge = graphEdges.find( edge => !resultSegment.bodyEdges.find(e => e == edge) + && !blackList.find(e => e == edge) + && (edge.vertexOne == nameOfLastVertex && edge.vertexTwo != nameOfBlockedVertex + || edge.vertexTwo == nameOfLastVertex && edge.vertexOne != nameOfBlockedVertex)); + + if (nextEdge == null){ + if (resultSegment.bodyEdges.length == 0){ + return null; + } + blackList.push(resultSegment.bodyEdges.pop()); + resultSegment.bodyVertices.pop(); + continue; + } + + resultSegment.bodyEdges.push(nextEdge); + + if (nextEdge.vertexOne == nameOfLastVertex){ + resultSegment.bodyVertices.push(this.vertices.find(v => v.name == nextEdge.vertexTwo)); + resultSegment.contactPointTwo = this.vertices.find(v => v.name == nextEdge.vertexTwo); + } else { + resultSegment.bodyVertices.push(this.vertices.find(v => v.name == nextEdge.vertexOne)); + resultSegment.contactPointTwo = this.vertices.find(v => v.name == nextEdge.vertexOne); + } + + } while (!finishPoint.find(v => resultSegment.contactPointTwo.name == v.name)) + return resultSegment + } + + public splitGraphByBridge(): BetaGraph[]{ + + if (this.vertices.length < 6){ + return [this]; + } + + let blockedVertices: IVertexView[] = []; + + this.vertices.slice(1).forEach( vertex => { + let firstWay = this.findWay(this.vertices[0], [vertex]); + if (!this.findWay(this.vertices[0], [vertex], null, firstWay)){ + blockedVertices.push(vertex); + } + }); + + if (blockedVertices.length == 0){ + return [this]; + } + + var newGraph1: BetaGraph = new BetaGraph(this.vertices.filter(v1 => !blockedVertices.find(v2 => v1 == v2)), + this.edges.filter(e => !blockedVertices.find(v2 => e.vertexOne == v2.name) + && !blockedVertices.find(v2 => e.vertexTwo == v2.name))); + + var newGraph2: BetaGraph = new BetaGraph(blockedVertices, + this.edges.filter(e => blockedVertices.find(v2 => e.vertexOne == v2.name) + && blockedVertices.find(v2 => e.vertexTwo == v2.name))); + + return [newGraph1].concat(newGraph2.splitGraphByBridge()); + } + + public checkPlanarity(): boolean { + + let splitedGraph = this.splitGraphByBridge() + if (splitedGraph.length > 1){ + let result: boolean = true; + splitedGraph.forEach( g => result = result && g.checkPlanarity()) + return result; + } + + var zeroCycle = this.findCycle(); + if(zeroCycle == null){ + return true; + } + if(zeroCycle.vertices.length === 0){ + return true; + } + + this.faces = [zeroCycle, new Cycle("G1", zeroCycle.vertices, zeroCycle.edges)]; + this.usedEdges = zeroCycle.edges; + this.usedVertices = zeroCycle.vertices; + + this.findSegments(); + + var counter = 0; + + while (this.segments.length != 0 && !this.segments.find(s => s.value == 0) && counter < 100){ + counter++; + this.segments.sort(function(a, b) { return b.value - a.value; }); + + var minValueSegment = this.segments.pop(); + var cutFace = this.faces.splice(this.faces.findIndex( f => f.vertices.find(v => v.name == minValueSegment.contactPointOne.name) != null + && f.vertices.find(v => v.name == minValueSegment.contactPointTwo.name) != null), 1)[0]; + var contactPointOneIndex = cutFace.vertices.findIndex(v => v.name == minValueSegment.contactPointOne.name); + var contactPointTwoIndex = cutFace.vertices.findIndex(v => v.name == minValueSegment.contactPointTwo.name); + + this.usedVertices = this.usedVertices.concat(minValueSegment.bodyVertices.slice(1, minValueSegment.bodyVertices.length - 1)); + this.usedEdges = this.usedEdges.concat(minValueSegment.bodyEdges.slice()); + + var newVertices1 : IVertexView[]; + var newVertices2 : IVertexView[]; + var newEdges1 : IEdgeView[]; + var newEdges2 : IEdgeView[]; + + if (contactPointOneIndex < contactPointTwoIndex){ + newVertices1 = cutFace.vertices.slice(0, contactPointOneIndex); + newVertices1 = newVertices1.concat(minValueSegment.bodyVertices.slice()); + newVertices1 = newVertices1.concat(cutFace.vertices.slice(contactPointTwoIndex + 1)); + + newEdges1 = cutFace.edges.slice(0, contactPointOneIndex); + newEdges1 = newEdges1.concat(minValueSegment.bodyEdges.slice()); + newEdges1 = newEdges1.concat(cutFace.edges.slice(contactPointTwoIndex)); + + newVertices2 = minValueSegment.bodyVertices.slice(); + newVertices2 = newVertices2.concat(cutFace.vertices.slice(contactPointOneIndex, contactPointTwoIndex).reverse()); + + newEdges2 = minValueSegment.bodyEdges.slice(); + newEdges2 = newEdges2.concat(cutFace.edges.slice(contactPointOneIndex, contactPointTwoIndex).reverse()); + + } else if (contactPointOneIndex > contactPointTwoIndex){ + newVertices1 = cutFace.vertices.slice(0, contactPointTwoIndex); + newVertices1 = newVertices1.concat(minValueSegment.bodyVertices.slice().reverse()); + newVertices1 = newVertices1.concat(cutFace.vertices.slice(contactPointOneIndex + 1)); + + newEdges1 = cutFace.edges.slice(0, contactPointTwoIndex); + newEdges1 = newEdges1.concat(minValueSegment.bodyEdges.slice().reverse()); + newEdges1 = newEdges1.concat(cutFace.edges.slice(contactPointOneIndex)); + + newVertices2 = minValueSegment.bodyVertices.slice().reverse(); + newVertices2 = newVertices2.concat(cutFace.vertices.slice(contactPointTwoIndex, contactPointOneIndex).reverse()); + + newEdges2 = minValueSegment.bodyEdges.slice().reverse(); + newEdges2 = newEdges2.concat(cutFace.edges.slice(contactPointTwoIndex, contactPointOneIndex).reverse()); + + } else if (contactPointOneIndex == contactPointTwoIndex){ + newVertices1 = cutFace.vertices.slice(); + newEdges1 = cutFace.edges.slice(); + newVertices2 = minValueSegment.bodyVertices.slice(); + newEdges2 = minValueSegment.bodyEdges.slice(); + } + + this.faces.push(new Cycle(cutFace.name + "0", newVertices1.slice(), newEdges1.slice()), new Cycle(cutFace.name + "1", newVertices2.slice(), newEdges2.slice())); + this.findSegments(); + } + + if (this.segments.length == 0){ + return true; + } else if (this.segments.find(s => s.value == 0)){ + return false; + } + return null; + } + + public toString(){ + let str: string = "Vertices: "; + this.vertices.forEach(v => str += v.name); + str += "Edges: "; + this.edges.forEach(e => str += e.vertexOne + e.vertexTwo + " "); + return str; + } + + private optimizeGraph() { + this.vertices = this.vertices.filter((v: IVertexView) => this.edges.find((e: IEdgeView) => e.vertexOne == v.name || e.vertexTwo == v.name )); - let num_vertices_deleted: number = 0; - let vertices_mig; + var numVerticesDeleted: number = 0; + var verticesMig; do{ - vertices_mig = this.vertices.filter((v: IVertexView) => this.edges.filter((e: IEdgeView) => e.vertexOne === v.name || e.vertexTwo === v.name).length >= 2 ); - num_vertices_deleted = this.vertices.length - vertices_mig.length; - this.vertices = vertices_mig; + verticesMig = this.vertices.filter((v: IVertexView) => this.edges.filter((e: IEdgeView) => e.vertexOne === v.name || e.vertexTwo === v.name).length >= 2 ); + numVerticesDeleted = this.vertices.length - verticesMig.length; + this.vertices = verticesMig; this.edges = this.edges.filter((e: IEdgeView) => this.vertices.find((v: IVertexView) => v.name === e.vertexOne ) && this.vertices.find((v: IVertexView) => v.name === e.vertexTwo )); - } while(num_vertices_deleted != 0); + } while(numVerticesDeleted != 0); return true; } + + private findCycle(): Cycle { + + if(this.vertices.length === 0){ + return null; + } + + var resultCycle:Cycle = new Cycle("G0", [this.vertices[0]], null); + + let colored:IVertexView[] = []; + + let nextEdge = this.edges.find((e: IEdgeView) => e.vertexOne === resultCycle.vertices[0].name || e.vertexTwo === resultCycle.vertices[0].name); + + if (nextEdge!=null){ + resultCycle.edges = [nextEdge]; + + if (nextEdge.vertexOne === resultCycle.vertices[0].name){ + resultCycle.vertices = resultCycle.vertices.concat([this.vertices.find((v: IVertexView) => v.name === nextEdge.vertexTwo)]); + colored = colored.concat([this.vertices.find((v: IVertexView) => v.name === nextEdge.vertexTwo)]); + } else + { + resultCycle.vertices = resultCycle.vertices.concat([this.vertices.find((v: IVertexView) => v.name === nextEdge.vertexOne)]); + colored = colored.concat([this.vertices.find((v: IVertexView) => v.name === nextEdge.vertexOne)]); + } + } + + while (resultCycle.vertices[0] !== resultCycle.vertices[resultCycle.vertices.length - 1]){ + + nextEdge = this.edges.find((e: IEdgeView) => (e.vertexOne === resultCycle.vertices[resultCycle.vertices.length - 1].name + && e.vertexTwo !== resultCycle.vertices[resultCycle.vertices.length - 2].name + && (colored.find((cv: IVertexView) => cv.name === e.vertexTwo) == null)) + || (e.vertexTwo === resultCycle.vertices[resultCycle.vertices.length - 1].name + && e.vertexOne !== resultCycle.vertices[resultCycle.vertices.length - 2].name + && (colored.find((cv: IVertexView) => cv.name === e.vertexOne) == null))); + + if (nextEdge!=null){ + resultCycle.edges = resultCycle.edges.concat([nextEdge]); + + if (nextEdge.vertexOne === resultCycle.vertices[resultCycle.vertices.length - 1].name){ + resultCycle.vertices = resultCycle.vertices.concat([this.vertices.find((v: IVertexView) => v.name === nextEdge.vertexTwo)]); + colored = colored.concat([this.vertices.find((v: IVertexView) => v.name === nextEdge.vertexTwo)]); + } else + { + resultCycle.vertices = resultCycle.vertices.concat([this.vertices.find((v: IVertexView) => v.name === nextEdge.vertexOne)]); + colored = colored.concat([this.vertices.find((v: IVertexView) => v.name === nextEdge.vertexOne)]); + } + } + } + + return resultCycle; + } + + private findSegments() { + + this.segments.length = 0; + + //Search segments. + this.edges.filter(nonUsedEdge => !this.usedEdges.find(e => e == nonUsedEdge)).forEach(nonUsedEdge => { + if (this.usedVertices.find(v => nonUsedEdge.vertexOne == v.name) && this.usedVertices.find(v => nonUsedEdge.vertexTwo == v.name)){ + this.segments.push(new Segment([nonUsedEdge], + [this.vertices.find(v => v.name == nonUsedEdge.vertexOne), + this.vertices.find(v => v.name == nonUsedEdge.vertexTwo)], + this.vertices.find(v => v.name == nonUsedEdge.vertexOne), + this.vertices.find(v => v.name == nonUsedEdge.vertexTwo))); + + } else if (this.usedVertices.find(v => nonUsedEdge.vertexOne == v.name)){ + this.segments.push(this.findWay(this.vertices.find(v => v.name == nonUsedEdge.vertexOne), + this.usedVertices, + this.edges.filter(edge => !this.usedEdges.find(e => e == edge)))); + + } else if (this.usedVertices.find(v => nonUsedEdge.vertexTwo == v.name)){ + this.segments.push(this.findWay(this.vertices.find(v => v.name == nonUsedEdge.vertexTwo), + this.usedVertices, + this.edges.filter(edge => !this.usedEdges.find(e => e == edge)))); + } + }); + + //Calculate value of each found segment + this.segments.forEach(s => s.value = this.faces.filter( f=> f.vertices.find(v => v.name == s.contactPointOne.name) + && f.vertices.find(v => v.name == s.contactPointTwo.name)).length); + + } + } \ No newline at end of file diff --git a/src/Cycle.tsx b/src/Cycle.tsx index d3d580b..8ff479e 100644 --- a/src/Cycle.tsx +++ b/src/Cycle.tsx @@ -4,9 +4,9 @@ import { IEdgeView, IVertexView } from 'graphlabs.core.template/build/models/gra export class Cycle { - name: string; - vertices: IVertexView[]; - edges: IEdgeView[]; + name: string = null; + vertices: IVertexView[] = []; + edges: IEdgeView[] = []; constructor(name: string, vertices: IVertexView[], edges: IEdgeView[]) { diff --git a/src/Segment.tsx b/src/Segment.tsx index 0bb550e..a45ece6 100644 --- a/src/Segment.tsx +++ b/src/Segment.tsx @@ -4,11 +4,11 @@ import { IEdgeView, IVertexView } from 'graphlabs.core.template/build/models/gra export class Segment { - bodyEdges: IEdgeView[]; - bodyVertices: IVertexView[]; - value: number; - contactPointOne: IVertexView; - contactPointTwo: IVertexView; + bodyEdges: IEdgeView[] = []; + bodyVertices: IVertexView[] = []; + value: number = null; + contactPointOne: IVertexView = null; + contactPointTwo: IVertexView = null; constructor(bodyEdges: IEdgeView[], bodyVertices : IVertexView[], contactPointOne: IVertexView, contactPointTwo: IVertexView) { From b5b8d291fe296b5c21aafa279bb26fd2a067fe0b Mon Sep 17 00:00:00 2001 From: AnastasiiaRazheva Date: Wed, 22 May 2019 23:57:13 +0300 Subject: [PATCH 07/17] build + componentDidMount MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Я перенесла проверку планарности в componentDidMount --- config/env.js | 93 +++++ config/jest/cssTransform.js | 14 + config/jest/fileTransform.js | 31 ++ config/paths.js | 89 +++++ config/webpack.config.js | 605 ++++++++++++++++++++++++++++++ config/webpackDevServer.config.js | 104 +++++ package-lock.json | 88 +---- package.json | 106 +++++- scripts/build.js | 192 ++++++++++ scripts/start.js | 132 +++++++ scripts/test.js | 60 +++ src/App.tsx | 41 +- src/react-app-env.d.ts | 65 +++- 13 files changed, 1508 insertions(+), 112 deletions(-) create mode 100644 config/env.js create mode 100644 config/jest/cssTransform.js create mode 100644 config/jest/fileTransform.js create mode 100644 config/paths.js create mode 100644 config/webpack.config.js create mode 100644 config/webpackDevServer.config.js create mode 100644 scripts/build.js create mode 100644 scripts/start.js create mode 100644 scripts/test.js diff --git a/config/env.js b/config/env.js new file mode 100644 index 0000000..b0344c5 --- /dev/null +++ b/config/env.js @@ -0,0 +1,93 @@ +'use strict'; + +const fs = require('fs'); +const path = require('path'); +const paths = require('./paths'); + +// Make sure that including paths.js after env.js will read .env variables. +delete require.cache[require.resolve('./paths')]; + +const NODE_ENV = process.env.NODE_ENV; +if (!NODE_ENV) { + throw new Error( + 'The NODE_ENV environment variable is required but was not specified.' + ); +} + +// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use +var dotenvFiles = [ + `${paths.dotenv}.${NODE_ENV}.local`, + `${paths.dotenv}.${NODE_ENV}`, + // Don't include `.env.local` for `test` environment + // since normally you expect tests to produce the same + // results for everyone + NODE_ENV !== 'test' && `${paths.dotenv}.local`, + paths.dotenv, +].filter(Boolean); + +// Load environment variables from .env* files. Suppress warnings using silent +// if this file is missing. dotenv will never modify any environment variables +// that have already been set. Variable expansion is supported in .env files. +// https://github.com/motdotla/dotenv +// https://github.com/motdotla/dotenv-expand +dotenvFiles.forEach(dotenvFile => { + if (fs.existsSync(dotenvFile)) { + require('dotenv-expand')( + require('dotenv').config({ + path: dotenvFile, + }) + ); + } +}); + +// We support resolving modules according to `NODE_PATH`. +// This lets you use absolute paths in imports inside large monorepos: +// https://github.com/facebook/create-react-app/issues/253. +// It works similar to `NODE_PATH` in Node itself: +// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders +// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored. +// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims. +// https://github.com/facebook/create-react-app/issues/1023#issuecomment-265344421 +// We also resolve them to make sure all tools using them work consistently. +const appDirectory = fs.realpathSync(process.cwd()); +process.env.NODE_PATH = (process.env.NODE_PATH || '') + .split(path.delimiter) + .filter(folder => folder && !path.isAbsolute(folder)) + .map(folder => path.resolve(appDirectory, folder)) + .join(path.delimiter); + +// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be +// injected into the application via DefinePlugin in Webpack configuration. +const REACT_APP = /^REACT_APP_/i; + +function getClientEnvironment(publicUrl) { + const raw = Object.keys(process.env) + .filter(key => REACT_APP.test(key)) + .reduce( + (env, key) => { + env[key] = process.env[key]; + return env; + }, + { + // Useful for determining whether we’re running in production mode. + // Most importantly, it switches React into the correct mode. + NODE_ENV: process.env.NODE_ENV || 'development', + // Useful for resolving the correct path to static assets in `public`. + // For example, . + // This should only be used as an escape hatch. Normally you would put + // images into the `src` and `import` them in code to get their paths. + PUBLIC_URL: publicUrl, + } + ); + // Stringify all values so we can feed into Webpack DefinePlugin + const stringified = { + 'process.env': Object.keys(raw).reduce((env, key) => { + env[key] = JSON.stringify(raw[key]); + return env; + }, {}), + }; + + return { raw, stringified }; +} + +module.exports = getClientEnvironment; diff --git a/config/jest/cssTransform.js b/config/jest/cssTransform.js new file mode 100644 index 0000000..8f65114 --- /dev/null +++ b/config/jest/cssTransform.js @@ -0,0 +1,14 @@ +'use strict'; + +// This is a custom Jest transformer turning style imports into empty objects. +// http://facebook.github.io/jest/docs/en/webpack.html + +module.exports = { + process() { + return 'module.exports = {};'; + }, + getCacheKey() { + // The output is always the same. + return 'cssTransform'; + }, +}; diff --git a/config/jest/fileTransform.js b/config/jest/fileTransform.js new file mode 100644 index 0000000..4ed6bdb --- /dev/null +++ b/config/jest/fileTransform.js @@ -0,0 +1,31 @@ +'use strict'; + +const path = require('path'); + +// This is a custom Jest transformer turning file imports into filenames. +// http://facebook.github.io/jest/docs/en/webpack.html + +module.exports = { + process(src, filename) { + const assetFilename = JSON.stringify(path.basename(filename)); + + if (filename.match(/\.svg$/)) { + return `const React = require('react'); + module.exports = { + __esModule: true, + default: ${assetFilename}, + ReactComponent: React.forwardRef((props, ref) => ({ + $$typeof: Symbol.for('react.element'), + type: 'svg', + ref: ref, + key: null, + props: Object.assign({}, props, { + children: ${assetFilename} + }) + })), + };`; + } + + return `module.exports = ${assetFilename};`; + }, +}; diff --git a/config/paths.js b/config/paths.js new file mode 100644 index 0000000..c24b4dd --- /dev/null +++ b/config/paths.js @@ -0,0 +1,89 @@ +'use strict'; + +const path = require('path'); +const fs = require('fs'); +const url = require('url'); + +// Make sure any symlinks in the project folder are resolved: +// https://github.com/facebook/create-react-app/issues/637 +const appDirectory = fs.realpathSync(process.cwd()); +const resolveApp = relativePath => path.resolve(appDirectory, relativePath); + +const envPublicUrl = process.env.PUBLIC_URL; + +function ensureSlash(inputPath, needsSlash) { + const hasSlash = inputPath.endsWith('/'); + if (hasSlash && !needsSlash) { + return inputPath.substr(0, inputPath.length - 1); + } else if (!hasSlash && needsSlash) { + return `${inputPath}/`; + } else { + return inputPath; + } +} + +const getPublicUrl = appPackageJson => + envPublicUrl || require(appPackageJson).homepage; + +// We use `PUBLIC_URL` environment variable or "homepage" field to infer +// "public path" at which the app is served. +// Webpack needs to know it to put the right