graph

package
v2.1.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 19, 2024 License: BSD-3-Clause Imports: 1 Imported by: 0

Documentation

Overview

Package graph provides graph implementation

Interface methods GetNodes, Add, AddBidirectional are the ways to interact with graph data structure. Node, Edge structures are also available with metadata for more advanced scenarios The Examples, file example_itinerary_test.go, example_connected_components_test.go are implementations of graph use cases to illustrate available features

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Graph

type Graph[T comparable] interface {
	// GetNodes returns map of all nodes in the graph
	GetNodes() set.Set[T]

	// Add relation from source to target node
	Add(T, T)

	// Add relation from source to target node
	AddNode(T)

	// Add bidirectional relation between node1 and node2
	AddBidirectional(T, T)

	// Adjacent nodes from a source
	Adjacencies(T) map[T]bool // not using Set to allow range iteration
}
Example (Itinerary)

This is a problem where we need to find the itinerary using the tickets e.g. tickets [A, B] [B, C] [B,D] [C,B] itinerary A->B->C->B->D using all tickets Note that if we had picked A->B->D we would not be able to use all tickets, so not the right path Since we need to keep track of all edges we visited, metadata support on the edge can be used There could be multiple tickets available for the same source, dest pair. So we can keep track of "available edges" in the metadata

package main

import (
	"fmt"
	"sort"

	"github.com/qulia/go-qulia/v2/lib/graph"
)

// This is a problem where we need to find the itinerary using the tickets
// e.g. tickets [A, B] [B, C] [B,D] [C,B] itinerary A->B->C->B->D using all tickets
// Note that if we had picked A->B->D we would not be able to use all tickets, so not the right path
// Since we need to keep track of all edges we visited, metadata support on the edge can be used
// There could be multiple tickets available for the same source, dest pair. So we can keep track of
// "available edges" in the metadata
func main() {
	ticketsInputs := [][]ticket{
		{{"A", "B"}, {"B", "C"}, {"B", "D"}, {"C", "B"}},
		{{"A", "B"}, {"A", "C"}, {"C", "A"}},
		// Note there are two tickets D,B
		{{"E", "F"}, {"D", "B"}, {"B", "C"}, {"C", "B"}, {"B", "E"}, {"D", "B"}, {"F", "D"}, {"D", "C"}, {"B", "D"}, {"C", "D"}},
	}

	for _, input := range ticketsInputs {
		fmt.Printf("%v\n", testWithTickets(input))
	}

}

func testWithTickets(tickets []ticket) []string {
	// Create graph with source, dest in tickets
	cGraph := graph.NewGraph[string]()
	ticketCount := map[ticket]int{}
	for _, ticket := range tickets {
		ticketCount[ticket]++
		cGraph.Add(ticket.src, ticket.dst)
	}

	var itinerary []string

	// sort nodes to get lexical order in result
	cities := cGraph.GetNodes().ToSlice()
	sort.Strings(cities)
	n := len(tickets)
	for _, c := range cities {
		itinerary = append(itinerary, c)
		if visitAll(c, cGraph, 0, n, ticketCount, &itinerary) {
			break
		} else {
			itinerary = itinerary[:len(itinerary)-1]
		}
	}

	return itinerary
}

func visitAll(c string, g graph.Graph[string], t, n int, ticketCount map[ticket]int, itinerary *[]string) bool {
	if t == n {
		return true
	}

	// sort targets to get lexical order in result
	var ds []string
	for n := range g.Adjacencies(c) {
		ds = append(ds, n)
	}
	sort.Strings(ds)

	for _, d := range ds {
		tc := ticket{c, d}
		if ticketCount[tc] > 0 {
			ticketCount[tc]--
			*itinerary = append(*itinerary, d)
			if visitAll(d, g, t+1, n, ticketCount, itinerary) {
				return true
			} else {
				// backtrack so it can be chosen again
				ticketCount[tc]++
				*itinerary = (*itinerary)[:len(*itinerary)-1]
			}
		}
	}

	return false
}

type ticket struct {
	src, dst string
}
Output:

[A B C B D]
[A C A B]
[B C B D B E F D C D B]

func NewGraph

func NewGraph[T comparable]() Graph[T]

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL