goneat

The GOLang implementation of NeuroEvolution of Augmented Topologies (NEAT) method to evolve and train Artificial Neural Networks without error back propagation

https://github.com/yaricom/goneat

Science Score: 67.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
    Found CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
    Found 3 DOI reference(s) in README
  • Academic publication links
    Links to: zenodo.org
  • Committers with academic emails
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (8.7%) to scientific vocabulary

Keywords

artificial-neural-networks augmenting-topologies neat neural-network neuroevolution reinforcement-learning reinforcement-learning-algorithms unsupervised-learning unsupervised-machine-learning
Last synced: 7 months ago · JSON representation ·

Repository

The GOLang implementation of NeuroEvolution of Augmented Topologies (NEAT) method to evolve and train Artificial Neural Networks without error back propagation

Basic Info
  • Host: GitHub
  • Owner: yaricom
  • License: mit
  • Language: Go
  • Default Branch: master
  • Homepage:
  • Size: 3.54 MB
Statistics
  • Stars: 78
  • Watchers: 5
  • Forks: 18
  • Open Issues: 10
  • Releases: 19
Topics
artificial-neural-networks augmenting-topologies neat neural-network neuroevolution reinforcement-learning reinforcement-learning-algorithms unsupervised-learning unsupervised-machine-learning
Created over 8 years ago · Last pushed over 1 year ago
Metadata Files
Readme Changelog Funding License Citation

README.md

goNEAT 🇺🇦 Made in Ukraine

banner

NeuroEvolution — evolving Artificial Neural Networks topology from the scratch

version GoDoc Go version license yaricom/goNEAT DOI

| Branch | Tests | Coverage | Linting | Code Security | |--------|--------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------|----------------------------------------------------------------------------| | master | CI | codecov | Lint | CodeQL |

Overview

This repository provides implementation of NeuroEvolution of Augmenting Topologies (NEAT) method written in Go language.

The NeuroEvolution (NE) is an artificial evolution of Neural Networks (NN) using genetic algorithms to find optimal NN parameters and network topology. NeuroEvolution of NN may assume a search for optimal weights of connections between NN nodes and search for the optimal topology of the resulting network graph. The NEAT method implemented in this work searches for optimal connection weights and the network graph topology for a given task (number of NN nodes per layer and their interconnections).

Minimum requirements

| Requirement | Notes | |-------------|------------------| | Go version | Go1.18 or higher |

Releases

Please do not depend on master as your production branch. Use releases instead.

Quick Start

You can evaluate the NEAT algorithm performance by running the following command:

bash cd $GOPATH/src/github.com/yaricom/goNEAT go run executor.go -out ./out/xor -context ./data/xor.neat -genome ./data/xorstartgenes -experiment XOR

Or

bash make run-xor `

The command above will run the XOR problem solver experiment and save the collected data samples. You can use saved experimental data for analysis using standard plotting libraries as in the figure below.

The XOR results plot

The figure was created using Matplotlib. You can find more details in the Jupyter notebook.

Documentation

You can find the algorithm performance evaluation and related documentation in the project's wiki

The goNEAT library saves results of the experiments using Numpy NPZ format, which allows analysis of collected experimental data samples using a variety of readily available Python libraries.

For your reference, we included Jupyter notebook with an example of the collected experimental data analysis, which can be used as a starter kit to analyze data samples acquired from your experiments.

Installation

Make sure you have at least GO 1.15.x installed onto your system and execute the following command: ```bash

