github.com/LdDl/ch@v1.7.8/import.go (about)

     1  package ch
     2  
     3  import (
     4  	"encoding/csv"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  	"strconv"
     9  
    10  	"github.com/pkg/errors"
    11  )
    12  
    13  // ImportFromFile Imports graph (prepared by ExportToFile(fname string) function) from file of CSV-format
    14  // Header of CSV-file containing information about edges:
    15  // 		from_vertex_id - int64, ID of source vertex
    16  // 		to_vertex_id - int64, ID of arget vertex
    17  // 		weight - float64, Weight of an edge
    18  // Header of CSV-file containing information about vertices:
    19  // 		vertex_id - int64, ID of vertex
    20  // 		order_pos - int, Position of vertex in hierarchies (evaluted by library)
    21  // 		importance - int, Importance of vertex in graph (evaluted by library)
    22  // Header of CSV-file containing information about shortcuts between vertices:
    23  // 		from_vertex_id - int64, ID of source vertex
    24  // 		to_vertex_id - int64, ID of target vertex
    25  // 		weight - float64, Weight of an shortcut
    26  // 		via_vertex_id - int64, ID of vertex through which the shortcut exists
    27  func ImportFromFile(edgesFname, verticesFname, contractionsFname string) (*Graph, error) {
    28  	// Read edges first
    29  	file, err := os.Open(edgesFname)
    30  	if err != nil {
    31  		return nil, err
    32  	}
    33  	defer file.Close()
    34  	reader := csv.NewReader(file)
    35  	reader.Comma = ';'
    36  
    37  	graph := Graph{}
    38  
    39  	// Fill graph with edges informations
    40  	// Skip header of CSV-file
    41  	_, err = reader.Read()
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  	// Read file line by line
    46  	for {
    47  		record, err := reader.Read()
    48  		if err == io.EOF {
    49  			break
    50  		}
    51  		sourceExternal, err := strconv.ParseInt(record[0], 10, 64)
    52  		if err != nil {
    53  			return nil, err
    54  		}
    55  		targetExternal, err := strconv.ParseInt(record[1], 10, 64)
    56  		if err != nil {
    57  			return nil, err
    58  		}
    59  
    60  		weight, err := strconv.ParseFloat(record[2], 64)
    61  		if err != nil {
    62  			return nil, err
    63  		}
    64  
    65  		err = graph.CreateVertex(sourceExternal)
    66  		if err != nil {
    67  			return nil, errors.Wrap(err, fmt.Sprintf("Can't add source vertex with external_ID = '%d'", sourceExternal))
    68  		}
    69  		err = graph.CreateVertex(targetExternal)
    70  		if err != nil {
    71  			return nil, errors.Wrap(err, fmt.Sprintf("Can't add target vertex with external_ID = '%d'", targetExternal))
    72  		}
    73  
    74  		err = graph.AddEdge(sourceExternal, targetExternal, weight)
    75  		if err != nil {
    76  			return nil, errors.Wrap(err, fmt.Sprintf("Can't add edge with source_internal_ID = '%d' and target_internal_ID = '%d'", sourceExternal, targetExternal))
    77  		}
    78  	}
    79  
    80  	// Read vertices
    81  	fileVertices, err := os.Open(verticesFname)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  	defer fileVertices.Close()
    86  	readerVertices := csv.NewReader(fileVertices)
    87  	readerVertices.Comma = ';'
    88  
    89  	// Skip header of CSV-file
    90  	_, err = readerVertices.Read()
    91  	if err != nil {
    92  		return nil, err
    93  	}
    94  	// Read file line by line
    95  	for {
    96  		record, err := readerVertices.Read()
    97  		if err == io.EOF {
    98  			break
    99  		}
   100  
   101  		vertexExternal, err := strconv.ParseInt(record[0], 10, 64)
   102  		if err != nil {
   103  			return nil, err
   104  		}
   105  		vertexOrderPos, err := strconv.ParseInt(record[1], 10, 64)
   106  		if err != nil {
   107  			return nil, err
   108  		}
   109  		vertexImportance, err := strconv.Atoi(record[2])
   110  		if err != nil {
   111  			return nil, err
   112  		}
   113  
   114  		vertexInternal, vertexFound := graph.FindVertex(vertexExternal)
   115  		if !vertexFound {
   116  			return nil, fmt.Errorf("Vertex with Label = %d is not found in graph", vertexExternal)
   117  		}
   118  		graph.Vertices[vertexInternal].SetOrderPos(vertexOrderPos)
   119  		graph.Vertices[vertexInternal].SetImportance(vertexImportance)
   120  	}
   121  
   122  	// Read contractions
   123  	fileShortcuts, err := os.Open(contractionsFname)
   124  	if err != nil {
   125  		return nil, err
   126  	}
   127  	defer fileShortcuts.Close()
   128  	readerShortcuts := csv.NewReader(fileShortcuts)
   129  	readerShortcuts.Comma = ';'
   130  	// Skip header of CSV-file
   131  	_, err = readerShortcuts.Read()
   132  	if err != nil {
   133  		return nil, err
   134  	}
   135  	// Read file line by line
   136  	for {
   137  		record, err := readerShortcuts.Read()
   138  		if err == io.EOF {
   139  			break
   140  		}
   141  		sourceExternal, err := strconv.ParseInt(record[0], 10, 64)
   142  		if err != nil {
   143  			return nil, err
   144  		}
   145  		targetExternal, err := strconv.ParseInt(record[1], 10, 64)
   146  		if err != nil {
   147  			return nil, err
   148  		}
   149  
   150  		weight, err := strconv.ParseFloat(record[2], 64)
   151  		if err != nil {
   152  			return nil, err
   153  		}
   154  		contractionExternal, err := strconv.ParseInt(record[3], 10, 64)
   155  		if err != nil {
   156  			return nil, err
   157  		}
   158  
   159  		err = graph.AddEdge(sourceExternal, targetExternal, weight)
   160  		if err != nil {
   161  			return nil, errors.Wrap(err, fmt.Sprintf("Can't add shortcut with source_internal_ID = '%d' and target_internal_ID = '%d'", sourceExternal, targetExternal))
   162  		}
   163  
   164  		err = graph.AddShortcut(sourceExternal, targetExternal, contractionExternal, weight)
   165  		if err != nil {
   166  			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))
   167  		}
   168  	}
   169  	return &graph, nil
   170  }
   171  
   172  // ImportRestrictionsFromFile Imports turn restrictions from file of CSV-format into graph
   173  //
   174  // Header of CSV-file:
   175  // from_vertex_id;via_vertex_id;to_vertex_id;
   176  // int;int;int
   177  //
   178  func (graph *Graph) ImportRestrictionsFromFile(fname string) error {
   179  	file, err := os.Open(fname)
   180  	if err != nil {
   181  		return err
   182  	}
   183  	reader := csv.NewReader(file)
   184  	reader.Comma = ';'
   185  
   186  	// skip header
   187  	_, err = reader.Read()
   188  	if err != nil {
   189  		return err
   190  	}
   191  	// read lines
   192  	for {
   193  		record, err := reader.Read()
   194  		if err == io.EOF {
   195  			break
   196  		}
   197  		sourceExternal, err := strconv.ParseInt(record[0], 10, 64)
   198  		if err != nil {
   199  			return err
   200  		}
   201  		viaExternal, err := strconv.ParseInt(record[1], 10, 64)
   202  		if err != nil {
   203  			return err
   204  		}
   205  		targetExternal, err := strconv.ParseInt(record[2], 10, 64)
   206  		if err != nil {
   207  			return err
   208  		}
   209  
   210  		err = graph.AddTurnRestriction(sourceExternal, viaExternal, targetExternal)
   211  		if err != nil {
   212  			return errors.Wrap(err, fmt.Sprintf("Can't add restriction between source_external_ID = '%d' and target_external_ID = '%d' via via_external_id = '%d'", sourceExternal, targetExternal, viaExternal))
   213  		}
   214  	}
   215  	return nil
   216  }