diff --git a/.gitattributes b/.gitattributes index 1ff0c42..5b65514 100644 --- a/.gitattributes +++ b/.gitattributes @@ -2,6 +2,7 @@ # Set default behavior to automatically normalize line endings. ############################################################################### * text=auto +*.yml text eol=lf ############################################################################### # Set default behavior for command prompt diff. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..2328cee --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,21 @@ +name: CI + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - name: Setup .NET + uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5 + with: + dotnet-version: 8.0.x + - name: Restore + run: dotnet restore SimpleML.GeneticAlgorithm/SimpleML.GeneticAlgorithm.csproj + - name: Build + run: dotnet build SimpleML.GeneticAlgorithm/SimpleML.GeneticAlgorithm.csproj --no-restore diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..da38c3e --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,32 @@ +name: Publish + +on: + push: + tags: + - 'v*' + +permissions: + id-token: write + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + - name: Setup .NET + uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5 + with: + dotnet-version: 8.0.x + - name: Restore + run: dotnet restore SimpleML.GeneticAlgorithm/SimpleML.GeneticAlgorithm.csproj + - name: Build + run: dotnet build SimpleML.GeneticAlgorithm/SimpleML.GeneticAlgorithm.csproj --no-restore -c Release + - name: Pack + run: dotnet pack SimpleML.GeneticAlgorithm/SimpleML.GeneticAlgorithm.csproj --no-build -c Release -o nupkgs + - name: Login to NuGet + uses: NuGet/login@8d196754b4036150537f80ac539e15c2f1028841 # v1 + with: + usernameVar: NUGET_USER + tokenVar: NUGET_TOKEN + - name: Push to NuGet + run: dotnet nuget push nupkgs/*.nupkg --source https://api.nuget.org/v3/index.json --skip-duplicate diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml new file mode 100644 index 0000000..5c5e5b4 --- /dev/null +++ b/.github/workflows/sonar.yml @@ -0,0 +1,46 @@ +name: SonarCloud + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + sonar: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + fetch-depth: 0 + - name: Setup .NET + uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5 + with: + dotnet-version: 8.0.x + - name: Setup Java (required by SonarScanner) + uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4 + with: + distribution: temurin + java-version: 21 + - name: Cache SonarCloud packages + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + with: + path: ~/.sonar/cache + key: ${{ runner.os }}-sonar + - name: Install dotnet-sonarscanner + run: dotnet tool install --global dotnet-sonarscanner + - name: SonarCloud begin + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: | + dotnet sonarscanner begin \ + /k:"PFalkowski_SimpleML" \ + /o:"pfalkowski" \ + /d:sonar.token="$SONAR_TOKEN" \ + /d:sonar.host.url="https://sonarcloud.io" + - name: Build + run: dotnet build SimpleML.GeneticAlgorithm/SimpleML.GeneticAlgorithm.csproj --no-incremental + - name: SonarCloud end + env: + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + run: dotnet sonarscanner end /d:sonar.token="$SONAR_TOKEN" diff --git a/README.md b/README.md index cda4c3d..26d70e9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,57 @@ -# SimpleML +# SimpleML.GeneticAlgorithm -The idea of the project is to implement various popular ML algorithms in a simple yet efficient way, conforming to best patterns and practices of modern OO programming. PR are very welcomed. +[![CI](https://github.com/PFalkowski/SimpleML/actions/workflows/ci.yml/badge.svg)](https://github.com/PFalkowski/SimpleML/actions/workflows/ci.yml) +[![NuGet version](https://img.shields.io/nuget/v/SimpleML.GeneticAlgorithm.svg)](https://www.nuget.org/packages/SimpleML.GeneticAlgorithm/) +[![NuGet downloads](https://img.shields.io/nuget/dt/SimpleML.GeneticAlgorithm.svg)](https://www.nuget.org/packages/SimpleML.GeneticAlgorithm/) +[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=PFalkowski_SimpleML&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=PFalkowski_SimpleML) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://choosealicense.com/licenses/mit/) +[![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-support-yellow.svg)](https://www.buymeacoffee.com/piotrfalkowski) + +A simple, extensible Genetic Algorithm implementation for .NET 8. + +## Install + +```bash +dotnet add package SimpleML.GeneticAlgorithm +``` + +## Usage + +```csharp +// Implement IFitnessFunction for your problem +public class MyFitness : IFitnessFunction +{ + public double Evaluate(Genotype genotype) => /* compute fitness */; + public Task EvaluateAsync(Genotype genotype) => Task.FromResult(Evaluate(genotype)); +} + +// Configure and run +var settings = new GeneticAlgorithmSettings(new MyFitness(), problemSize: 100) +{ + PopulationSize = 5000, + SurvivalRate = 0.1, + MutationRate = 0.05, + StopFunction = new BasicStopFunction { MaxEpochs = 500, MinFitness = 95 } +}; + +var ga = new GeneticAlgorithm(settings); +await ga.Run(); + +Console.WriteLine($"Best fitness: {ga.RunInfo.BestFitnessSoFar}"); +``` + +## Key types + +| Type | Description | +|------|-------------| +| `GeneticAlgorithm` | Orchestrates the evolution loop | +| `GeneticAlgorithmSettings` | Population size, survival/mutation rates, stop condition | +| `Population` | Gene pool management, selection, and breeding | +| `Genotype` | Individual solution encoded as a boolean array | +| `BasicStopFunction` | Stops after max epochs, target fitness, or fitness plateau | +| `EliteSelection` | Keeps the top N organisms | +| `BinaryTournamentSelection` | Random pairwise tournament selection | + +--- + +The idea of the project is to implement various popular ML algorithms in a simple yet efficient way, conforming to best patterns and practices of modern OO programming. PRs are very welcome. diff --git a/SimpleML.GeneticAlgorithm/GeneticAlgorithm.cs b/SimpleML.GeneticAlgorithm/GeneticAlgorithm.cs index a3da94e..20f15b9 100644 --- a/SimpleML.GeneticAlgorithm/GeneticAlgorithm.cs +++ b/SimpleML.GeneticAlgorithm/GeneticAlgorithm.cs @@ -12,7 +12,7 @@ public class GeneticAlgorithm public GeneticAlgorithmSettings Settings { get; protected set; } public IStopFunction StopFunction { get; protected set; } public RunMetadata RunInfo { get; protected set; } = new RunMetadata(); - public ILoggerLite Logger { get; protected set; } + public ILogger? Logger { get; protected set; } public GeneticAlgorithm(GeneticAlgorithmSettings settings) { diff --git a/SimpleML.GeneticAlgorithm/GeneticAlgorithmSettings.cs b/SimpleML.GeneticAlgorithm/GeneticAlgorithmSettings.cs index f024060..b9ef6b6 100644 --- a/SimpleML.GeneticAlgorithm/GeneticAlgorithmSettings.cs +++ b/SimpleML.GeneticAlgorithm/GeneticAlgorithmSettings.cs @@ -25,8 +25,8 @@ public GeneticAlgorithmSettings(IFitnessFunction fitnessFunction, int problemSiz public IStopFunction StopFunction { get; set; } = new BasicStopFunction(); public ISelectionAlgorithm FittestSelectionAlgorithm { get; set; } public IFitnessFunction FitnessFunction { get; protected set; } - public ILoggerLite Logger { get; protected set; } = new ConsoleLogger(); - public FileInfo ContinueFile { get; set; } + public ILogger? Logger { get; protected set; } = new ConsoleLogger(); + public FileInfo? ContinueFile { get; set; } public int MaxDegreeOfParallelism => Math.Min(PopulationSize, 500); } } \ No newline at end of file diff --git a/SimpleML.GeneticAlgorithm/Population.cs b/SimpleML.GeneticAlgorithm/Population.cs index 4cef3b7..795b34d 100644 --- a/SimpleML.GeneticAlgorithm/Population.cs +++ b/SimpleML.GeneticAlgorithm/Population.cs @@ -11,8 +11,8 @@ public class Population private readonly object _syncRoot = new object(); public Random Rng { get; protected set; } - public List GenePool { get; protected set; } - public Genotype BestFit { get; protected set; } + public List GenePool { get; protected set; } = null!; + public Genotype? BestFit { get; protected set; } public IFitnessFunction FitnessFunction { get; protected set; } public ISelectionAlgorithm FittestSelectionAlgorithm { get; protected set; } public GeneticAlgorithmSettings Settings { get; protected set; } diff --git a/SimpleML.GeneticAlgorithm/RunMetadata.cs b/SimpleML.GeneticAlgorithm/RunMetadata.cs index 10f0267..ec00354 100644 --- a/SimpleML.GeneticAlgorithm/RunMetadata.cs +++ b/SimpleML.GeneticAlgorithm/RunMetadata.cs @@ -7,8 +7,8 @@ public class RunMetadata { public ulong Epochs { get; set; } public ulong SimulationsCount { get; set; } - public Genotype CurrentEpochBest { get; set; } - public Genotype BestOverall { get; set; } + public Genotype? CurrentEpochBest { get; set; } + public Genotype? BestOverall { get; set; } public double CurrentFitness => CurrentEpochBest?.Fitness ?? 0; public double BestFitnessSoFar => BestOverall?.Fitness ?? 0; public DateTime StartTime { get; set; } diff --git a/SimpleML.GeneticAlgorithm/SimpleML.GeneticAlgorithm.csproj b/SimpleML.GeneticAlgorithm/SimpleML.GeneticAlgorithm.csproj index f3846e1..972c956 100644 --- a/SimpleML.GeneticAlgorithm/SimpleML.GeneticAlgorithm.csproj +++ b/SimpleML.GeneticAlgorithm/SimpleML.GeneticAlgorithm.csproj @@ -2,26 +2,33 @@ net8.0 - True + latest + enable Piotr Falkowski Simple Genetic Algorithm implementation - Piotr Falkowski © 2023 + Piotr Falkowski © 2026 + MIT https://github.com/PFalkowski/SimpleML https://github.com/PFalkowski/SimpleML git - SimpleML.GeneticAlgorithm - Piotr Falkowski - SimpleML - 4.0.0 - Improved conditions in best fit calculation. Config changes of default values. Add MaxEpochs configurable form IStopFunction. Fix not randomized new organism genes added to populations. Fix incorrect number of epochs to wait when no delta change. - MIT - True + 4.1.0 + true + $(NoWarn);CS1591 + README.md + true + true + true + snupkg - + - + + + + +