go get github.com/yaricom/goNEAT ```

For new projects, consider using the v2 of the library with the following import:

go import "github.com/yaricom/goNEAT/v3"

Essential Packages

genetics package

The genetics package provides the genetic part of the NEAT algorithm describing all the machinery related to genome mutations, mating, and speciation of the population of organisms.

It contains implementation of all important types related to the NEAT algorithm: * Gene type in this system specifies a "Connection Gene." * MIMOControlGene type is the Multiple-Input Multiple-Output (MIMO) control Gene which allows creation of modular genomes
* Genome type is the primary source of genotype information used to create a phenotype. * Organism type is Genotypes (Genomes) and Phenotypes (Networks) combined with fitness information, i.e. the genotype and phenotype together. * Population type is a group of Organisms including their Species * Species type is a group of similar Organisms. Reproduction takes place mostly within a single species, so that compatible organisms can mate.

Additionally, it contains variety of utility functions to serialise/deserialize specified above types using two supported data formats: * plain text * YAML

The current implementation supports sequential and parallel execution of evolution epoch which controlled by related parameter in the NEAT context options.

math package

Package math defines standard mathematical primitives used by the NEAT algorithm as well as utility functions

network package

Package network provides data structures and utilities to describe Artificial Neural Network and network solvers.

The most important types are: * NNode type defines the node of the network and is a part of organism's genotype as well as phenotype * Link type is a connection from one node to another with an associated weight. * Network type is a collection of all nodes within an organism's phenotype, which effectively defines Neural Network topology. * Solver type defines network solver interface, which allows propagation of the activation waves through the underlying network graph.

The current implementation supports two types of network solvers: * FastModularNetworkSolver is the network solver implementation to be used for large neural networks simulation. * Standard Network Solver implemented by the Network type

The topology of the Neural Network represented by the Network fully supports the directed graph presentation as defined by Gonum graph package. This feature can be used for analysis of the network topology as well as encoding the graph in variety of popular graph presentation formats.

experiment package

Package experiment defines standard evolutionary epochs evaluators and experimental data samples collectors. It provides standardised approach to define experiments using the NEAT algorithm implementation.

The most important type here is: * GenerationEvaluator is the interface to be implemented by custom experiments

You can find examples of GenerationEvaluator implementations at examples: * pole - single-, double-pole balancing experiments * xor - XOR solver experiment

The following code snippet demonstrates how to run experiments using different implementations of the GenerationEvaluator and the experiment.Execute:

```go // create experiment expt := experiment.Experiment{ Id: 0, Trials: make(experiment.Trials, neatOptions.NumRuns), RandSeed: seed, } var generationEvaluator experiment.GenerationEvaluator switch *experimentName { case "XOR": exp.MaxFitnessScore = 16.0 // as given by fitness function definition generationEvaluator = xor.NewXORGenerationEvaluator(outDir) case "cartpole": exp.MaxFitnessScore = 1.0 // as given by fitness function definition generationEvaluator = pole.NewCartPoleGenerationEvaluator(outDir, true, 1500000) case "cartpoleparallel": exp.MaxFitnessScore = 1.0 // as given by fitness function definition generationEvaluator = pole.NewCartPoleParallelGenerationEvaluator(outDir, true, 1500000) case "cart2polemarkov": exp.MaxFitnessScore = 1.0 // as given by fitness function definition generationEvaluator = pole2.NewCartDoublePoleGenerationEvaluator(outDir, true, pole2.ContinuousAction) case "cart2polenon-markov": generationEvaluator = pole2.NewCartDoublePoleGenerationEvaluator(outDir, false, pole2.ContinuousAction) case "cart2polemarkovparallel": exp.MaxFitnessScore = 1.0 // as given by fitness function definition generationEvaluator = pole2.NewCartDoublePoleParallelGenerationEvaluator(outDir, true, pole2.ContinuousAction) default: log.Fatalf("Unsupported experiment: %s", *experimentName) }

// prepare to execute errChan := make(chan error) ctx, cancel := context.WithCancel(context.Background())

// run experiment in the separate GO routine go func() { if err = expt.Execute(neat.NewContext(ctx, neatOptions), startGenome, generationEvaluator, nil); err != nil { errChan <- err } else { errChan <- nil } }() ```

For more details, take a look at the experiment executor implementation provided with the goNEAT library.

neat package

Package neat is an entry point to the NEAT algorithm. It defines the NEAT execution context and configuration options.

You can find all available configuration options in the Options.

The configuration options can be saved either using plain text or the YAML format. We recommend using the YAML format for new projects because it allows for a more flexible setup and detailed documentation of the configuration parameters.

