Skip to content

Commit

Permalink
update epoxrt functions
Browse files Browse the repository at this point in the history
  • Loading branch information
LdDl committed Apr 30, 2021
1 parent 35f5064 commit 49ffb55
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 112 deletions.
3 changes: 3 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ New ideas, thought about needed features will be store in this file.
* Separate benchmarks to BENCHMARK.md **Done**
* Better CSV format or another format (JSON / binary). **W.I.P. Splitting single file to multiple**

### WIP
* Separate export functions

### Planned
* Better heuristics for calculationg importance of each vertex.
* Max-cost path finder.
Expand Down
2 changes: 1 addition & 1 deletion contraction.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (graph *Graph) markNeighbors(inEdges, outEdges []incidentEdge) {

// ContractionPath
//
// ViaVertex - ID of vertex through which the contraction exists
// ViaVertex - ID of vertex through which the shortcut exists
// Cost - summary cost of path between two vertices
//
type ContractionPath struct {
Expand Down
142 changes: 85 additions & 57 deletions export.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,88 +6,70 @@ import (
"os"
"strconv"
"strings"

"github.com/pkg/errors"
)

// ExportToFile Exports graph to file of CSV-format
// Header of edges CSV-file:
// from_vertex_id - int64, ID of source vertex
// to_vertex_id - int64, ID of target vertex
// f_internal - int64, Internal ID of source vertex
// t_internal - int64, Internal ID of target vertex
// weight - float64, Weight of an edge
// Header of vertices CSV-file:
// vertex_id - int64, ID of vertex
// internal_id - int64, Internal ID of vertex
// order_pos - int, Position of vertex in hierarchies (evaluted by library)
// importance - int, Importance of vertex in graph (evaluted by library)
// Header of contractios CSV-file:
// Header of shortcuts CSV-file:
// from_vertex_id - int64, ID of source vertex
// to_vertex_id - int64, ID of arget vertex
// f_internal - int64, Internal ID of source vertex
// t_internal - int64, Internal ID of target vertex
// weight - float64, Weight of an edge
// via_vertex_id - int64, ID of vertex through which the contraction exists
// v_internal - int64, Internal ID of vertex through which the contraction exists
// to_vertex_id - int64, ID of target vertex
// weight - float64, Weight of an shortcut
// via_vertex_id - int64, ID of vertex through which the shortcut exists
func (graph *Graph) ExportToFile(fname string) error {

fnamePart := strings.Split(fname, ".csv") // to guarantee proper filename and its extension
file, err := os.Create(fnamePart[0] + ".csv")
if err != nil {
return err
}
defer file.Close()

writer := csv.NewWriter(file)
defer writer.Flush()
writer.Comma = ';'
err = writer.Write([]string{"from_vertex_id", "to_vertex_id", "f_internal", "t_internal", "weight"})
err := graph.ExportEdgesToFile(fnamePart[0] + ".csv")
if err != nil {
return err
return errors.Wrap(err, "Can't export edges")
}

fileVertices, err := os.Create(fnamePart[0] + "_vertices.csv")
// Write reference information about vertices
err = graph.ExportVerticesToFile(fnamePart[0] + "_vertices.csv")
if err != nil {
return err
return errors.Wrap(err, "Can't export shortcuts")
}
defer fileVertices.Close()

writerVertices := csv.NewWriter(fileVertices)
defer writerVertices.Flush()
writerVertices.Comma = ';'
err = writerVertices.Write([]string{"vertex_id", "internal_id", "order_pos", "importance"})
// Write reference information about contractions
err = graph.ExportShortcutsToFile(fnamePart[0] + "_shortcuts.csv")
if err != nil {
return err
return errors.Wrap(err, "Can't export shortcuts")
}

fileContractions, err := os.Create(fnamePart[0] + "_shortcuts.csv")
return nil
}

// ExportVerticesToFile Exports edges information to CSV-file with header:
// from_vertex_id - int64, ID of source vertex
// to_vertex_id - int64, ID of target vertex
// weight - float64, Weight of an edge
func (graph *Graph) ExportEdgesToFile(fname string) error {
file, err := os.Create(fname)
if err != nil {
return err
return errors.Wrap(err, "Can't create edges file")
}
defer fileContractions.Close()
defer file.Close()

writerContractions := csv.NewWriter(fileContractions)
defer writerContractions.Flush()
writerContractions.Comma = ';'
err = writerContractions.Write([]string{"from_vertex_id", "to_vertex_id", "f_internal", "t_internal", "weight", "via_vertex_id", "v_internal"})
writer := csv.NewWriter(file)
defer writer.Flush()
writer.Comma = ';'
err = writer.Write([]string{"from_vertex_id", "to_vertex_id", "weight"})
if err != nil {
return err
return errors.Wrap(err, "Can't write header to edges file")
}

for i := 0; i < len(graph.Vertices); i++ {
currentVertexExternal := graph.Vertices[i].Label
currentVertexInternal := graph.Vertices[i].vertexNum

// Write reference information about vertex
err = writerVertices.Write([]string{
fmt.Sprintf("%d", currentVertexExternal),
fmt.Sprintf("%d", currentVertexInternal),
fmt.Sprintf("%d", graph.Vertices[i].orderPos),
fmt.Sprintf("%d", graph.Vertices[i].importance),
})
if err != nil {
return err
}

// Write reference information about "outcoming" adjacent vertices
// Why don't write info about "incoming" adjacent vertices also? Because all edges will be covered due the loop iteration mechanism
outcomingNeighbors := graph.Vertices[i].outIncidentEdges
Expand All @@ -99,18 +81,67 @@ func (graph *Graph) ExportToFile(fname string) error {
err = writer.Write([]string{
fmt.Sprintf("%d", currentVertexExternal),
fmt.Sprintf("%d", toVertexExternal),
fmt.Sprintf("%d", currentVertexInternal),
fmt.Sprintf("%d", toVertexInternal),
strconv.FormatFloat(cost, 'f', -1, 64),
})
if err != nil {
return err
return errors.Wrap(err, "Can't write edge information")
}
}
}
}

// Write reference information about contractions
return nil
}

// ExportVerticesToFile Exports vertices information to CSV-file with header:
// vertex_id - int64, ID of vertex
// order_pos - int, Position of vertex in hierarchies (evaluted by library)
// importance - int, Importance of vertex in graph (evaluted by library)
func (graph *Graph) ExportVerticesToFile(fname string) error {
fileVertices, err := os.Create(fname)
if err != nil {
return errors.Wrap(err, "Can't create vertices file")
}
defer fileVertices.Close()
writerVertices := csv.NewWriter(fileVertices)
defer writerVertices.Flush()
writerVertices.Comma = ';'
err = writerVertices.Write([]string{"vertex_id", "order_pos", "importance"})
if err != nil {
return errors.Wrap(err, "Can't write header to vertices file")
}
for i := 0; i < len(graph.Vertices); i++ {
currentVertexExternal := graph.Vertices[i].Label
err = writerVertices.Write([]string{
fmt.Sprintf("%d", currentVertexExternal),
fmt.Sprintf("%d", graph.Vertices[i].orderPos),
fmt.Sprintf("%d", graph.Vertices[i].importance),
})
if err != nil {
return errors.Wrap(err, "Can't write vertex information")
}
}
return nil
}

// ExportShortcutsToFile Exports shortcuts information to CSV-file with header:
// from_vertex_id - int64, ID of source vertex
// to_vertex_id - int64, ID of target vertex
// weight - float64, Weight of an shortcut
// via_vertex_id - int64, ID of vertex through which the shortcut exists
func (graph *Graph) ExportShortcutsToFile(fname string) error {
fileContractions, err := os.Create(fname)
if err != nil {
return errors.Wrap(err, "Can't create shortcuts file")
}
defer fileContractions.Close()
writerContractions := csv.NewWriter(fileContractions)
defer writerContractions.Flush()
writerContractions.Comma = ';'
err = writerContractions.Write([]string{"from_vertex_id", "to_vertex_id", "weight", "via_vertex_id"})
if err != nil {
return errors.Wrap(err, "Can't write header to shortucts file")
}
for sourceVertexInternal, to := range graph.shortcuts {
sourceVertexExternal := graph.Vertices[sourceVertexInternal].Label
for targetVertexInternal, viaNodeInternal := range to {
Expand All @@ -119,16 +150,13 @@ func (graph *Graph) ExportToFile(fname string) error {
err = writerContractions.Write([]string{
fmt.Sprintf("%d", sourceVertexExternal),
fmt.Sprintf("%d", targetVertexExternal),
fmt.Sprintf("%d", sourceVertexInternal),
fmt.Sprintf("%d", targetVertexInternal),
strconv.FormatFloat(viaNodeInternal.Cost, 'f', -1, 64),
fmt.Sprintf("%d", viaNodeExternal),
fmt.Sprintf("%d", viaNodeInternal.ViaVertex),
})
if err != nil {
return err
return errors.Wrap(err, "Can't write shortcut information")
}
}
}
return err
return nil
}
27 changes: 27 additions & 0 deletions graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,33 @@ func (graph *Graph) AddEdge(from, to int64, weight float64) error {
return nil
}

// AddShortcut Adds new shortcut between two vertices
//
// from User's definied ID of first vertex of shortcut
// to User's definied ID of last vertex of shortcut
// weight User's definied weight of shortcut
//
func (graph *Graph) AddShortcut(from, to, via int64, weight float64) error {
if graph.frozen {
return ErrGraphIsFrozen
}
fromInternal := graph.mapping[from]
toInternal := graph.mapping[to]
viaInternal := graph.mapping[via]
if _, ok := graph.shortcuts[fromInternal]; !ok {
graph.shortcuts[fromInternal] = make(map[int64]*ContractionPath)
graph.shortcuts[fromInternal][toInternal] = &ContractionPath{
ViaVertex: viaInternal,
Cost: weight,
}
}
graph.shortcuts[fromInternal][toInternal] = &ContractionPath{
ViaVertex: viaInternal,
Cost: weight,
}
return nil
}

// AddTurnRestriction Adds new turn restriction between two vertices via some other vertex
//
// from User's definied ID of source vertex
Expand Down
74 changes: 20 additions & 54 deletions import.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,16 @@ import (
// Header of CSV-file containing information about edges:
// from_vertex_id - int64, ID of source vertex
// to_vertex_id - int64, ID of arget vertex
// f_internal - int64, Internal ID of source vertex
// t_internal - int64, Internal ID of target vertex
// weight - float64, Weight of an edge
// Header of CSV-file containing information about vertices:
// vertex_id - int64, ID of vertex
// internal_id - int64, internal ID of target vertex
// order_pos - int, Position of vertex in hierarchies (evaluted by library)
// importance - int, Importance of vertex in graph (evaluted by library)
// Header of CSV-file containing information about contractios between vertices:
// Header of CSV-file containing information about shortcuts between vertices:
// from_vertex_id - int64, ID of source vertex
// to_vertex_id - int64, ID of arget vertex
// f_internal - int64, Internal ID of source vertex
// t_internal - int64, Internal ID of target vertex
// weight - float64, Weight of an edge
// via_vertex_id - int64, ID of vertex through which the contraction exists
// v_internal - int64, Internal ID of vertex through which the contraction exists
// to_vertex_id - int64, ID of target vertex
// weight - float64, Weight of an shortcut
// via_vertex_id - int64, ID of vertex through which the shortcut exists
func ImportFromFile(edgesFname, verticesFname, contractionsFname string) (*Graph, error) {
// Read edges first
file, err := os.Open(edgesFname)
Expand Down Expand Up @@ -62,27 +56,18 @@ func ImportFromFile(edgesFname, verticesFname, contractionsFname string) (*Graph
return nil, err
}

sourceInternal, err := strconv.ParseInt(record[2], 10, 64)
if err != nil {
return nil, err
}
targetInternal, err := strconv.ParseInt(record[3], 10, 64)
weight, err := strconv.ParseFloat(record[2], 64)
if err != nil {
return nil, err
}

weight, err := strconv.ParseFloat(record[4], 64)
err = graph.CreateVertex(sourceExternal)
if err != nil {
return nil, err
return nil, errors.Wrap(err, fmt.Sprintf("Can't add source vertex with external_ID = '%d'", sourceExternal))
}

err = graph.AddVertex(sourceExternal, sourceInternal)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("Can't add source vertex with external_ID = '%d' and internal_ID = '%d'", sourceExternal, sourceInternal))
}
err = graph.AddVertex(targetExternal, targetInternal)
err = graph.CreateVertex(targetExternal)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("Can't add target vertex with external_ID = '%d' and internal_ID = '%d'", targetExternal, targetInternal))
return nil, errors.Wrap(err, fmt.Sprintf("Can't add target vertex with external_ID = '%d'", targetExternal))
}

