Skip to content

Commit

Permalink
Add support for tapered eval for all bonus and penalties & `staticeva…
Browse files Browse the repository at this point in the history
…l` UCI option (#414)

* Add support for tapered eval bonus and penalties
* Add `staticeval` UCI option, which accepts a file paths and evaluates all positions in such file

Usage example:
```pwsh
dotnet run -c Release -- "staticeval \\wsl$\Ubuntu-20.04\home\edu\dev\texel-tuner\datasets\quiet-labeled.book" > quiet-labeled-evals.epd
```
  • Loading branch information
eduherminio authored Sep 26, 2023
1 parent ecd462b commit 04705bf
Show file tree
Hide file tree
Showing 10 changed files with 337 additions and 113 deletions.
1 change: 1 addition & 0 deletions src/Lynx.Cli/Lynx.Cli.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<ServerGarbageCollection>true</ServerGarbageCollection>
<EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
<!--<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>-->
<!--TODO remove after RC-2, according to https:/dotnet/core/issues/8439-->
<Features>$(Features);InterceptorsPreview</Features>
</PropertyGroup>
Expand Down
7 changes: 0 additions & 7 deletions src/Lynx.Cli/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,6 @@
config.GetSection(nameof(EngineSettings)).Bind(Configuration.EngineSettings);
config.GetSection(nameof(GeneralSettings)).Bind(Configuration.GeneralSettings);

// TODO remove when .NET sdk includes https:/dotnet/runtime/issues/89732
var generalConfig = config.GetSection(nameof(GeneralSettings));
if (bool.TryParse(generalConfig[nameof(Configuration.GeneralSettings.EnableLogging)], out var enableLogging))
{
Configuration.GeneralSettings.EnableLogging = enableLogging;
}

if (Configuration.GeneralSettings.EnableLogging)
{
LogManager.Configuration = new NLogLoggingConfiguration(config.GetSection("NLog"));
Expand Down
96 changes: 75 additions & 21 deletions src/Lynx.Cli/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,32 +30,86 @@
"NMP_DepthReduction": 3,
"AspirationWindowAlpha": 50,
"AspirationWindowBeta": 50,

"IsolatedPawnPenalty": 10,
"DoubledPawnPenalty": 10,
"PassedPawnBonus": [
0,
10,
30,
50,
75,
100,
150,
200
],
"SemiOpenFileRookBonus": 10,
"OpenFileRookBonus": 15,
"SemiOpenFileKingPenalty": 10,
"OpenFileKingPenalty": 15,
"KingShieldBonus": 5,
"BishopMobilityBonus": 1,
"QueenMobilityBonus": 1,
// Evaluation
"IsolatedPawnPenalty": {
"MG": 10,
"EG": 10
},
"DoubledPawnPenalty": {
"MG": 10,
"EG": 10
},
"PassedPawnBonus": {
"Rank0": {
"MG": 0,
"EG": 0
},
"Rank1": {
"MG": 10,
"EG": 10
},
"Rank2": {
"MG": 30,
"EG": 30
},
"Rank3": {
"MG": 50,
"EG": 50
},
"Rank4": {
"MG": 75,
"EG": 75
},
"Rank5": {
"MG": 100,
"EG": 100
},
"Rank6": {
"MG": 150,
"EG": 150
},
"Rank7": {
"MG": 200,
"EG": 200
}
},
"SemiOpenFileRookBonus": {
"MG": 10,
"EG": 10
},
"OpenFileRookBonus": {
"MG": 15,
"EG": 15
},
"SemiOpenFileKingPenalty": {
"MG": 10,
"EG": 10
},
"OpenFileKingPenalty": {
"MG": 15,
"EG": 15
},
"KingShieldBonus": {
"MG": 5,
"EG": 5
},
"BishopMobilityBonus": {
"MG": 1,
"EG": 1
},
"QueenMobilityBonus": {
"MG": 1,
"EG": 1
},
"BishopPairBonus": {
"MG": 0,
"EG": 100
},
"TranspositionTableEnabled": true,
"TranspositionTableSize": "256",
"UseOnlineTablebaseInRootPositions": false,
"UseOnlineTablebaseInSearch": false,
"BenchDepth": 5,
"BishopPairMaxBonus": 100,
"RFP_MaxDepth": 6,
"RFP_DepthScalingFactor": 75
},
Expand Down
105 changes: 90 additions & 15 deletions src/Lynx/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,78 @@ public sealed class GeneralSettings
public bool EnableLogging { get; set; } = false;
}