Take a look at the example configuration file to get a better understanding.

The NEAT context options can be read as follows:

go // Loading YAML options optFile, err := os.Open("./data/xor_test.neat.yml") if err != nil { return err } options, err := neat.LoadYAMLOptions(optFile)

Or with plain-text format:

go // Loading plain-text options optFile, err := os.Open("./data/xor_test.neat") if err != nil { return err } options, err := neat.LoadNeatOptions(optFile)

Phenotype Network Graph Visualization

The formats package provides support for various network graph serialization formats which can be used to visualize the graph with help of well-known tools. Currently, we have support for DOT and CytoscapeJS data formats.

The CytoscapeJS JSON format

Another important data format supported by the library is the CytoscapeJS JSON. The Network graph serialized into this format can be easily rendered using either Cytoscape App or the corresponding CytoscapeJS JavaScript library.

The following code snippet demonstrates how this can be done: ```go import ( "github.com/yaricom/goNEAT/v3/neat/network" "github.com/yaricom/goNEAT/v3/neat/network/formats" "bytes" "fmt" )

allNodes := []*network.NNode{ network.NewNNode(1, network.InputNeuron), network.NewNNode(2, network.InputNeuron), network.NewNNode(3, network.BiasNeuron), network.NewNNode(4, network.HiddenNeuron), network.NewNNode(5, network.HiddenNeuron), network.NewNNode(6, network.HiddenNeuron), network.NewNNode(7, network.OutputNeuron), network.NewNNode(8, network.OutputNeuron), }

// HIDDEN 4 allNodes3.connectFrom(allNodes[0], 15.0) allNodes3.connectFrom(allNodes1, 10.0) // HIDDEN 5 allNodes4.connectFrom(allNodes1, 5.0) allNodes4.connectFrom(allNodes2, 1.0) // HIDDEN 6 allNodes5.connectFrom(allNodes4, 17.0) // OUTPUT 7 allNodes6.connectFrom(allNodes3, 7.0) allNodes6.connectFrom(allNodes5, 4.5) // OUTPUT 8 allNodes[7].connectFrom(allNodes5, 13.0)

net := network.NewNetwork(allNodes[0:3], allNodes[6:8], allNodes, 0)

b := bytes.NewBufferString("") err := formats.WriteCytoscapeJSON(b, net) fmt.Println(b) The produced output looks like the following: json { "elements": { "nodes": [ { "data": { "activationfunction": "SigmoidSteepenedActivation", "activationvalue": 0, "background-color": "#339FDC", "border-color": "#CCCCCC", "controlnode": false, "id": "1", "inconnectionscount": 0, "neurontype": "INPT", "nodetype": "SENSOR", "outconnectionscount": 1, "parent": "", "shape": "diamond" }, "selectable": true }, { "data": { "activationfunction": "SigmoidSteepenedActivation", "activationvalue": 0, "background-color": "#339FDC", "border-color": "#CCCCCC", "controlnode": false, "id": "2", "inconnectionscount": 0, "neurontype": "INPT", "nodetype": "SENSOR", "outconnectionscount": 2, "parent": "", "shape": "diamond" }, "selectable": true }, { "data": { "activationfunction": "SigmoidSteepenedActivation", "activationvalue": 0, "background-color": "#FFCC33", "border-color": "#CCCCCC", "controlnode": false, "id": "3", "inconnectionscount": 0, "neurontype": "BIAS", "nodetype": "SENSOR", "outconnectionscount": 1, "parent": "", "shape": "pentagon" }, "selectable": true }, { "data": { "activationfunction": "SigmoidSteepenedActivation", "activationvalue": 0, "background-color": "#009999", "border-color": "#CCCCCC", "controlnode": false, "id": "4", "inconnectionscount": 2, "neurontype": "HIDN", "nodetype": "NEURON", "outconnectionscount": 1, "parent": "", "shape": "hexagon" }, "selectable": true }, { "data": { "activationfunction": "SigmoidSteepenedActivation", "activationvalue": 0, "background-color": "#009999", "border-color": "#CCCCCC", "controlnode": false, "id": "5", "inconnectionscount": 2, "neurontype": "HIDN", "nodetype": "NEURON", "outconnectionscount": 1, "parent": "", "shape": "hexagon" }, "selectable": true }, { "data": { "activationfunction": "SigmoidSteepenedActivation", "activationvalue": 0, "background-color": "#009999", "border-color": "#CCCCCC", "controlnode": false, "id": "6", "inconnectionscount": 1, "neurontype": "HIDN", "nodetype": "NEURON", "outconnectionscount": 2, "parent": "", "shape": "hexagon" }, "selectable": true }, { "data": { "activationfunction": "SigmoidSteepenedActivation", "activationvalue": 0, "background-color": "#E7298A", "border-color": "#CCCCCC", "controlnode": false, "id": "7", "inconnectionscount": 2, "neurontype": "OUTP", "nodetype": "NEURON", "outconnectionscount": 0, "parent": "", "shape": "round-rectangle" }, "selectable": true }, { "data": { "activationfunction": "SigmoidSteepenedActivation", "activationvalue": 0, "background-color": "#E7298A", "border-color": "#CCCCCC", "controlnode": false, "id": "8", "inconnectionscount": 1, "neurontype": "OUTP", "nodetype": "NEURON", "outconnectionscount": 0, "parent": "", "shape": "round-rectangle" }, "selectable": true } ], "edges": [ { "data": { "id": "1-4", "recurrent": false, "source": "1", "target": "4", "timedelayed": false, "weight": 15 }, "selectable": true }, { "data": { "id": "2-4", "recurrent": false, "source": "2", "target": "4", "timedelayed": false, "weight": 10 }, "selectable": true }, { "data": { "id": "2-5", "recurrent": false, "source": "2", "target": "5", "timedelayed": false, "weight": 5 }, "selectable": true }, { "data": { "id": "3-5", "recurrent": false, "source": "3", "target": "5", "timedelayed": false, "weight": 1 }, "selectable": true }, { "data": { "id": "5-6", "recurrent": false, "source": "5", "target": "6", "timedelayed": false, "weight": 17 }, "selectable": true }, { "data": { "id": "4-7", "recurrent": false, "source": "4", "target": "7", "timedelayed": false, "weight": 7 }, "selectable": true }, { "data": { "id": "6-7", "recurrent": false, "source": "6", "target": "7", "timedelayed": false, "weight": 4.5 }, "selectable": true }, { "data": { "id": "6-8", "recurrent": false, "source": "6", "target": "8", "timedelayed": false, "weight": 13 }, "selectable": true } ] }, "layout": { "name": "circle" }, "style": [ { "selector": "node", "style": { "background-color": "data(background-color)", "border-color": "data(border-color)", "border-width": 3, "label": "data(id)", "shape": "data(shape)" } }, { "selector": "edge", "style": { "curve-style": "bezier", "line-color": "#CCCCCC", "target-arrow-color": "#CCCCCC", "target-arrow-shape": "triangle-backcurve", "width": 5 } } ] } ```