err = graph.AddEdge(sourceExternal, targetExternal, weight)
Expand Down Expand Up @@ -115,21 +100,18 @@ func ImportFromFile(edgesFname, verticesFname, contractionsFname string) (*Graph
if err != nil {
return nil, err
}
vertexInternal, err := strconv.ParseInt(record[1], 10, 64)
if err != nil {
return nil, err
}
vertexOrderPos, err := strconv.Atoi(record[2])
vertexOrderPos, err := strconv.Atoi(record[1])
if err != nil {
return nil, err
}
vertexImportance, err := strconv.Atoi(record[3])
vertexImportance, err := strconv.Atoi(record[2])
if err != nil {
return nil, err
}

if graph.Vertices[vertexInternal].Label != vertexExternal {
return nil, fmt.Errorf("Vertex with Label = %d has wrong reference information. Incoming label info is '%d'", graph.Vertices[vertexInternal].Label, vertexExternal)
vertexInternal, vertexFound := graph.FindVertex(vertexExternal)
if !vertexFound {
return nil, fmt.Errorf("Vertex with Label = %d is not found in graph", vertexExternal)
}
graph.Vertices[vertexInternal].SetOrderPos(vertexOrderPos)
graph.Vertices[vertexInternal].SetImportance(vertexImportance)
Expand Down Expand Up @@ -162,39 +144,23 @@ func ImportFromFile(edgesFname, verticesFname, contractionsFname string) (*Graph
return nil, err
}

sourceInternal, err := strconv.ParseInt(record[2], 10, 64)
weight, err := strconv.ParseFloat(record[2], 64)
if err != nil {
return nil, err
}
targetInternal, err := strconv.ParseInt(record[3], 10, 64)
contractionExternal, err := strconv.ParseInt(record[3], 10, 64)
if err != nil {
return nil, err
}

weight, err := strconv.ParseFloat(record[4], 64)
err = graph.AddEdge(sourceExternal, targetExternal, weight)
if err != nil {
return nil, err
return nil, errors.Wrap(err, fmt.Sprintf("Can't add shortcut with source_internal_ID = '%d' and target_internal_ID = '%d'", sourceExternal, targetExternal))
}

contractionInternal, err := strconv.ParseInt(record[6], 10, 64)
err = graph.AddShortcut(sourceExternal, targetExternal, contractionExternal, weight)
if err != nil {
return nil, err
}

err = graph.AddEdge(sourceExternal, targetExternal, weight)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("Can't add edge with source_internal_ID = '%d' and target_internal_ID = '%d'", sourceExternal, targetExternal))
}
if _, ok := graph.shortcuts[sourceInternal]; !ok {
graph.shortcuts[sourceInternal] = make(map[int64]*ContractionPath)
graph.shortcuts[sourceInternal][targetInternal] = &ContractionPath{
ViaVertex: contractionInternal,
Cost: weight,
}
}
graph.shortcuts[sourceInternal][targetInternal] = &ContractionPath{
ViaVertex: contractionInternal,
Cost: weight,
return nil, errors.Wrap(err, fmt.Sprintf("Can't add shortcut with source_internal_ID = '%d' and target_internal_ID = '%d' to internal map", sourceExternal, targetExternal))
}
}
return &graph, nil
Expand Down

0 comments on commit 49ffb55

Please sign in to comment.