public class TaperedEvaluationTerm
{
public int MG { get; set; }

public int EG { get; set; }

internal TaperedEvaluationTerm(int singleValue) : this(singleValue, singleValue)
{
}

public TaperedEvaluationTerm(int mg, int eg)
{
MG = mg;
EG = eg;
}

public override string ToString()
{
return $"{{\"MG\":{MG},\"EG\":{EG}}}";
}
}

public class TaperedEvaluationTermByRank
{
private readonly List<TaperedEvaluationTerm> _evaluationTermsIndexedByPiece;

public TaperedEvaluationTerm Rank0 { get; set; }
public TaperedEvaluationTerm Rank1 { get; set; }
public TaperedEvaluationTerm Rank2 { get; set; }
public TaperedEvaluationTerm Rank3 { get; set; }
public TaperedEvaluationTerm Rank4 { get; set; }
public TaperedEvaluationTerm Rank5 { get; set; }
public TaperedEvaluationTerm Rank6 { get; set; }
public TaperedEvaluationTerm Rank7 { get; set; }

public TaperedEvaluationTermByRank(
TaperedEvaluationTerm rank0, TaperedEvaluationTerm rank1, TaperedEvaluationTerm rank2,
TaperedEvaluationTerm rank3, TaperedEvaluationTerm rank4, TaperedEvaluationTerm rank5,
TaperedEvaluationTerm rank6, TaperedEvaluationTerm rank7)
{
Rank0 = rank0;
Rank1 = rank1;
Rank2 = rank2;
Rank3 = rank3;
Rank4 = rank4;
Rank5 = rank5;
Rank6 = rank6;
Rank7 = rank7;

_evaluationTermsIndexedByPiece = [rank0, rank1, rank2, rank3, rank4, rank5, rank6, rank7];
}

public TaperedEvaluationTerm this[int i]
{
get { return _evaluationTermsIndexedByPiece[i]; }
}

public override string ToString()
{
return "{" +
$"\"{nameof(Rank0)}\":{Rank0}," +
$"\"{nameof(Rank1)}\":{Rank1}," +
$"\"{nameof(Rank2)}\":{Rank2}," +
$"\"{nameof(Rank3)}\":{Rank3}," +
$"\"{nameof(Rank4)}\":{Rank4}," +
$"\"{nameof(Rank5)}\":{Rank5}," +
$"\"{nameof(Rank6)}\":{Rank6}," +
$"\"{nameof(Rank7)}\":{Rank7}" +
"}";
}
}

