From 918fd328846fbc8f7b104a591d7c7ccefdbf6aa1 Mon Sep 17 00:00:00 2001 From: Roy Han Date: Thu, 25 Jul 2024 14:01:01 -0700 Subject: [PATCH] initial commit --- cmd/interactive.go | 147 ++++++++++++++++++++++++++++++++++++++++++++- go.mod | 20 ++++++ go.sum | 45 ++++++++++++++ plot.png | Bin 0 -> 9420 bytes 4 files changed, 209 insertions(+), 3 deletions(-) create mode 100644 plot.png diff --git a/cmd/interactive.go b/cmd/interactive.go index adbc3e9fb..71d49e021 100644 --- a/cmd/interactive.go +++ b/cmd/interactive.go @@ -1,6 +1,7 @@ package cmd import ( + "encoding/json" "errors" "fmt" "io" @@ -13,6 +14,11 @@ import ( "strings" "github.com/spf13/cobra" + "gonum.org/v1/gonum/mat" + "gonum.org/v1/gonum/stat" + "gonum.org/v1/plot" + "gonum.org/v1/plot/plotter" + "gonum.org/v1/plot/vg" "github.com/ollama/ollama/api" "github.com/ollama/ollama/envconfig" @@ -375,9 +381,9 @@ func generateInteractive(cmd *cobra.Command, opts runOptions) error { return err } req := &api.ShowRequest{ - Name: opts.Model, - System: opts.System, - Options: opts.Options, + Name: opts.Model, + System: opts.System, + Options: opts.Options, } resp, err := client.Show(cmd.Context(), req) if err != nil { @@ -447,6 +453,140 @@ func generateInteractive(cmd *cobra.Command, opts runOptions) error { } case strings.HasPrefix(line, "/exit"), strings.HasPrefix(line, "/bye"): return nil + case strings.HasPrefix(line, "/embed"): + line = strings.TrimPrefix(line, "/embed") + client, err := api.ClientFromEnvironment() + if err != nil { + fmt.Println("error: couldn't connect to ollama server") + return err + } + + var strArray []string + fmt.Printf("line is %s\n", line) + err = json.Unmarshal([]byte(line), &strArray) + if err != nil { + fmt.Println("error: couldn't parse input") + return err + } + + for i, s := range strArray { + fmt.Printf("strArray[%d] is %s\n", i, s) + } + + req := &api.EmbedRequest{ + Model: opts.Model, + Input: strArray, + } + + resp, err := client.Embed(cmd.Context(), req) + if err != nil { + fmt.Println("error: couldn't get embeddings") + return err + } + + embeddings := resp.Embeddings + + r, c := len(embeddings), len(embeddings[0]) + data := make([]float64, r*c) + for i := 0; i < r; i++ { + for j := 0; j < c; j++ { + data[i*c+j] = float64(embeddings[i][j]) + } + } + + X := mat.NewDense(r, c, data) + + // Initialize PCA + var pca stat.PC + + // Perform PCA + if !pca.PrincipalComponents(X, nil) { + return fmt.Errorf("PCA failed") + } + + // Extract principal component vectors + var vectors mat.Dense + pca.VectorsTo(&vectors) + + // // Extract variances of the principal components + // var variances []float64 + // variances = pca.VarsTo(variances) + + W := vectors.Slice(0, c, 0, 2).(*mat.Dense) + + // Perform PCA reduction + var reducedData mat.Dense + reducedData.Mul(X, W) + + // Print the projected 2D points + fmt.Println("Reduced embeddings to 2D:") + for i := 0; i < reducedData.RawMatrix().Rows; i++ { + row := reducedData.RowView(i) + fmt.Printf("[%v, %v]\n", row.AtVec(0), row.AtVec(1)) + } + + points := make(plotter.XYs, reducedData.RawMatrix().Rows) + for i := 0; i < reducedData.RawMatrix().Rows; i++ { + row := reducedData.RowView(i) + points[i].X = row.AtVec(0) + points[i].Y = row.AtVec(1) + } + + // Create a new plot + p := plot.New() + + // Set plot title and axis labels + p.Title.Text = "2D Data Plot" + p.X.Label.Text = "X" + p.Y.Label.Text = "Y" + + // Create a scatter plot of the points + s, err := plotter.NewScatter(points) + if err != nil { + panic(err) + } + p.Add(s) + + /// Create labels plotter and add it to the plot + + labels := make([]string, reducedData.RawMatrix().Rows) + for i := 0; i < reducedData.RawMatrix().Rows; i++ { + labels[i] = fmt.Sprintf("%d", i+1) + } + + l, err := plotter.NewLabels(plotter.XYLabels{XYs: points, Labels: labels}) + if err != nil { + panic(err) + } + p.Add(l) + + // Make the grid square + p.X.Min = -1 + p.X.Max = 1 + p.Y.Min = -1 + p.Y.Max = 1 + + // Set the aspect ratio to be 1:1 + p.X.Tick.Marker = plot.ConstantTicks([]plot.Tick{ + {Value: -1, Label: "-1"}, + {Value: -0.5, Label: "-0.5"}, + {Value: 0, Label: "0"}, + {Value: 0.5, Label: "0.5"}, + {Value: 1, Label: "1"}, + }) + p.Y.Tick.Marker = plot.ConstantTicks([]plot.Tick{ + {Value: -1, Label: "-1"}, + {Value: -0.5, Label: "-0.5"}, + {Value: 0, Label: "0"}, + {Value: 0.5, Label: "0.5"}, + {Value: 1, Label: "1"}, + }) + + // Save the plot to a PNG file + if err := p.Save(6*vg.Inch, 6*vg.Inch, "plot.png"); err != nil { + panic(err) + } + case strings.HasPrefix(line, "/"): args := strings.Fields(line) isFile := false @@ -466,6 +606,7 @@ func generateInteractive(cmd *cobra.Command, opts runOptions) error { } sb.WriteString(line) + default: sb.WriteString(line) } diff --git a/go.mod b/go.mod index 2e0c6614c..57d623d73 100644 --- a/go.mod +++ b/go.mod @@ -25,25 +25,45 @@ require ( ) require ( + gioui.org v0.2.0 // indirect + gioui.org/cpu v0.0.0-20220412190645-f1e9e8c3b1f7 // indirect + gioui.org/shader v1.0.6 // indirect + gioui.org/x v0.2.0 // indirect + git.sr.ht/~sbinet/gg v0.5.0 // indirect + github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b // indirect + github.com/andybalholm/stroke v0.0.0-20221221101821-bd29b49d73f0 // indirect github.com/apache/arrow/go/arrow v0.0.0-20211112161151-bc219186db40 // indirect github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/campoy/embedmd v1.0.0 // indirect github.com/chewxy/hm v1.0.0 // indirect github.com/chewxy/math32 v1.10.1 // indirect github.com/cloudwego/base64x v0.1.4 // indirect github.com/cloudwego/iasm v0.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/gizak/termui/v3 v3.1.0 // indirect + github.com/go-fonts/liberation v0.3.2 // indirect + github.com/go-latex/latex v0.0.0-20231108140139-5c1ce85aa4ea // indirect + github.com/go-pdf/fpdf v0.9.0 // indirect + github.com/go-text/typesetting v0.0.0-20230803102845-24e03d8b5372 // indirect github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect github.com/google/flatbuffers v24.3.25+incompatible // indirect github.com/kr/text v0.2.0 // indirect + github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect + github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/xtgo/set v1.0.0 // indirect go4.org/unsafe/assume-no-moving-gc v0.0.0-20231121144256-b99613f794b6 // indirect + golang.org/x/exp/shiny v0.0.0-20230801115018-d63ba01acd4b // indirect + golang.org/x/image v0.14.0 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect gonum.org/v1/gonum v0.15.0 // indirect + gonum.org/v1/plot v0.14.0 // indirect gorgonia.org/vecf32 v0.9.0 // indirect gorgonia.org/vecf64 v0.9.0 // indirect + rsc.io/pdf v0.1.1 // indirect ) require ( diff --git a/go.sum b/go.sum index 926ed26d8..dca34f684 100644 --- a/go.sum +++ b/go.sum @@ -2,11 +2,28 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= +gioui.org v0.2.0 h1:RbzDn1h/pCVf/q44ImQSa/J3MIFpY3OWphzT/Tyei+w= +gioui.org v0.2.0/go.mod h1:1H72sKEk/fNFV+l0JNeM2Dt3co3Y4uaQcD+I+/GQ0e4= +gioui.org/cpu v0.0.0-20210808092351-bfe733dd3334/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ= +gioui.org/cpu v0.0.0-20220412190645-f1e9e8c3b1f7 h1:tNJdnP5CgM39PRc+KWmBRRYX/zJ+rd5XaYxY5d5veqA= +gioui.org/cpu v0.0.0-20220412190645-f1e9e8c3b1f7/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ= +gioui.org/shader v1.0.6 h1:cvZmU+eODFR2545X+/8XucgZdTtEjR3QWW6W65b0q5Y= +gioui.org/shader v1.0.6/go.mod h1:mWdiME581d/kV7/iEhLmUgUK5iZ09XR5XpduXzbePVM= +gioui.org/x v0.2.0 h1:/MbdjKH19F16auv19UiQxli2n6BYPw7eyh9XBOTgmEw= +gioui.org/x v0.2.0/go.mod h1:rCGN2nZ8ZHqrtseJoQxCMZpt2xrZUrdZ2WuMRLBJmYs= +git.sr.ht/~sbinet/gg v0.5.0 h1:6V43j30HM623V329xA9Ntq+WJrMjDxRjuAB1LFWF5m8= +git.sr.ht/~sbinet/gg v0.5.0/go.mod h1:G2C0eRESqlKhS7ErsNey6HHrqU1PwsnCQlekFi9Q2Oo= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= +github.com/ajstarks/deck v0.0.0-20200831202436-30c9fc6549a9/go.mod h1:JynElWSGnm/4RlzPXRlREEwqTHAN3T56Bv2ITsFT3gY= +github.com/ajstarks/deck/generate v0.0.0-20210309230005-c3f852c02e19/go.mod h1:T13YZdzov6OU0A1+RfKZiZN9ca6VeKdBdyDV+BY97Tk= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b h1:slYM766cy2nI3BwyRiyQj/Ud48djTMtMebDqepE95rw= +github.com/ajstarks/svgo v0.0.0-20211024235047-1546f124cd8b/go.mod h1:1KcenG0jGWcpt8ov532z81sp/kMMUG485J2InIOyADM= +github.com/andybalholm/stroke v0.0.0-20221221101821-bd29b49d73f0 h1:uF5Q/hWnDU1XZeT6CsrRSxHLroUSEYYO3kgES+yd+So= +github.com/andybalholm/stroke v0.0.0-20221221101821-bd29b49d73f0/go.mod h1:ccdDYaY5+gO+cbnQdFxEXqfy0RkoV25H3jLXUDNM3wg= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/arrow/go/arrow v0.0.0-20211112161151-bc219186db40 h1:q4dksr6ICHXqG5hm0ZW5IHyeEJXoIJSOZeBLmWPNeIQ= github.com/apache/arrow/go/arrow v0.0.0-20211112161151-bc219186db40/go.mod h1:Q7yQnSMnLvcXlZ8RV+jwz/6y1rQTqbX6C82SndT52Zs= @@ -17,6 +34,8 @@ github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/campoy/embedmd v1.0.0 h1:V4kI2qTJJLf4J29RzI/MAt2c3Bl4dQSYPuflzwFH2hY= +github.com/campoy/embedmd v1.0.0/go.mod h1:oxyr9RCiSXg0M3VJ3ks0UGfp98BpSSGr0kpiX3MzVl8= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chewxy/hm v1.0.0 h1:zy/TSv3LV2nD3dwUEQL2VhXeoXbb9QkpmdRAVUFiA6k= github.com/chewxy/hm v1.0.0/go.mod h1:qg9YI4q6Fkj/whwHR1D+bOGeF7SniIP40VweVepLjg0= @@ -62,12 +81,20 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/gizak/termui/v3 v3.1.0 h1:ZZmVDgwHl7gR7elfKf1xc4IudXZ5qqfDh4wExk4Iajc= +github.com/gizak/termui/v3 v3.1.0/go.mod h1:bXQEBkJpzxUAKf0+xq9MSWAvWZlE7c+aidmyFlkYTrY= github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/liberation v0.3.2 h1:XuwG0vGHFBPRRI8Qwbi5tIvR3cku9LUfZGq/Ar16wlQ= +github.com/go-fonts/liberation v0.3.2/go.mod h1:N0QsDLVUQPy3UYg9XAc3Uh3UDMp2Z7M1o4+X98dXkmI= github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= +github.com/go-latex/latex v0.0.0-20231108140139-5c1ce85aa4ea h1:DfZQkvEbdmOe+JK2TMtBM+0I9GSdzE2y/L1/AmD8xKc= +github.com/go-latex/latex v0.0.0-20231108140139-5c1ce85aa4ea/go.mod h1:Y7Vld91/HRbTBm7JwoI7HejdDB0u+e9AUBO9MB7yuZk= +github.com/go-pdf/fpdf v0.9.0 h1:PPvSaUuo1iMi9KkaAn90NuKi+P4gwMedWPHhj8YlJQw= +github.com/go-pdf/fpdf v0.9.0/go.mod h1:oO8N111TkmKb9D7VvWGLvLJlaZUQVPM+6V42pp3iV4Y= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -76,10 +103,13 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-text/typesetting v0.0.0-20230803102845-24e03d8b5372 h1:FQivqchis6bE2/9uF70M2gmmLpe82esEm2QadL0TEJo= +github.com/go-text/typesetting v0.0.0-20230803102845-24e03d8b5372/go.mod h1:evDBbvNR/KaVFZ2ZlDSOWWXIUKq0wCOEtzLxRM8SG3k= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -138,9 +168,12 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM= +github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -148,6 +181,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/nlpodyssey/gopickle v0.3.0 h1:BLUE5gxFLyyNOPzlXxt6GoHEMMxD0qhsE4p0CIQyoLw= github.com/nlpodyssey/gopickle v0.3.0/go.mod h1:f070HJ/yR+eLi5WmM1OXJEGaTpuJEUiib19olXgYha0= +github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d h1:x3S6kxmy49zXVVyhcnrFqxvNVCBPb2KZ9hV2RBdS840= +github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/pdevine/tensor v0.0.0-20240510204454-f88f4562727c h1:GwiUUjKefgvSNmv3NCvI/BL0kDebW6Xa+kcdpdc1mTY= @@ -221,6 +256,8 @@ golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ= golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE= +golang.org/x/exp/shiny v0.0.0-20230801115018-d63ba01acd4b h1:sgkbz1SFTsoQIvzTIw45hccUcGocu00QM3qucBYV8b0= +golang.org/x/exp/shiny v0.0.0-20230801115018-d63ba01acd4b/go.mod h1:UH99kUObWAZkDnWqppdQe5ZhPYESUw8I0zVV1uWBR+0= golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -230,6 +267,8 @@ golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+o golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4= +golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -272,6 +311,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -303,6 +343,7 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -317,6 +358,8 @@ gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= +gonum.org/v1/plot v0.14.0 h1:+LBDVFYwFe4LHhdP8coW6296MBEY4nQ+Y4vuUpJopcE= +gonum.org/v1/plot v0.14.0/go.mod h1:MLdR9424SJed+5VqC6MsouEpig9pZX2VZ57H9ko2bXU= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -360,5 +403,7 @@ gorgonia.org/vecf64 v0.9.0 h1:bgZDP5x0OzBF64PjMGC3EvTdOoMEcmfAh1VCUnZFm1A= gorgonia.org/vecf64 v0.9.0/go.mod h1:hp7IOWCnRiVQKON73kkC/AUMtEXyf9kGlVrtPQ9ccVA= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/plot.png b/plot.png new file mode 100644 index 0000000000000000000000000000000000000000..1a35cd0d5535d4e2590c69b268a7b0c8949eb0d6 GIT binary patch literal 9420 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 E8$?c!0{{R3 literal 0 HcmV?d00001