The above CYJS can be visualized as following with Cytoscape App.

Example Network

You can find more interesting visualizations at project's Wiki.

The DOT format

The Network can be serialized into popular GraphViz DOT format. The following code snippet demonstrates how this can be done:

```go import ( "github.com/yaricom/goNEAT/v3/neat/network" "github.com/yaricom/goNEAT/v3/neat/network/formats" "bytes" "fmt" )

allNodes := []*network.NNode{ network.NewNNode(1, network.InputNeuron), network.NewNNode(2, network.InputNeuron), network.NewNNode(3, network.BiasNeuron), network.NewNNode(4, network.HiddenNeuron), network.NewNNode(5, network.HiddenNeuron), network.NewNNode(6, network.HiddenNeuron), network.NewNNode(7, network.OutputNeuron), network.NewNNode(8, network.OutputNeuron), }

// HIDDEN 4 allNodes3.connectFrom(allNodes[0], 15.0) allNodes3.connectFrom(allNodes1, 10.0) // HIDDEN 5 allNodes4.connectFrom(allNodes1, 5.0) allNodes4.connectFrom(allNodes2, 1.0) // HIDDEN 6 allNodes5.connectFrom(allNodes4, 17.0) // OUTPUT 7 allNodes6.connectFrom(allNodes3, 7.0) allNodes6.connectFrom(allNodes5, 4.5) // OUTPUT 8 allNodes[7].connectFrom(allNodes5, 13.0)

net := network.NewNetwork(allNodes[0:3], allNodes[6:8], allNodes, 0) net.Name = "TestNN"

b := bytes.NewBufferString("") err := formats.WriteDOT(b, net) fmt.Println(b) ```

