Skip to content

Commit

Permalink
Program: save solution metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
gsomix committed Jul 8, 2023
1 parent aa7a1d3 commit 8dbee98
Show file tree
Hide file tree
Showing 140 changed files with 174 additions and 148 deletions.
8 changes: 8 additions & 0 deletions Icfpc2023/Domain.fs
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,11 @@ type Problem = {
type Solution = {
Placements: PointD[]
}

type Score = double
type Solver = string

type SolutionMetadata = {
Score: Score
Solver: Solver
}
26 changes: 16 additions & 10 deletions Icfpc2023/JsonDefs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ type SolutionJson = {
placements: PlacementJson[]
}

type SolutionScoreJson = {
score: SolutionScore
type SolutionMetadataJson = {
score: Score
solver: Solver
}

#nowarn "25"
Expand Down Expand Up @@ -63,14 +64,19 @@ let ReadSolutionFromJson(json: string): Solution =
Placements = solJson.placements |> Array.map(fun p -> PointD(p.x, p.y))
}

let WriteSolutionScoreToJson(score: SolutionScore): string =
let scoreJson = {
score = score
let WriteSolutionMetadataToJson(metadata: SolutionMetadata): string =
let metadataJson = {
score = metadata.Score
solver = metadata.Solver
}
JsonConvert.SerializeObject(scoreJson)
JsonConvert.SerializeObject(metadataJson)

let ReadSolutionScoreFromJson(json: string): SolutionScore =
JsonConvert.DeserializeObject<SolutionScoreJson>(json).score
let ReadSolutionMetadataFromJson(json: string): SolutionMetadata =
let metadataJson = JsonConvert.DeserializeObject<SolutionMetadataJson>(json)
{
Score = metadataJson.score
Solver = metadataJson.solver
}

let ReadProblemFromFile(filePath: string): Problem =
let json = File.ReadAllText(filePath)
Expand All @@ -80,6 +86,6 @@ let ReadSolutionFromFile(filePath: string): Solution =
let json = File.ReadAllText(filePath)
ReadSolutionFromJson json

let ReadSolutionScoreFromFile(filePath: string): SolutionScore =
let ReadSolutionMetadataFromFile(filePath: string): SolutionMetadata =
let json = File.ReadAllText(filePath)
ReadSolutionScoreFromJson json
ReadSolutionMetadataFromJson json
118 changes: 66 additions & 52 deletions Icfpc2023/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ open System.Threading.Tasks
open Icfpc2023
open Icfpc2023.HttpApi

let inline (|Parse|_|) (str: string) : 'a option =
let mutable value = Unchecked.defaultof<'a>
let result = (^a: (static member TryParse: string * byref< ^a> -> bool) str, &value)
if result then Some value
else None

let solutionDirectory =
let mutable directory = Environment.CurrentDirectory
while not(isNull directory) && not <| File.Exists(Path.Combine(directory, "Icfpc2023.sln")) do
Expand Down Expand Up @@ -33,36 +39,41 @@ let solvers = Map [
"dummy", DummySolver.Solve
]

let writeScore i score =
let solutionScoreFile = Path.Combine(solutionsDir, $"{i}.score.json")
let solutionScoreText = JsonDefs.WriteSolutionScoreToJson score
File.WriteAllText(solutionScoreFile, solutionScoreText)

let readProblem i =
let problemFile = Path.Combine(problemsDir, $"{i}.json")
let readProblem (problemId: int) =
let problemFile = Path.Combine(problemsDir, $"{problemId}.json")
JsonDefs.ReadProblemFromFile problemFile

let readSolution i =
let solutionFile = Path.Combine(solutionsDir, $"{i}.json")
JsonDefs.ReadSolutionFromFile solutionFile
let writeSolutionMetadata (problemId: int) metadata =
let solutionMetadataFile = Path.Combine(solutionsDir, $"{problemId}.meta.json")
let solutionMetadataText = JsonDefs.WriteSolutionMetadataToJson metadata
File.WriteAllText(solutionMetadataFile, solutionMetadataText)

let writeSolution i solution score =
let solutionFile = Path.Combine(solutionsDir, $"{i}.json")
let solutionText = JsonDefs.WriteSolutionToJson solution
File.WriteAllText(solutionFile, solutionText)
let readSolutionMetadata (problemId: int) =
let solutionMetadataFile = Path.Combine(solutionsDir, $"{problemId}.meta.json")
JsonDefs.ReadSolutionMetadataFromFile solutionMetadataFile

writeScore i score
let readSolution (problemId: int) =
let solutionFile = Path.Combine(solutionsDir, $"{problemId}.json")
let solutionMetadata = readSolutionMetadata problemId
let solution = JsonDefs.ReadSolutionFromFile solutionFile
solution, solutionMetadata

let readScoreOrCompute i problem =
let solutionScoreFile = Path.Combine(solutionsDir, $"{i}.score.json")
try
JsonDefs.ReadSolutionScoreFromFile solutionScoreFile
with
| :? FileNotFoundException ->
let oldSolution = readSolution i
let score = Scoring.CalculateScore problem oldSolution
writeScore i score
score
let writeSolution (problemId: int) solution solutionMetadata =
let solutionFile = Path.Combine(solutionsDir, $"{problemId}.json")
let solutionText = JsonDefs.WriteSolutionToJson solution
File.WriteAllText(solutionFile, solutionText)
writeSolutionMetadata problemId solutionMetadata

let solve (problemId: int) (solverName: Solver) =
let problem = readProblem problemId
let solver = solvers[solverName]
let solution = solver problem
let score = Scoring.CalculateScore problem solution
let solutionMetadata = {
Score = score
Solver = solverName
}
writeSolution problemId solution solutionMetadata

[<EntryPoint>]
let main(args: string[]): int =
Expand All @@ -79,50 +90,53 @@ let main(args: string[]): int =
printfn $"Downloading problem {i} to \"{filePath}\""
File.WriteAllText(filePath, content)
}
| [|"download"; numStr|] ->
let num = int numStr

| [| "download"; Parse(problemId) |] ->
Directory.CreateDirectory problemsDir |> ignore
let content = runSynchronously <| DownloadProblem num
let filePath = Path.Combine(problemsDir, $"{string num}.json")
printfn $"Downloading problem {num} to \"{filePath}\""
let content = runSynchronously <| DownloadProblem problemId
let filePath = Path.Combine(problemsDir, $"{string problemId}.json")
printfn $"Downloading problem {problemId} to \"{filePath}\""
File.WriteAllText(filePath, content)

| [| "solve"; numStr; solverStr |] ->
let num = int numStr
let problem = readProblem num
let solver = solvers[solverStr]
let solution = solver problem
let score = Scoring.CalculateScore problem solution
writeSolution num solution score
| [| "solve"; Parse(problemId); solverName |] ->
solve problemId solverName

| [| "solve"; "all"; solverName |] ->
let problems = Directory.GetFiles(problemsDir, "*.json")
for problem in problems do
let problemId = Path.GetFileNameWithoutExtension problem |> int
printfn $"Solving problem \"{problemId}\""
solve problemId solverName

| [| "solveBest"; numStr; solverStr |] ->
let num = int numStr
let problem = readProblem num
| [| "solveBest"; Parse(problemId); solverName |] ->
let problem = readProblem problemId

let oldSolution = readSolution num
let oldScore = readScoreOrCompute num problem
let _, oldSolutionMetadata = readSolution problemId
let oldScore = oldSolutionMetadata.Score
let oldSolver = oldSolutionMetadata.Solver

let solver = solvers[solverStr]
let solver = solvers[solverName]
let newSolution = solver problem
let newScore = Scoring.CalculateScore problem newSolution

let diff = newScore - oldScore
let diff_percent = 100.0 * (diff / oldScore)
printfn $"Score for problem {num}: {oldScore} -> {newScore} (%+f{diff} / %+.0f{diff_percent}%%)"
printfn $"Score for problem {problemId}: {oldScore} ({oldSolver}) -> {newScore} ({solverName}) (%+f{diff} / %+.0f{diff_percent}%%)"
if newScore > oldScore then
printfn $"Writing solution..."
writeSolution num newSolution newScore
let solutionMetadata = {
Score = newScore
Solver = solverName
}
writeSolution problemId newSolution solutionMetadata
else
printfn "Do nothing!"

| [| "score"; numStr |] ->
let num = int numStr
let problem = readProblem num
let solution = readSolution num
let score = Scoring.CalculateScore problem solution
printfn $"Score: {string score}"
| [| "score"; Parse(problemId) |] ->
let _, solutionMetadata = readSolution problemId
printfn $"Score: {string solutionMetadata.Score}"

| [|"upload"; "all"|] ->
| [| "upload"; "all" |] ->
let token = readToken()
let solutions = Directory.GetFiles(solutionsDir, "*.json")
for solution in solutions do
Expand Down
8 changes: 3 additions & 5 deletions Icfpc2023/Scoring.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ type private Musician = {
Location: PointD
}

type SolutionScore = double

let private CalculateAttendeeMusicianScore (attendee: Attendee) (musician: Musician): SolutionScore =
let private CalculateAttendeeMusicianScore (attendee: Attendee) (musician: Musician): Score =
let d_squared = (attendee.X - musician.Location.X) ** 2.0 + (attendee.Y - musician.Location.Y) ** 2.0
ceil(1_000_000.0 * attendee.Tastes[musician.Instrument] / d_squared)

Expand All @@ -21,14 +19,14 @@ let private AnyOtherMusicianBlocksSound (musicians: Musician[]) (attendee: Atten
|> Seq.filter(fun (i, _) -> i <> mIndex)
|> Seq.exists(fun (_, m) -> blockZone.Contains(m.Location))

let private CalculateAttendeeScore (musicians: Musician[]) (attendee: Attendee): SolutionScore =
let private CalculateAttendeeScore (musicians: Musician[]) (attendee: Attendee): Score =
Seq.indexed musicians
|> Seq.sumBy(fun (i, musician) ->
if AnyOtherMusicianBlocksSound musicians attendee i then 0.0
else CalculateAttendeeMusicianScore attendee musician
)

let CalculateScore(problem: Problem) (solution: Solution): SolutionScore =
let CalculateScore(problem: Problem) (solution: Solution): Score =
let musicians =
problem.Musicians
|> Seq.zip solution.Placements
Expand Down
1 change: 1 addition & 0 deletions solutions/1.meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"score":1190163.0,"solver":"dummy"}
1 change: 0 additions & 1 deletion solutions/1.score.json

This file was deleted.

2 changes: 1 addition & 1 deletion solutions/10.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"placements":[{"x":125.0,"y":838.0},{"x":125.0,"y":848.0},{"x":125.0,"y":858.0},{"x":125.0,"y":868.0},{"x":125.0,"y":878.0},{"x":125.0,"y":888.0},{"x":125.0,"y":898.0},{"x":125.0,"y":908.0},{"x":125.0,"y":918.0},{"x":125.0,"y":928.0},{"x":125.0,"y":938.0},{"x":125.0,"y":948.0},{"x":125.0,"y":958.0},{"x":125.0,"y":968.0},{"x":125.0,"y":978.0},{"x":135.0,"y":838.0},{"x":135.0,"y":848.0},{"x":135.0,"y":858.0},{"x":135.0,"y":868.0},{"x":135.0,"y":878.0},{"x":135.0,"y":888.0},{"x":135.0,"y":898.0},{"x":135.0,"y":908.0},{"x":135.0,"y":918.0},{"x":135.0,"y":928.0},{"x":135.0,"y":938.0},{"x":135.0,"y":948.0},{"x":135.0,"y":958.0},{"x":135.0,"y":968.0},{"x":135.0,"y":978.0},{"x":145.0,"y":838.0},{"x":145.0,"y":848.0},{"x":145.0,"y":858.0},{"x":145.0,"y":868.0},{"x":145.0,"y":878.0},{"x":145.0,"y":888.0},{"x":145.0,"y":898.0},{"x":145.0,"y":908.0},{"x":145.0,"y":918.0},{"x":145.0,"y":928.0},{"x":145.0,"y":938.0},{"x":145.0,"y":948.0},{"x":145.0,"y":958.0},{"x":145.0,"y":968.0},{"x":145.0,"y":978.0},{"x":155.0,"y":838.0},{"x":155.0,"y":848.0},{"x":155.0,"y":858.0},{"x":155.0,"y":868.0},{"x":155.0,"y":878.0},{"x":155.0,"y":888.0},{"x":155.0,"y":898.0},{"x":155.0,"y":908.0},{"x":155.0,"y":918.0},{"x":155.0,"y":928.0},{"x":155.0,"y":938.0},{"x":155.0,"y":948.0},{"x":155.0,"y":958.0},{"x":155.0,"y":968.0},{"x":155.0,"y":978.0},{"x":165.0,"y":838.0},{"x":165.0,"y":848.0},{"x":165.0,"y":858.0},{"x":165.0,"y":868.0},{"x":165.0,"y":878.0},{"x":165.0,"y":888.0},{"x":165.0,"y":898.0},{"x":165.0,"y":908.0},{"x":165.0,"y":918.0},{"x":165.0,"y":928.0},{"x":165.0,"y":938.0},{"x":165.0,"y":948.0},{"x":165.0,"y":958.0},{"x":165.0,"y":968.0},{"x":165.0,"y":978.0},{"x":175.0,"y":838.0},{"x":175.0,"y":848.0},{"x":175.0,"y":858.0},{"x":175.0,"y":868.0},{"x":175.0,"y":878.0},{"x":175.0,"y":888.0},{"x":175.0,"y":898.0},{"x":175.0,"y":908.0},{"x":175.0,"y":918.0},{"x":175.0,"y":928.0},{"x":175.0,"y":938.0},{"x":175.0,"y":948.0},{"x":175.0,"y":958.0},{"x":175.0,"y":968.0},{"x":175.0,"y":978.0},{"x":185.0,"y":838.0},{"x":185.0,"y":848.0},{"x":185.0,"y":858.0},{"x":185.0,"y":868.0}]}
{"placements":[{"x":125.0,"y":838.0},{"x":135.0,"y":838.0},{"x":145.0,"y":838.0},{"x":155.0,"y":838.0},{"x":165.0,"y":838.0},{"x":175.0,"y":838.0},{"x":185.0,"y":838.0},{"x":195.0,"y":838.0},{"x":205.0,"y":838.0},{"x":215.0,"y":838.0},{"x":225.0,"y":838.0},{"x":235.0,"y":838.0},{"x":245.0,"y":838.0},{"x":255.0,"y":838.0},{"x":265.0,"y":838.0},{"x":275.0,"y":838.0},{"x":285.0,"y":838.0},{"x":295.0,"y":838.0},{"x":305.0,"y":838.0},{"x":315.0,"y":838.0},{"x":325.0,"y":838.0},{"x":335.0,"y":838.0},{"x":345.0,"y":838.0},{"x":355.0,"y":838.0},{"x":125.0,"y":872.6410161513776},{"x":135.0,"y":872.6410161513776},{"x":145.0,"y":872.6410161513776},{"x":155.0,"y":872.6410161513776},{"x":165.0,"y":872.6410161513776},{"x":175.0,"y":872.6410161513776},{"x":185.0,"y":872.6410161513776},{"x":195.0,"y":872.6410161513776},{"x":205.0,"y":872.6410161513776},{"x":215.0,"y":872.6410161513776},{"x":225.0,"y":872.6410161513776},{"x":235.0,"y":872.6410161513776},{"x":245.0,"y":872.6410161513776},{"x":255.0,"y":872.6410161513776},{"x":265.0,"y":872.6410161513776},{"x":275.0,"y":872.6410161513776},{"x":285.0,"y":872.6410161513776},{"x":295.0,"y":872.6410161513776},{"x":305.0,"y":872.6410161513776},{"x":315.0,"y":872.6410161513776},{"x":325.0,"y":872.6410161513776},{"x":335.0,"y":872.6410161513776},{"x":345.0,"y":872.6410161513776},{"x":355.0,"y":872.6410161513776},{"x":125.0,"y":907.282032302755},{"x":135.0,"y":907.282032302755},{"x":145.0,"y":907.282032302755},{"x":155.0,"y":907.282032302755},{"x":165.0,"y":907.282032302755},{"x":175.0,"y":907.282032302755},{"x":185.0,"y":907.282032302755},{"x":195.0,"y":907.282032302755},{"x":205.0,"y":907.282032302755},{"x":215.0,"y":907.282032302755},{"x":225.0,"y":907.282032302755},{"x":235.0,"y":907.282032302755},{"x":245.0,"y":907.282032302755},{"x":255.0,"y":907.282032302755},{"x":265.0,"y":907.282032302755},{"x":275.0,"y":907.282032302755},{"x":285.0,"y":907.282032302755},{"x":295.0,"y":907.282032302755},{"x":305.0,"y":907.282032302755},{"x":315.0,"y":907.282032302755},{"x":325.0,"y":907.282032302755},{"x":335.0,"y":907.282032302755},{"x":345.0,"y":907.282032302755},{"x":355.0,"y":907.282032302755},{"x":125.0,"y":941.9230484541326},{"x":135.0,"y":941.9230484541326},{"x":145.0,"y":941.9230484541326},{"x":155.0,"y":941.9230484541326},{"x":165.0,"y":941.9230484541326},{"x":175.0,"y":941.9230484541326},{"x":185.0,"y":941.9230484541326},{"x":195.0,"y":941.9230484541326},{"x":205.0,"y":941.9230484541326},{"x":215.0,"y":941.9230484541326},{"x":225.0,"y":941.9230484541326},{"x":235.0,"y":941.9230484541326},{"x":245.0,"y":941.9230484541326},{"x":255.0,"y":941.9230484541326},{"x":265.0,"y":941.9230484541326},{"x":275.0,"y":941.9230484541326},{"x":285.0,"y":941.9230484541326},{"x":295.0,"y":941.9230484541326},{"x":305.0,"y":941.9230484541326},{"x":315.0,"y":941.9230484541326},{"x":325.0,"y":941.9230484541326},{"x":335.0,"y":941.9230484541326}]}
1 change: 1 addition & 0 deletions solutions/10.meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"score":-17663817.0,"solver":"dummy"}
1 change: 0 additions & 1 deletion solutions/10.score.json

This file was deleted.

Loading

0 comments on commit 8dbee98

Please sign in to comment.