public sealed class EngineSettings
{
public int DefaultMaxDepth { get; set; } = 5;
Expand Down Expand Up @@ -169,25 +241,31 @@ public sealed class EngineSettings

public int AspirationWindowBeta { get; set; } = 50;

public int IsolatedPawnPenalty { get; set; } = 10;
#region Evaluation

public int DoubledPawnPenalty { get; set; } = 10;
public TaperedEvaluationTerm IsolatedPawnPenalty { get; set; } = new(10, 10);

public int[] PassedPawnBonus { get; set; } = new[] { 0, 10, 30, 50, 75, 100, 150, 200 };
public TaperedEvaluationTerm DoubledPawnPenalty { get; set; } = new(10, 10);

public int SemiOpenFileRookBonus { get; set; } = 10;
public TaperedEvaluationTermByRank PassedPawnBonus { get; set; } = new(new(0), new(10), new(30), new(50), new(75), new(100), new(150), new TaperedEvaluationTerm(200));

public int OpenFileRookBonus { get; set; } = 15;
public TaperedEvaluationTerm SemiOpenFileRookBonus { get; set; } = new(10, 10);

public int SemiOpenFileKingPenalty { get; set; } = 10;
public TaperedEvaluationTerm OpenFileRookBonus { get; set; } = new(15, 15);

public int OpenFileKingPenalty { get; set; } = 15;
public TaperedEvaluationTerm SemiOpenFileKingPenalty { get; set; } = new(10, 10);

public int KingShieldBonus { get; set; } = 5;
public TaperedEvaluationTerm OpenFileKingPenalty { get; set; } = new(15, 15);

public int BishopMobilityBonus { get; set; } = 1;
public TaperedEvaluationTerm KingShieldBonus { get; set; } = new(5, 5);

public int QueenMobilityBonus { get; set; } = 1;
public TaperedEvaluationTerm BishopMobilityBonus { get; set; } = new(1, 1);

public TaperedEvaluationTerm QueenMobilityBonus { get; set; } = new(1, 1);

public TaperedEvaluationTerm BishopPairBonus { get; set; } = new(0, 100);

#endregion

public bool TranspositionTableEnabled { get; set; } = true;

Expand All @@ -213,11 +291,6 @@ public sealed class EngineSettings
/// </summary>
public int BenchDepth { get; set; } = 5;

/// <summary>
/// It'll be scaled with phase
/// </summary>
public int BishopPairMaxBonus { get; set; } = 100;

public int RFP_MaxDepth { get; set; } = 6;

public int RFP_DepthScalingFactor { get; set; } = 75;
Expand All @@ -226,6 +299,8 @@ public sealed class EngineSettings
[JsonSourceGenerationOptions(
GenerationMode = JsonSourceGenerationMode.Default, WriteIndented = true)] // https:/dotnet/runtime/issues/78602#issuecomment-1322004254
[JsonSerializable(typeof(EngineSettings))]
[JsonSerializable(typeof(TaperedEvaluationTerm))]
[JsonSerializable(typeof(TaperedEvaluationTermByRank))]
internal partial class EngineSettingsJsonSerializerContext : JsonSerializerContext
{
}
49 changes: 49 additions & 0 deletions src/Lynx/LynxDriver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ static ReadOnlySpan<char> ExtractCommandItems(string rawCommand)
case "printsettings":
await HandleSettings();
break;
case "staticeval":
await HandleStaticEval(rawCommand, cancellationToken);
HandleQuit();
break;
default:
_logger.Warn("Unknown command received: {0}", rawCommand);
break;
Expand Down Expand Up @@ -330,6 +334,51 @@ private async ValueTask HandleSettings()
await _engineWriter.Writer.WriteAsync(message);
}

private async ValueTask HandleStaticEval(string rawCommand, CancellationToken cancellationToken)
{
try
{

var fullPath = Path.GetFullPath(rawCommand[(rawCommand.IndexOf(' ') + 1)..]);
if (!File.Exists(fullPath))
{
_logger.Warn("File {0} not found in (1), ignoring command", rawCommand, fullPath);
return;
}

foreach (var line in await File.ReadAllLinesAsync(fullPath, cancellationToken))
{
var fen = line[..line.IndexOfAny([';', '[', '"'])];

var position = new Position(fen);
if (!position.IsValid())
{
_logger.Warn("Position {0}, parsed as {1} and then {2} not valid, skipping it", line, fen, position.FEN());
continue;
}

var ourFen = position.FEN();
if (ourFen != fen)
{
_logger.Debug("Raw fen: {0}, parsed fen: {1}", fen, ourFen);
}

var eval = position.StaticEvaluation(0);
if (position.Side == Side.Black)
{
eval = -eval; // White perspective
}

await _engineWriter.Writer.WriteAsync($"{line}: {eval}", cancellationToken);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message + e.StackTrace);
await _engineWriter.Writer.WriteAsync(e.Message + e.StackTrace, cancellationToken);
}
}

#endregion

private async Task SendCommand(string command, CancellationToken cancellationToken)
Expand Down
Loading

0 comments on commit 04705bf

Please sign in to comment.