The DOT output can be saved into the file for subsequent visualization by variety of tools listed at GraphViz Downloads.

Conclusion

The experiments described in this work confirm that introduced NEAT algorithm implementation can evolve new structures in the Artificial Neural Networks (XOR experiments) and can solve reinforcement learning tasks under conditions of incomplete knowledge (single-pole balancing and double-pole balancing).

We hope that you will find great applications in your research and work projects for the provided NEAT algorithm's implementation as well as utilities to run experiments while collecting relevant data samples.

Projects Using goNEAT library

  • Learning to play Asteroids in Golang with NEAT - interesting article about implementation of the intelligent agent to play classic Asteroid game using the NEAT algorithm.
  • NEAT with Novelty Search - implementation of the Novelty Search optimization algorithm for solution search in the deceptive environments.
  • Evolvable-Substrate HyperNEAT - is hypercube-based extension of the NEAT allowing to encode ANNs in the substrate with specific geometric topology and with significant number of neural units.

References

Citing

If you find our work useful, please consider citing:

text @software{omelianenko_iaroslav_zenodo_8178788, author = {Omelianenko, Iaroslav}, title = {The GoLang implementation of NeuroEvolution of Augmented Topologies (NEAT) algorithm}, month = {9}, year = {2024}, note = {If you use this software, please cite it as below.}, publisher = {Zenodo}, version = {v4.2.0}, doi = {10.5281/zenodo.8178788}, url = {https://doi.org/10.5281/zenodo.8178788} }

This source code maintained and managed by Iaroslav Omelianenko

Owner

  • Name: Iaroslav Omelianenko
  • Login: yaricom
  • Kind: user
  • Location: Kiev, Ukraine
  • Company: @NewGround-LLC

Research & Development, Synthetic Intelligence, Neuroevolution, Cooperative Robotics. Author of the “Hands-On Neuroevolution with Python” http://bit.ly/3bGR7p9

Citation (CITATION.cff)

cff-version: 1.2.0
message: "If you use this software, please cite it as below."
authors:
- family-names: "Omelianenko"
  given-names: "Iaroslav"
  orcid: "https://orcid.org/0000-0002-2190-5664"
title: "The GoLang implementation of NeuroEvolution of Augmented Topologies (NEAT) algorithm"
version: 4.0.1
doi: 10.5281/zenodo.8178789
date-released: 2023-07-24
url: "https://github.com/yaricom/goNEAT"

GitHub Events

Total
  • Release event: 1
  • Watch event: 3
  • Push event: 4
  • Create event: 1
Last Year
  • Release event: 1
  • Watch event: 3
  • Push event: 4
  • Create event: 1

Committers

Last synced: 10 months ago

All Time
  • Total Commits: 783
  • Total Committers: 1
  • Avg Commits per committer: 783.0
  • Development Distribution Score (DDS): 0.0
Past Year
  • Commits: 14
  • Committers: 1
  • Avg Commits per committer: 14.0
  • Development Distribution Score (DDS): 0.0
Top Committers
Name Email Commits
Iaroslav Omelianenko y****l@y****m 783

Issues and Pull Requests

Last synced: 11 months ago

All Time
  • Total issues: 25
  • Total pull requests: 40
  • Average time to close issues: about 1 month
  • Average time to close pull requests: 12 days
  • Total issue authors: 7
  • Total pull request authors: 1
  • Average comments per issue: 1.52
  • Average comments per pull request: 0.33
  • Merged pull requests: 40
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 0
  • Pull requests: 1
  • Average time to close issues: N/A
  • Average time to close pull requests: about 2 months
  • Issue authors: 0
  • Pull request authors: 1
  • Average comments per issue: 0
  • Average comments per pull request: 0.0
  • Merged pull requests: 1
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • yaricom (13)
  • qwertyuu (5)
  • steampoweredtaco (3)
  • chrispytoes (1)
  • simon-winter (1)
  • rubens21 (1)
  • oowhyy (1)
Pull Request Authors
  • yaricom (41)
Top Labels
Issue Labels
enhancement (9)
Pull Request Labels

Packages

  • Total packages: 8
  • Total downloads: unknown
  • Total dependent packages: 8
    (may contain duplicates)
  • Total dependent repositories: 4
    (may contain duplicates)
  • Total versions: 37
proxy.golang.org: github.com/yaricom/goNEAT/v3
  • Versions: 4
  • Dependent Packages: 2
  • Dependent Repositories: 2
Rankings
Dependent repos count: 3.6%
Dependent packages count: 3.7%
Average: 4.4%
Forks count: 5.1%
Stargazers count: 5.4%
Last synced: 7 months ago
proxy.golang.org: github.com/yaricom/goNEAT
  • Versions: 0
  • Dependent Packages: 4
  • Dependent Repositories: 1
Rankings
Dependent packages count: 2.5%
Average: 4.5%
Dependent repos count: 4.8%
Forks count: 5.1%
Stargazers count: 5.5%
Last synced: 7 months ago
proxy.golang.org: github.com/yaricom/goNEAT/v2
  • Versions: 6
  • Dependent Packages: 2
  • Dependent Repositories: 1
Rankings
Dependent packages count: 3.7%
Average: 4.7%
Dependent repos count: 4.8%
Forks count: 5.1%
Stargazers count: 5.4%
Last synced: 7 months ago
proxy.golang.org: github.com/yaricom/goneat
  • Versions: 1
  • Dependent Packages: 0
  • Dependent Repositories: 0
Rankings
Forks count: 3.2%
Stargazers count: 3.3%
Average: 5.7%
Dependent packages count: 7.0%
Dependent repos count: 9.3%
Last synced: 7 months ago
proxy.golang.org: github.com/yaricom/goneat/v4
  • Versions: 8
  • Dependent Packages: 0
  • Dependent Repositories: 0
Rankings
Forks count: 5.1%
Stargazers count: 5.3%
Average: 7.5%
Dependent packages count: 8.9%
Dependent repos count: 10.6%
Last synced: 7 months ago
proxy.golang.org: github.com/yaricom/goNEAT/v4
  • Versions: 8
  • Dependent Packages: 0
  • Dependent Repositories: 0
Rankings
Forks count: 5.1%
Stargazers count: 5.3%
Average: 7.5%
Dependent packages count: 8.9%
Dependent repos count: 10.6%
Last synced: 7 months ago
proxy.golang.org: github.com/yaricom/goneat/v2
  • Versions: 6
  • Dependent Packages: 0
  • Dependent Repositories: 0
Rankings
Dependent packages count: 7.0%
Average: 8.2%
Dependent repos count: 9.3%
Last synced: 7 months ago
proxy.golang.org: github.com/yaricom/goneat/v3
  • Versions: 4
  • Dependent Packages: 0
  • Dependent Repositories: 0
Rankings
Dependent packages count: 7.0%
Average: 8.2%
Dependent repos count: 9.3%
Last synced: 7 months ago

Dependencies

go.mod go
  • github.com/davecgh/go-spew v1.1.0
  • github.com/pkg/errors v0.9.1
  • github.com/pmezard/go-difflib v1.0.0
  • github.com/sbinet/npyio v0.6.0
  • github.com/spf13/cast v1.5.0
  • github.com/stretchr/objx v0.1.0
  • github.com/stretchr/testify v1.7.1
  • golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3
  • gonum.org/v1/gonum v0.11.0
  • gopkg.in/yaml.v3 v3.0.1
go.sum go
  • dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9
  • gioui.org v0.0.0-20210308172011-57750fc8a0a6
  • github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802
  • github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af
  • github.com/boombuler/barcode v1.0.0
  • github.com/campoy/embedmd v1.0.0
  • github.com/davecgh/go-spew v1.1.0
  • github.com/davecgh/go-spew v1.1.1
  • github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90
  • github.com/fogleman/gg v1.3.0
  • github.com/frankban/quicktest v1.14.3
  • github.com/go-fonts/dejavu v0.1.0
  • github.com/go-fonts/latin-modern v0.2.0
  • github.com/go-fonts/liberation v0.1.1
  • github.com/go-fonts/stix v0.1.0
  • github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1
  • github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07
  • github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
  • github.com/google/go-cmp v0.5.7
  • github.com/jung-kurt/gofpdf v1.0.0
  • github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5
  • github.com/kr/pretty v0.3.0
  • github.com/kr/text v0.2.0
  • github.com/phpdave11/gofpdf v1.4.2
  • github.com/phpdave11/gofpdi v1.0.12
  • github.com/pkg/errors v0.8.1
  • github.com/pkg/errors v0.9.1
  • github.com/pmezard/go-difflib v1.0.0
  • github.com/rogpeppe/go-internal v1.6.1
  • github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58
  • github.com/sbinet/npyio v0.6.0
  • github.com/spf13/cast v1.5.0
  • github.com/stretchr/objx v0.1.0
  • github.com/stretchr/testify v1.2.2
  • github.com/stretchr/testify v1.7.1
  • golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2
  • golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529
  • golang.org/x/exp v0.0.0-20180321215751-8460e604b9de
  • golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f
  • golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2
  • golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8
  • golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3
  • golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81
  • golang.org/x/image v0.0.0-20190227222117-0694c2d4d067
  • golang.org/x/image v0.0.0-20190802002840-cff245a6509b
  • golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a
  • golang.org/x/image v0.0.0-20200119044424-58c23975cae1
  • golang.org/x/image v0.0.0-20200430140353-33d19683fad8
  • golang.org/x/image v0.0.0-20200618115811-c13761719519
  • golang.org/x/image v0.0.0-20201208152932-35266b937fa6
  • golang.org/x/image v0.0.0-20210216034530-4410531fe030
  • golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028
  • golang.org/x/mod v0.1.0
  • golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3
  • golang.org/x/net v0.0.0-20190620200207-3b0461eec859
  • golang.org/x/sync v0.0.0-20190423024810-112230192c58
  • golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a
  • golang.org/x/sys v0.0.0-20190312061237-fead79001313
  • golang.org/x/sys v0.0.0-20190412213103-97732733099d
  • golang.org/x/sys v0.0.0-20210304124612-50617c2ba197
  • golang.org/x/text v0.3.0
  • golang.org/x/text v0.3.5
  • golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b
  • golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e
  • golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e
  • golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e
  • golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7
  • golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
  • gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4
  • gonum.org/v1/gonum v0.8.2
  • gonum.org/v1/gonum v0.9.3
  • gonum.org/v1/gonum v0.11.0
  • gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0
  • gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b
  • gonum.org/v1/plot v0.9.0
  • gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405
  • gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
  • gopkg.in/yaml.v3 v3.0.1
  • rsc.io/pdf v0.1.1
.github/workflows/ci.yml actions
  • actions/checkout v2 composite
  • actions/setup-go v2 composite
.github/workflows/codeql-analysis.yml actions
  • actions/checkout v2 composite
  • github/codeql-action/analyze v1 composite
  • github/codeql-action/autobuild v1 composite
  • github/codeql-action/init v1 composite
.github/workflows/drafter.yml actions
  • release-drafter/release-drafter v5 composite
.github/workflows/lint.yml actions
  • actions/checkout v3 composite
  • actions/setup-go v3 composite
  • golangci/golangci-lint-action v3 composite