diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..1ff0c42
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,63 @@
+###############################################################################
+# Set default behavior to automatically normalize line endings.
+###############################################################################
+* text=auto
+
+###############################################################################
+# Set default behavior for command prompt diff.
+#
+# This is need for earlier builds of msysgit that does not have it on by
+# default for csharp files.
+# Note: This is only used by command line
+###############################################################################
+#*.cs diff=csharp
+
+###############################################################################
+# Set the merge driver for project and solution files
+#
+# Merging from the command prompt will add diff markers to the files if there
+# are conflicts (Merging from VS is not affected by the settings below, in VS
+# the diff markers are never inserted). Diff markers may cause the following
+# file extensions to fail to load in VS. An alternative would be to treat
+# these files as binary and thus will always conflict and require user
+# intervention with every merge. To do so, just uncomment the entries below
+###############################################################################
+#*.sln merge=binary
+#*.csproj merge=binary
+#*.vbproj merge=binary
+#*.vcxproj merge=binary
+#*.vcproj merge=binary
+#*.dbproj merge=binary
+#*.fsproj merge=binary
+#*.lsproj merge=binary
+#*.wixproj merge=binary
+#*.modelproj merge=binary
+#*.sqlproj merge=binary
+#*.wwaproj merge=binary
+
+###############################################################################
+# behavior for image files
+#
+# image files are treated as binary by default.
+###############################################################################
+#*.jpg binary
+#*.png binary
+#*.gif binary
+
+###############################################################################
+# diff behavior for common document formats
+#
+# Convert binary document formats to text before diffing them. This feature
+# is only available from the command line. Turn it on by uncommenting the
+# entries below.
+###############################################################################
+#*.doc diff=astextplain
+#*.DOC diff=astextplain
+#*.docx diff=astextplain
+#*.DOCX diff=astextplain
+#*.dot diff=astextplain
+#*.DOT diff=astextplain
+#*.pdf diff=astextplain
+#*.PDF diff=astextplain
+#*.rtf diff=astextplain
+#*.RTF diff=astextplain
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5232a01
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,547 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Oo]ut/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# File created using '.gitignore Generator' for Visual Studio Code: https://bit.ly/vscode-gig
+
+# Created by https://www.toptal.com/developers/gitignore/api/rider,visualstudio,visualstudiocode,web,windows,zsh
+# Edit at https://www.toptal.com/developers/gitignore?templates=rider,visualstudio,visualstudiocode,web,windows,zsh
+
+### Rider ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# AWS User-specific
+.idea/**/aws.xml
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn. Uncomment if using
+# auto-import.
+# .idea/artifacts
+# .idea/compiler.xml
+# .idea/jarRepositories.xml
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+### VisualStudioCode ###
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+### VisualStudioCode Patch ###
+# Ignore all local history of files
+.history
+.ionide
+
+# Support for Project snippet scope
+!.vscode/*.code-snippets
+
+### Windows ###
+# Windows thumbnail cache files
+Thumbs.db
+Thumbs.db:encryptable
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+### Zsh ###
+# Zsh compiled script + zrecompile backup
+*.zwc
+*.zwc.old
+
+# Zsh completion-optimization dumpfile
+*zcompdump*
+
+# Zsh zcalc history
+.zcalc_history
+
+# A popular plugin manager's files
+._zinit
+.zinit_lstupd
+
+# zdharma/zshelldoc tool's files
+zsdoc/data
+
+# robbyrussell/oh-my-zsh/plugins/per-directory-history plugin's files
+# (when set-up to store the history in the local directory)
+.directory_history
+
+# MichaelAquilina/zsh-autoswitch-virtualenv plugin's files
+# (for Zsh plugins using Python)
+.venv
+
+# Zunit tests' output
+/tests/_output/*
+!/tests/_output/.gitkeep
+
+### VisualStudio ###
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# VS Code files for those working on multiple tools
+
+# Local History for Visual Studio Code
+
+# Windows Installer files from build outputs
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+### VisualStudio Patch ###
+# Additional files built by Visual Studio
+
+# End of https://www.toptal.com/developers/gitignore/api/rider,visualstudio,visualstudiocode,web,windows,zsh
+
+# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option)
+
+.DS_Store
+*.db
+
+.vscode
\ No newline at end of file
diff --git a/GeneticAlgo.AvaloniaInterface/.gitignore b/GeneticAlgo.AvaloniaInterface/.gitignore
new file mode 100644
index 0000000..8afdcb6
--- /dev/null
+++ b/GeneticAlgo.AvaloniaInterface/.gitignore
@@ -0,0 +1,454 @@
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# Tye
+.tye/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+##
+## Visual studio for Mac
+##
+
+
+# globs
+Makefile.in
+*.userprefs
+*.usertasks
+config.make
+config.status
+aclocal.m4
+install-sh
+autom4te.cache/
+*.tar.gz
+tarballs/
+test-results/
+
+# Mac bundle stuff
+*.dmg
+*.app
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
+
+# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore
+# Windows thumbnail cache files
+Thumbs.db
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
+
+# JetBrains Rider
+.idea/
+*.sln.iml
+
+##
+## Visual Studio Code
+##
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
diff --git a/GeneticAlgo.AvaloniaInterface/App.axaml b/GeneticAlgo.AvaloniaInterface/App.axaml
new file mode 100644
index 0000000..565ac22
--- /dev/null
+++ b/GeneticAlgo.AvaloniaInterface/App.axaml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/GeneticAlgo.AvaloniaInterface/App.axaml.cs b/GeneticAlgo.AvaloniaInterface/App.axaml.cs
new file mode 100644
index 0000000..4a5870e
--- /dev/null
+++ b/GeneticAlgo.AvaloniaInterface/App.axaml.cs
@@ -0,0 +1,43 @@
+using System;
+using Avalonia;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Markup.Xaml;
+using GeneticAlgo.AvaloniaInterface.ViewModels;
+using GeneticAlgo.Shared;
+using GeneticAlgo.Shared.Models;
+using GeneticAlgo.Shared.Tools;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace GeneticAlgo.AvaloniaInterface
+{
+ public partial class App : Application
+ {
+ public override void Initialize()
+ {
+ AvaloniaXamlLoader.Load(this);
+ }
+
+ public override void OnFrameworkInitializationCompleted()
+ {
+ if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+ {
+ const int maximum = 2;
+ var settings = Settings.GetInstance();
+
+ var collection = new ServiceCollection();
+ collection.AddSingleton();
+ collection.AddSingleton(_ => Settings.Dummy);
+ collection.AddSingleton(new ExecutionConfiguration(TimeSpan.FromMilliseconds(1), maximum, -maximum));
+
+ var provider = collection.BuildServiceProvider();
+
+ desktop.MainWindow = new MainWindow
+ {
+ DataContext = provider.GetRequiredService(),
+ };
+ }
+
+ base.OnFrameworkInitializationCompleted();
+ }
+ }
+}
\ No newline at end of file
diff --git a/GeneticAlgo.AvaloniaInterface/GeneticAlgo.AvaloniaInterface.csproj b/GeneticAlgo.AvaloniaInterface/GeneticAlgo.AvaloniaInterface.csproj
new file mode 100644
index 0000000..a26a23a
--- /dev/null
+++ b/GeneticAlgo.AvaloniaInterface/GeneticAlgo.AvaloniaInterface.csproj
@@ -0,0 +1,32 @@
+
+
+ WinExe
+ net6.0
+ enable
+
+ copyused
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/GeneticAlgo.AvaloniaInterface/MainWindow.axaml b/GeneticAlgo.AvaloniaInterface/MainWindow.axaml
new file mode 100644
index 0000000..ea9ed6b
--- /dev/null
+++ b/GeneticAlgo.AvaloniaInterface/MainWindow.axaml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/GeneticAlgo.AvaloniaInterface/MainWindow.axaml.cs b/GeneticAlgo.AvaloniaInterface/MainWindow.axaml.cs
new file mode 100644
index 0000000..e0b7e3c
--- /dev/null
+++ b/GeneticAlgo.AvaloniaInterface/MainWindow.axaml.cs
@@ -0,0 +1,26 @@
+using Avalonia.Controls;
+using Avalonia.Interactivity;
+using GeneticAlgo.AvaloniaInterface.ViewModels;
+
+namespace GeneticAlgo.AvaloniaInterface
+{
+ public partial class MainWindow : Window
+ {
+ public MainWindow()
+ {
+ InitializeComponent();
+ }
+
+ public MainWindowViewModel ViewModel => (MainWindowViewModel)DataContext!;
+
+ private async void Run_OnClick(object? sender, RoutedEventArgs e)
+ {
+ await ViewModel.RunAsync();
+ }
+
+ private void Stop_OnClick(object? sender, RoutedEventArgs e)
+ {
+ ViewModel.Stop();
+ }
+ }
+}
\ No newline at end of file
diff --git a/GeneticAlgo.AvaloniaInterface/Program.cs b/GeneticAlgo.AvaloniaInterface/Program.cs
new file mode 100644
index 0000000..f0dc960
--- /dev/null
+++ b/GeneticAlgo.AvaloniaInterface/Program.cs
@@ -0,0 +1,21 @@
+using System;
+using Avalonia;
+
+namespace GeneticAlgo.AvaloniaInterface
+{
+ class Program
+ {
+ // Initialization code. Don't use any Avalonia, third-party APIs or any
+ // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
+ // yet and stuff might break.
+ [STAThread]
+ public static void Main(string[] args) => BuildAvaloniaApp()
+ .StartWithClassicDesktopLifetime(args);
+
+ // Avalonia configuration, don't remove; also used by visual designer.
+ public static AppBuilder BuildAvaloniaApp()
+ => AppBuilder.Configure()
+ .UsePlatformDetect()
+ .LogToTrace();
+ }
+}
\ No newline at end of file
diff --git a/GeneticAlgo.AvaloniaInterface/ViewModels/MainWindowViewModel.cs b/GeneticAlgo.AvaloniaInterface/ViewModels/MainWindowViewModel.cs
new file mode 100644
index 0000000..e73016f
--- /dev/null
+++ b/GeneticAlgo.AvaloniaInterface/ViewModels/MainWindowViewModel.cs
@@ -0,0 +1,125 @@
+using System.Linq;
+using System.Threading.Tasks;
+using Avalonia;
+using GeneticAlgo.Shared;
+using GeneticAlgo.Shared.Models;
+using GeneticAlgo.UIShared;
+using OxyPlot;
+using OxyPlot.Series;
+using Serilog;
+
+namespace GeneticAlgo.AvaloniaInterface.ViewModels;
+
+public class MainWindowViewModel : AvaloniaObject
+{
+ private readonly IStatisticsConsumer _statisticsConsumer;
+ private readonly IExecutionContext _executionContext;
+ private readonly ExecutionConfiguration _configuration;
+ private readonly BarrierCircle[] _circles;
+
+ public MainWindowViewModel(
+ IExecutionContext executionContext,
+ ExecutionConfiguration configuration)
+ {
+ Logger.Init();
+ _executionContext = executionContext;
+ _configuration = configuration;
+ _circles = _executionContext.GetCircles();
+
+ IsRunning = AvaloniaProperty
+ .RegisterAttached(nameof(IsRunning), typeof(MainWindowViewModel));
+
+ var lineSeries = new ScatterSeries
+ {
+ MarkerSize = 1,
+ MarkerStroke = OxyColors.ForestGreen,
+ MarkerType = MarkerType.Circle,
+ };
+
+ var goalSeries = new ScatterSeries
+ {
+ MarkerSize = 3,
+ MarkerStroke = OxyColors.Blue,
+ MarkerType = MarkerType.Circle,
+ };
+
+ var bestDotSeries = new ScatterSeries
+ {
+ MarkerSize = 2,
+ MarkerStroke = OxyColors.Violet,
+ MarkerType = MarkerType.Circle,
+ };
+
+ var circleSeries = new ScatterSeries
+ {
+ MarkerFill = OxyColors.Red,
+ MarkerType = MarkerType.Circle,
+ };
+
+ ScatterModel = new PlotModel
+ {
+ Title = "Points",
+ Series = { circleSeries, lineSeries, goalSeries, bestDotSeries },
+ };
+
+ var barSeries = new LinearBarSeries
+ {
+ DataFieldX = nameof(FitnessModel.X),
+ DataFieldY = nameof(FitnessModel.Y),
+ };
+
+ BarModel = new PlotModel
+ {
+ Title = "Fitness",
+ Series = { barSeries },
+ };
+
+ _statisticsConsumer = new PlotStatisticConsumer(circleSeries, lineSeries, barSeries, goalSeries, bestDotSeries);
+ }
+
+ public PlotModel ScatterModel { get; }
+ public PlotModel BarModel { get; }
+
+ public AttachedProperty IsRunning { get; }
+
+ public async Task RunAsync()
+ {
+ foreach (var series in ScatterModel.Series.OfType())
+ {
+ series.XAxis.Maximum = _configuration.MaximumValue;
+ series.XAxis.Minimum = _configuration.MinimumValue;
+ series.YAxis.Maximum = _configuration.MaximumValue;
+ series.YAxis.Minimum = _configuration.MinimumValue;
+ }
+
+ foreach (var series in BarModel.Series.OfType())
+ {
+ series.XAxis.Maximum = _executionContext.PointsCount();
+ series.XAxis.Minimum = 0;
+ series.YAxis.Maximum = 30;
+ series.YAxis.Minimum = 0;
+ }
+
+ SetValue(IsRunning, true);
+ _executionContext.Reset();
+
+ IterationResult iterationResult;
+
+ do
+ {
+ iterationResult = await _executionContext.ExecuteIterationAsync();
+ _executionContext.ReportStatistics(_statisticsConsumer, _circles);
+
+ ScatterModel.InvalidatePlot(true);
+ BarModel.InvalidatePlot(true);
+
+ await Task.Delay(_configuration.IterationDelay);
+ }
+ while (GetValue(IsRunning));
+ }
+
+ public void Stop()
+ {
+ SetValue(IsRunning, false);
+ }
+}
\ No newline at end of file
diff --git a/GeneticAlgo.Core/GeneticAlgo.Core.csproj b/GeneticAlgo.Core/GeneticAlgo.Core.csproj
new file mode 100644
index 0000000..9edd8f4
--- /dev/null
+++ b/GeneticAlgo.Core/GeneticAlgo.Core.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/GeneticAlgo.MemoryTest/GeneticAlgo.MemoryTest.csproj b/GeneticAlgo.MemoryTest/GeneticAlgo.MemoryTest.csproj
new file mode 100644
index 0000000..91e9de2
--- /dev/null
+++ b/GeneticAlgo.MemoryTest/GeneticAlgo.MemoryTest.csproj
@@ -0,0 +1,16 @@
+
+
+
+ Exe
+ net6.0
+ enable
+ enable
+ GeneticAlgo.ConsolePlayground
+
+
+
+
+
+
+
+
diff --git a/GeneticAlgo.MemoryTest/Program.cs b/GeneticAlgo.MemoryTest/Program.cs
new file mode 100644
index 0000000..429e8b2
--- /dev/null
+++ b/GeneticAlgo.MemoryTest/Program.cs
@@ -0,0 +1,22 @@
+using System.Numerics;
+using System.Text.Json;
+using GeneticAlgo.Shared.Entities;
+using GeneticAlgo.Shared.Models;
+
+namespace GeneticAlgo.MemoryTest;
+
+public class Program
+{
+ public static void Main(string[] args)
+ {
+ var execution = new Execution(4, 4, 1000, 500);
+ while (true)
+ {
+ execution.ExecuteIteration();
+ if (execution.Population.AllDead())
+ {
+ execution.ExecuteIfDead();
+ }
+ }
+ }
+}
diff --git a/GeneticAlgo.Shared/Entities/Brain.cs b/GeneticAlgo.Shared/Entities/Brain.cs
new file mode 100644
index 0000000..59f8f5c
--- /dev/null
+++ b/GeneticAlgo.Shared/Entities/Brain.cs
@@ -0,0 +1,54 @@
+using System.Buffers;
+using System.Numerics;
+
+namespace GeneticAlgo.Shared.Entities;
+
+public class Brain
+{
+ public Vector2[] Directions;
+ public int Step;
+ public double MutateChance;
+
+ public Brain(int size)
+ {
+ Directions = ArrayPool.Shared.Rent(size);
+ Step = 0;
+ MutateChance = 0.025;
+ Randomize();
+ }
+
+ public void Randomize()
+ {
+ for (var i = 0; i < Directions.Length; i++)
+ {
+ var angle = Random.Shared.NextDouble() * 2 * Math.PI;
+ var x = Math.Cos(angle) * 0.005;
+ var y = Math.Sin(angle) * 0.005;
+ Directions[i] = new Vector2((float) x, (float) y);
+ }
+ }
+ public Brain CloneBrain()
+ {
+ Brain clone = new Brain(Directions.Length);
+ for (int i = 0; i < Directions.Length; i++)
+ clone.Directions[i] = Directions[i];
+ return clone;
+ }
+ public void Mutate()
+ {
+ for (var i = 0; i < Directions.Length; i++)
+ {
+ var rand = Random.Shared.NextDouble();
+ if (rand > MutateChance) continue;
+ var angle = Random.Shared.NextDouble() * 2 * Math.PI;
+ var x = Math.Cos(angle) * 0.005;
+ var y = Math.Sin(angle) * 0.005;
+ Directions[i] = new Vector2((float) x, (float) y);
+ }
+ }
+
+ public void Clear()
+ {
+ ArrayPool.Shared.Return(Directions);
+ }
+}
\ No newline at end of file
diff --git a/GeneticAlgo.Shared/Entities/Dot.cs b/GeneticAlgo.Shared/Entities/Dot.cs
new file mode 100644
index 0000000..31195a7
--- /dev/null
+++ b/GeneticAlgo.Shared/Entities/Dot.cs
@@ -0,0 +1,117 @@
+using System.Buffers;
+using System.Numerics;
+using System.Text.Json;
+
+namespace GeneticAlgo.Shared.Entities;
+
+public class Dot
+{
+ public Vector2 Position;
+ public Vector2 Speed;
+ public Vector2 Acceleration;
+ public Brain Brain;
+ public bool IsDead;
+ public bool IsReached;
+ public bool IsBest;
+ public bool IsSlow;
+ public double Fitness;
+
+ public Dot()
+ {
+ Brain = new Brain(Settings.StepsCount);
+ IsDead = false;
+ IsReached = false;
+ IsBest = false;
+ IsSlow = false;
+ Fitness = 0.0;
+ Position = new Vector2(0.0f, 0.0f);
+ Speed = new Vector2(0.0f, 0.0f);
+ Acceleration = new Vector2(0.0f, 0.0f);
+ }
+
+ public void Move()
+ {
+ if (Brain.Step < Brain.Directions.Length)
+ {
+ Acceleration = Brain.Directions[Brain.Step];
+ Brain.Step++;
+ }
+ else
+ {
+ IsDead = true;
+ IsSlow = true;
+ }
+
+ var newVec = new Vector2(Speed.X + Acceleration.X, Speed.Y + Acceleration.Y);
+ if (newVec.Length() >= Settings.LimitSpeed)
+ {
+ Speed.X %= (float) Settings.LimitSpeed;
+ Speed.Y %= (float) Settings.LimitSpeed;
+
+ }
+
+ Speed.X += Acceleration.X;
+ Speed.Y += Acceleration.Y;
+ Position.X += Speed.X;
+ Position.Y += Speed.Y;
+ }
+
+ public void NextIteration(double width, double height)
+ {
+ if (!IsDead && !IsReached)
+ {
+ Move();
+ double distX = Position.X - Settings.Goal.X;
+ double distY = Position.Y - Settings.Goal.Y;
+ double dist = Math.Sqrt(distX * distX + distY * distY);
+ if (Position.X > width / 2 || Position.Y > height / 2 || Position.X < -width / 2 ||
+ Position.Y < -height / 2 || IsBumped())
+ IsDead = true;
+ else if (dist < 0.025)
+ IsReached = true;
+ }
+ }
+
+ public Dot GetBaby()
+ {
+ Dot baby = new Dot();
+ baby.Brain = Brain.CloneBrain();
+ return baby;
+ }
+ public bool IsBumped()
+ {
+ var barriers = Settings.Barriers;
+ foreach (var barrier in barriers)
+ {
+ var radius = barrier.Radius / 155;
+ var distX = barrier.Center.X - Position.X;
+ var distY = barrier.Center.Y - Position.Y;
+ if (Math.Sqrt(distX * distX + distY * distY) > radius) continue;
+ return true;
+ }
+
+ return false;
+ }
+
+ public void CalculateFitness()
+ {
+ if (IsReached)
+ Fitness = 50000.0 / (Brain.Step * Brain.Step);
+ else if (!IsSlow)
+ {
+ double distX = Position.X - Settings.Goal.X;
+ double distY = Position.Y - Settings.Goal.Y;
+ double dist = Math.Sqrt(distX * distX + distY * distY);
+ Fitness = 0.1 / (dist * dist);
+ }
+ else
+ {
+ Fitness = 0.0;
+ }
+ }
+
+ public void Clear()
+ {
+ Brain.Clear();
+ }
+}
\ No newline at end of file
diff --git a/GeneticAlgo.Shared/Entities/Execution.cs b/GeneticAlgo.Shared/Entities/Execution.cs
new file mode 100644
index 0000000..d8e03b0
--- /dev/null
+++ b/GeneticAlgo.Shared/Entities/Execution.cs
@@ -0,0 +1,30 @@
+using System.Numerics;
+using System.Reflection.Metadata.Ecma335;
+
+namespace GeneticAlgo.Shared.Entities;
+public class Execution
+{
+ public Population Population;
+ public double Width;
+ public double Height;
+
+ public Execution(double width, double height, int size, int minStep)
+ {
+ Width = width;
+ Height = height;
+ Population = new Population(minStep, size);
+ }
+ public void ExecuteIfDead()
+ {
+ Population.NextGeneration();
+ Population.MutateBabies();
+ }
+ public void ExecuteIteration()
+ {
+ if (!Population.AllDead())
+ {
+ Population.NextIteration(Width, Height);
+ Population.CalculateFitness();
+ }
+ }
+}
\ No newline at end of file
diff --git a/GeneticAlgo.Shared/Entities/Population.cs b/GeneticAlgo.Shared/Entities/Population.cs
new file mode 100644
index 0000000..1fb4a9c
--- /dev/null
+++ b/GeneticAlgo.Shared/Entities/Population.cs
@@ -0,0 +1,133 @@
+using System.Buffers;
+using System.Numerics;
+using Serilog;
+
+namespace GeneticAlgo.Shared.Entities;
+
+public class Population
+{
+ public int Gen = 1;
+ public double FitnessSum;
+ public Dot[] Dots;
+ public int BestDot;
+ public int MinStep;
+
+ public Population(int minStep, int dotsCount)
+ {
+ BestDot = 0;
+ MinStep = minStep;
+ Dots = new Dot[dotsCount];
+ for (int i = 0; i < Dots.Length; i++)
+ Dots[i] = new Dot();
+ Logger.Init();
+ }
+
+ public void NextIteration(double width, double height)
+ {
+ for (int i = 0; i < Dots.Length; i++)
+ {
+ if (Dots[i].Brain.Step > MinStep + 200)
+ {
+ Dots[i].IsDead = true;
+ Dots[i].IsSlow = true;
+ }
+ else
+ {
+ Dots[i].NextIteration(width, height);
+ }
+ }
+ }
+
+ public void CalculateFitness()
+ {
+ for (int i = 0; i < Dots.Length; i++)
+ {
+ Dots[i].CalculateFitness();
+ }
+ }
+
+ public bool AllDead()
+ {
+ for (int i = 0; i < Dots.Length; i++) {
+ if (!Dots[i].IsDead && !Dots[i].IsReached) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public void NextGeneration()
+ {
+ var newDots = new Dot[Dots.Length];
+ SetBestDot();
+ CalculateFitnessSum();
+
+ newDots[0] = Dots[BestDot].GetBaby();
+ newDots[0].IsBest = true;
+ for (int i = 1; i < newDots.Length; i++)
+ {
+ var parent = SelectParent();
+ var baby = parent.GetBaby();
+ newDots[i] = baby;
+ }
+
+ for (int i = 0; i < newDots.Length; i++)
+ {
+ Dots[i].Clear();
+ }
+ Dots = newDots;
+ Gen++;
+ }
+
+ public void CalculateFitnessSum()
+ {
+ FitnessSum = 0;
+ for (int i = 0; i < Dots.Length; i++) {
+ FitnessSum += Dots[i].Fitness;
+ }
+ }
+
+ public Dot SelectParent()
+ {
+ var rand = Random.Shared.NextDouble() * FitnessSum;
+ double runningSum = 0;
+ for (int i = 0; i < Dots.Length; i++)
+ {
+ runningSum += Dots[i].Fitness;
+ if (runningSum > rand)
+ return Dots[i];
+ }
+
+ return null;
+ }
+
+ public void MutateBabies()
+ {
+ for (int i = 1; i< Dots.Length; i++)
+ Dots[i].Brain.Mutate();
+ }
+
+ public void SetBestDot()
+ {
+ double max = 0;
+ int maxIndex = 0;
+ for (int i = 0; i < Dots.Length; i++)
+ {
+ if (Dots[i].Fitness > max)
+ {
+ max = Dots[i].Fitness;
+ maxIndex = i;
+ }
+ }
+
+ BestDot = maxIndex;
+
+ if (Dots[BestDot].IsReached)
+ {
+ MinStep = Dots[BestDot].Brain.Step;
+ //Log.Information("Steps: {0} \n Fitness: {1} number of best: {2}", MinStep, Dots[_bestDot].Fitness, _bestDot);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/GeneticAlgo.Shared/GeneticAlgo.Shared.csproj b/GeneticAlgo.Shared/GeneticAlgo.Shared.csproj
new file mode 100644
index 0000000..bee73b5
--- /dev/null
+++ b/GeneticAlgo.Shared/GeneticAlgo.Shared.csproj
@@ -0,0 +1,14 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
diff --git a/GeneticAlgo.Shared/IExecutionContext.cs b/GeneticAlgo.Shared/IExecutionContext.cs
new file mode 100644
index 0000000..98c0d11
--- /dev/null
+++ b/GeneticAlgo.Shared/IExecutionContext.cs
@@ -0,0 +1,17 @@
+using GeneticAlgo.Shared.Models;
+
+namespace GeneticAlgo.Shared
+{
+ public interface IExecutionContext
+ {
+ void Reset();
+
+ int GetSize();
+ Task ExecuteIterationAsync();
+
+ BarrierCircle[] GetCircles();
+
+ int PointsCount();
+ void ReportStatistics(IStatisticsConsumer statisticsConsumer, BarrierCircle[] circles);
+ }
+}
\ No newline at end of file
diff --git a/GeneticAlgo.Shared/IStatisticsConsumer.cs b/GeneticAlgo.Shared/IStatisticsConsumer.cs
new file mode 100644
index 0000000..7217166
--- /dev/null
+++ b/GeneticAlgo.Shared/IStatisticsConsumer.cs
@@ -0,0 +1,8 @@
+using GeneticAlgo.Shared.Models;
+
+namespace GeneticAlgo.Shared;
+
+public interface IStatisticsConsumer
+{
+ void Consume(IReadOnlyCollection statistics, IReadOnlyCollection barriers, Point best);
+}
\ No newline at end of file
diff --git a/GeneticAlgo.Shared/Logger.cs b/GeneticAlgo.Shared/Logger.cs
new file mode 100644
index 0000000..9651f3b
--- /dev/null
+++ b/GeneticAlgo.Shared/Logger.cs
@@ -0,0 +1,14 @@
+using Serilog;
+
+namespace GeneticAlgo.Shared;
+
+public class Logger
+{
+ public static void Init()
+ {
+ Log.Logger = new LoggerConfiguration()
+ .MinimumLevel.Debug()
+ .WriteTo.File("gen-algo.log", rollingInterval:RollingInterval.Day)
+ .CreateLogger();
+ }
+}
\ No newline at end of file
diff --git a/GeneticAlgo.Shared/Models/BarrierCircle.cs b/GeneticAlgo.Shared/Models/BarrierCircle.cs
new file mode 100644
index 0000000..6cd01d3
--- /dev/null
+++ b/GeneticAlgo.Shared/Models/BarrierCircle.cs
@@ -0,0 +1,3 @@
+namespace GeneticAlgo.Shared.Models;
+
+public record struct BarrierCircle(Point Center, double Radius);
\ No newline at end of file
diff --git a/GeneticAlgo.Shared/Models/ExecutionConfiguration.cs b/GeneticAlgo.Shared/Models/ExecutionConfiguration.cs
new file mode 100644
index 0000000..d5873d0
--- /dev/null
+++ b/GeneticAlgo.Shared/Models/ExecutionConfiguration.cs
@@ -0,0 +1,3 @@
+namespace GeneticAlgo.Shared.Models;
+
+public record ExecutionConfiguration(TimeSpan IterationDelay, int MaximumValue, int MinimumValue);
\ No newline at end of file
diff --git a/GeneticAlgo.Shared/Models/FitnessModel.cs b/GeneticAlgo.Shared/Models/FitnessModel.cs
new file mode 100644
index 0000000..d9815ed
--- /dev/null
+++ b/GeneticAlgo.Shared/Models/FitnessModel.cs
@@ -0,0 +1,3 @@
+namespace GeneticAlgo.Shared.Models;
+
+public record FitnessModel(int X, double Y);
\ No newline at end of file
diff --git a/GeneticAlgo.Shared/Models/IterationResult.cs b/GeneticAlgo.Shared/Models/IterationResult.cs
new file mode 100644
index 0000000..80ea145
--- /dev/null
+++ b/GeneticAlgo.Shared/Models/IterationResult.cs
@@ -0,0 +1,8 @@
+namespace GeneticAlgo.Shared.Models;
+
+public enum IterationResult
+{
+ SolutionFound = 1,
+ SolutionCannotBeFound,
+ IterationFinished,
+}
\ No newline at end of file
diff --git a/GeneticAlgo.Shared/Models/Point.cs b/GeneticAlgo.Shared/Models/Point.cs
new file mode 100644
index 0000000..fbbad94
--- /dev/null
+++ b/GeneticAlgo.Shared/Models/Point.cs
@@ -0,0 +1,3 @@
+namespace GeneticAlgo.Shared.Models;
+
+public record Point(double X, double Y);
\ No newline at end of file
diff --git a/GeneticAlgo.Shared/Models/Statistic.cs b/GeneticAlgo.Shared/Models/Statistic.cs
new file mode 100644
index 0000000..6331f45
--- /dev/null
+++ b/GeneticAlgo.Shared/Models/Statistic.cs
@@ -0,0 +1,3 @@
+namespace GeneticAlgo.Shared.Models;
+
+public record struct Statistic(int Id, Point Point, double Fitness);
\ No newline at end of file
diff --git a/GeneticAlgo.Shared/Settings.cs b/GeneticAlgo.Shared/Settings.cs
new file mode 100644
index 0000000..a26631b
--- /dev/null
+++ b/GeneticAlgo.Shared/Settings.cs
@@ -0,0 +1,33 @@
+using System.Buffers;
+using System.Numerics;
+using System.Text.Json;
+using GeneticAlgo.Shared.Models;
+using GeneticAlgo.Shared.Tools;
+
+namespace GeneticAlgo.Shared;
+
+public class Settings
+{
+ private static Settings? _instance = null;
+ public static readonly Vector2 Goal = new((float) 1.0, (float) 1.0);
+ public static readonly double LimitSpeed = 0.03;
+ public static readonly int StepsCount = 400;
+ public static readonly IExecutionContext Dummy = new DummyExecutionContext(200, 1, 3);
+ public static readonly BarrierCircle[] Barriers = Dummy.GetCircles();
+ public static readonly ArrayPool Pool = ArrayPool.Create(StepsCount, Dummy.GetSize());
+
+ private Settings()
+ {
+
+ }
+
+ public static Settings GetInstance()
+ {
+ if (_instance is null)
+ {
+ _instance = new Settings();
+ }
+
+ return _instance;
+ }
+}
\ No newline at end of file
diff --git a/GeneticAlgo.Shared/Tools/DummyExecutionContext.cs b/GeneticAlgo.Shared/Tools/DummyExecutionContext.cs
new file mode 100644
index 0000000..ea05daa
--- /dev/null
+++ b/GeneticAlgo.Shared/Tools/DummyExecutionContext.cs
@@ -0,0 +1,105 @@
+using System.Numerics;
+using System.Text.Json;
+using GeneticAlgo.Shared.Entities;
+using GeneticAlgo.Shared.Models;
+using Serilog;
+
+namespace GeneticAlgo.Shared.Tools;
+
+public class DummyExecutionContext : IExecutionContext
+{
+ private readonly int _circleCount;
+ private readonly int _size;
+ private readonly int _maximumValue;
+ private readonly Vector2 _goal;
+ private readonly Execution _execution;
+ private Dot BestDot;
+ private readonly BarrierCircle[] _circles;
+
+ public DummyExecutionContext(int size, int maximumValue, int circleCount)
+ {
+ _size = size;
+ _maximumValue = maximumValue;
+ _circleCount = circleCount;
+ _goal = new Vector2((float) 1.0, (float) 1.0);
+ _circles = ReportCircles();
+ _execution = new Execution(4, 4, _size, 500);
+ BestDot = new Dot();
+ Logger.Init();
+ }
+
+ private double NextPosition => Random.Shared.NextDouble() * _maximumValue;
+ private double NextRadius => 0.3 + Random.Shared.NextDouble() * _maximumValue * 2;
+
+ public void Reset() { }
+
+ public int GetSize()
+ {
+ return _size;
+ }
+ public Task ExecuteIterationAsync()
+ {
+ return Task.FromResult(IterationResult.IterationFinished);
+ }
+
+ public BarrierCircle[] GetCircles()
+ {
+ return _circles;
+ }
+
+ public int PointsCount()
+ {
+ return _execution.Population.Dots.Length;
+ }
+ public BarrierCircle[] ReportCircles()
+ {
+ var circles = new BarrierCircle[_circleCount];
+ for (int i = 0; i < _circleCount; i++)
+ {
+ var positionX = NextPosition;
+ var positionY = NextPosition;
+ var radius = NextRadius;
+ while (Math.Sqrt(positionX * positionX + positionY * positionY) < radius ||
+ Math.Sqrt((positionX - _goal.X) * (positionX - _goal.X) +
+ (positionY - _goal.Y) * (positionY - _goal.Y)) < radius)
+ {
+ positionX = NextPosition;
+ positionY = NextPosition;
+ radius = NextRadius;
+ }
+
+ circles[i] = new BarrierCircle(new Point(positionX, positionY), 50 * radius);
+ }
+
+ return circles;
+ }
+ public void ReportStatistics(IStatisticsConsumer statisticsConsumer, BarrierCircle[] circles)
+ {
+ _execution.ExecuteIteration();
+ Statistic[] statistics = Enumerable.Range(0, _execution.Population.Dots.Length)
+ .Select(i => new Statistic(i,
+ new Point(_execution.Population.Dots[i].Position.X, _execution.Population.Dots[i].Position.Y)
+ ,_execution.Population.Dots[i].Fitness))
+ .ToArray();
+
+ if (_execution.Population.Gen == 1)
+ {
+ BestDot.Position.X = -10;
+ BestDot.Position.Y = -10;
+ }
+ //Log.Information("Best: {0} {1}", best.Position.X, best.Position.Y);
+ statisticsConsumer.Consume(statistics, circles, new Point(BestDot.Position.X, BestDot.Position.Y));
+
+ /*for (int i = 0; i < _execution.Population.Dots.Length; i++)
+ {
+ Log.Information("Fitness: {0} \n Steps: {1}", _execution.Population.Dots[i].Fitness,
+ _execution.Population.Dots[i].Brain.Step);
+ }*/
+
+ if (_execution.Population.AllDead())
+ {
+ _execution.ExecuteIfDead();
+ BestDot = _execution.Population.Dots.First(x => x.IsBest);
+ }
+ }
+}
\ No newline at end of file
diff --git a/GeneticAlgo.UIShared/GeneticAlgo.UIShared.csproj b/GeneticAlgo.UIShared/GeneticAlgo.UIShared.csproj
new file mode 100644
index 0000000..2b923c6
--- /dev/null
+++ b/GeneticAlgo.UIShared/GeneticAlgo.UIShared.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/GeneticAlgo.UIShared/PlotStatisticConsumer.cs b/GeneticAlgo.UIShared/PlotStatisticConsumer.cs
new file mode 100644
index 0000000..1ffb190
--- /dev/null
+++ b/GeneticAlgo.UIShared/PlotStatisticConsumer.cs
@@ -0,0 +1,50 @@
+using GeneticAlgo.Shared;
+using GeneticAlgo.Shared.Models;
+using OxyPlot.Series;
+
+namespace GeneticAlgo.UIShared;
+
+public class PlotStatisticConsumer : IStatisticsConsumer
+{
+ private readonly ScatterSeries _circleSeries;
+ private readonly ScatterSeries _scatterSeries;
+ private readonly LinearBarSeries _linearBarSeries;
+ private readonly ScatterSeries _goalSeries;
+ private readonly ScatterSeries _bestDotSeries;
+
+ public PlotStatisticConsumer(ScatterSeries circleSeries, ScatterSeries scatterSeries,
+ LinearBarSeries linearBarSeries, ScatterSeries goalSeries, ScatterSeries bestDotSeries)
+ {
+ _scatterSeries = scatterSeries;
+ _linearBarSeries = linearBarSeries;
+ _circleSeries = circleSeries;
+ _goalSeries = goalSeries;
+ _bestDotSeries = bestDotSeries;
+ }
+
+ public void Consume(IReadOnlyCollection statistics, IReadOnlyCollection barriers, Point best)
+ {
+ _scatterSeries.Points.Clear();
+
+ foreach (var statistic in statistics)
+ {
+ var point = statistic.Point;
+ _scatterSeries.Points.Add(new ScatterPoint(point.X, point.Y));
+ }
+
+ _goalSeries.Points.Clear();
+ _goalSeries.Points.Add(new ScatterPoint(1, 1));
+ _bestDotSeries.Points.Clear();
+ _bestDotSeries.Points.Add(new ScatterPoint(best.X, best.Y));
+ _circleSeries.Points.Clear();
+
+ foreach (var (point, radius) in barriers)
+ {
+ _circleSeries.Points.Add(new ScatterPoint(point.X, point.Y, radius));
+ }
+
+ _linearBarSeries.ItemsSource = statistics
+ .Select(s => new FitnessModel(s.Id, s.Fitness))
+ .ToArray();
+ }
+}
\ No newline at end of file
diff --git a/GeneticAlgo.sln b/GeneticAlgo.sln
new file mode 100644
index 0000000..3e24334
--- /dev/null
+++ b/GeneticAlgo.sln
@@ -0,0 +1,49 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.1.32328.378
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeneticAlgo.Core", "GeneticAlgo.Core\GeneticAlgo.Core.csproj", "{294B2B1A-89E7-4B91-8927-71334C454A81}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeneticAlgo.MemoryTest", "GeneticAlgo.MemoryTest\GeneticAlgo.MemoryTest.csproj", "{8FC52BCD-7965-462A-B4E8-41C9894D4E7E}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeneticAlgo.Shared", "GeneticAlgo.Shared\GeneticAlgo.Shared.csproj", "{CB0B8678-232B-40BD-B0C5-41526D94C95C}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeneticAlgo.AvaloniaInterface", "GeneticAlgo.AvaloniaInterface\GeneticAlgo.AvaloniaInterface.csproj", "{7695D1B6-C0CD-4C03-B6F8-6654B3812A9B}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeneticAlgo.UIShared", "GeneticAlgo.UIShared\GeneticAlgo.UIShared.csproj", "{5274AD9E-1208-4E52-A1B6-EF83CB824B5D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {294B2B1A-89E7-4B91-8927-71334C454A81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {294B2B1A-89E7-4B91-8927-71334C454A81}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {294B2B1A-89E7-4B91-8927-71334C454A81}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {294B2B1A-89E7-4B91-8927-71334C454A81}.Release|Any CPU.Build.0 = Release|Any CPU
+ {8FC52BCD-7965-462A-B4E8-41C9894D4E7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {8FC52BCD-7965-462A-B4E8-41C9894D4E7E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {8FC52BCD-7965-462A-B4E8-41C9894D4E7E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {8FC52BCD-7965-462A-B4E8-41C9894D4E7E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CB0B8678-232B-40BD-B0C5-41526D94C95C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CB0B8678-232B-40BD-B0C5-41526D94C95C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CB0B8678-232B-40BD-B0C5-41526D94C95C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CB0B8678-232B-40BD-B0C5-41526D94C95C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7695D1B6-C0CD-4C03-B6F8-6654B3812A9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7695D1B6-C0CD-4C03-B6F8-6654B3812A9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7695D1B6-C0CD-4C03-B6F8-6654B3812A9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7695D1B6-C0CD-4C03-B6F8-6654B3812A9B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5274AD9E-1208-4E52-A1B6-EF83CB824B5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5274AD9E-1208-4E52-A1B6-EF83CB824B5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5274AD9E-1208-4E52-A1B6-EF83CB824B5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5274AD9E-1208-4E52-A1B6-EF83CB824B5D}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {3A628698-86DE-4920-896A-0C4CCA08CC77}
+ EndGlobalSection
+EndGlobal
diff --git a/TechLab4.md b/TechLab4.md
new file mode 100644
index 0000000..994f14d
--- /dev/null
+++ b/TechLab4.md
@@ -0,0 +1,102 @@
+# Лабораторная 4
+## Point 1
+### Задание
+Есть материальная точка, находящаяся в (0,0). Её нужно за минимальное количество шагов дойти до точки (1,1).\
+При этом есть n-ое количество кругов - препятствий, сталкиваясь с которыми точка прекращает своё движение. Параметры этих кругов мы задаём сами.
+### Решение
+#### Движение
+Для начала разберём, как наша точка движется. У неё есть параметры: позиция, скорость и ускорение, которые, для удобства, задаются векторами.\
+Общий план таков:\
+К вектору скорости точки прибавляется вектор ускорения, а затем вектор скорости прибавляется к вектору позиции точки. Этим и определяется следующая через условное dt её позиция.\
+Это и есть ген - действие ускорения в i-ый момент времени. А соответственно хромосома - набор таких ускорений, то есть весь путь точки до тех пор, пока она не окажется у цели, не врежется в края или препятствия, или не сделает слишком много шагов.
+
+Теперь немного про реализацию:\
+У каждой точки есть свой "мозг", в котором случайным образом задаётся какое-то k-ое количество направлений ускорений, которые будут приложены к точке по порядку, то есть определит её хромосому.\
+В моей реализации "случайным образом" значит, что задаётся рандомный угол (0, 2$\pi$), и по этому углу определяется вектор ускорения, причём фиксированной длины.
+
+
+
+Также у скорости есть предел. Если этот предел превышен, то координаты вектора берутся по модулю этого предела, тем самым мы не даём точке двигаться слишком быстро, что облегчает её путь обучения, потому что при большой скорости точке трудно попасть в цель.
+
+#### Фитнесс функция
+Зададим фитнесс функцию - проще говоря, величину награды точке за её путь. Соответственно чем оптимальнее путь, тем больше у точки фитнесс функция.\
+Один из вариантов задать фитнесс функцию такой:
+```cs
+if (IsReached)
+ Fitness = 50000.0 / (Brain.Step * Brain.Step);
+else if (!IsSlow)
+{
+ double distX = Position.X - Goal.X;
+ double distY = Position.Y - Goal.Y;
+ double dist = Math.Sqrt(distX * distX + distY * distY);
+ Fitness = 0.1 / (dist * dist);
+}
+else
+{
+ Fitness = 0.0;
+}
+```
+Другими словами, если точка дошла до цели, то её награда будет гораздо больше, чем у точки, которая до цели не дошла (отсюда такая большая константа 50000).\
+Причём если точка дошла до цели, то её фитнесс функция будет зависеть от количества шагов, за которые она сделала до того как придти к цели: чем меньше шагов, тем больше фитнесс функция.\
+А если точка не дошла, а врезалась в край/препятствие, то её фитнесс функция будет зависить от расстояния до цели.\
+А если же точка сделала слишком много шагов, то её фитнесс функция будет равна 0 (это введено из-за того, что появилась проблема с тем, когда точка дошла до лимита шагов прям около цели и её фитнесс функция могла стать даже больше, чем у точки, которая дошла до цели, соответственно следующие поколения учились бы неправильно).
+
+#### Поколение
+Теперь определим, как точки, грубо говоря, наследуются друг от друга. После того, как все точки этого поколения остановились, для каждой новой точки следующего поколения определяется родитель, чей путь она повторит (чей "мозг" она скопирует).\
+Родитель точки определяется следующим образом:\
+В конце каждого поколения значения фитнесс функций всех точек суммируются, и затем выбирается случайное число от 0 до значения этой суммы. И соответственно на фитнесс функцию какой точки это число попадёт, та точка и будет родителем данной.
+
+
+
+Нетрудно заметить, что чем больше у какой-то определённой точки фитнесс функция, тем больше у неё вероятность стать родителем для любой точки следующего поколения.
+
+#### Улучшение обучения
+Вроде как всё хорошо, однако возникает проблема:\
+Допустим, у нас есть всего одна точка, которая дошла до цели, но сделала это максимально неэффективно. Тогда это приведёт к тому, что эта точка станет родителем для всё большего и большего количества точек следующих поколений.\
+И в итоге наши особи выучатся неправильно, так как задача стоит дойти до цели максимально оптимально.
+
+Для этого у нас будет существовать вероятность мутации генов. Другими словами, у каждого гена хромосомы будет фиксированная вероятность мутировать, то есть поменять направление ускорения. Так, при плохом кейсе, описанном выше, будет существовать вероятность того, что у какой-то точки смутирует один или несколько генов, и она в итоге дойдёт до цели более оптимально.\
+Именно мутация генов является ключом к оптимальности решения.
+
+_Идея_: https://www.youtube.com/watch?v=BOZfhUcNiqk&t=0s
+## Point 2
+### Метрики
+Соберём метрики и посмотрим, сколько памяти выделяется во время прогонки алгоритма на 1000 точках:
+
+
+
+
+
+
+
+### Предполагаемые проблемы
+Если посмотреть внутрь метрик, то можно заметить, что основная проблема с памятью появляется в этом фрагменте кода:
+```cs
+public Brain(int size)
+{
+ Directions = new Vector2[size];
+ Step = 0;
+ MutateChance = 0.025;
+ Randomize();
+}
+```
+То есть больше всего памяти выделяется при создании массива векторов в "мозге" каждой точке.
+## Point 3
+### Решение проблем
+Одним из решений проблем является не генерировать каждый раз массив и выделять память под него, а перезаполнять старые массивы. То есть условно "мозг", генерируя набор ускорений, перезаполняется. Для этого можно использовать ArrayPool: в конструкторе "мозга" доставать массив из пула, а в конце нового поколения - возвращать в пул "мозг" каждлй точки. Возвращаясь к фрагменту кода выше, мы можем переписать его вот так:
+```cs
+public Brain(int size)
+{
+ Directions = ArrayPool.Shared.Rent(size);
+ Step = 0;
+ MutateChance = 0.025;
+ Randomize();
+}
+```
+### Новые метрики
+
+
+
+
+
+