Skip to content

Instantly share code, notes, and snippets.

@davidglassborow
Forked from dungpa/zebra4.fs
Last active December 13, 2018 14:53
Show Gist options
  • Save davidglassborow/a53c62b0d2ecc53f2908a0d0fc2af03c to your computer and use it in GitHub Desktop.
Save davidglassborow/a53c62b0d2ecc53f2908a0d0fc2af03c to your computer and use it in GitHub Desktop.
The whole solution for Zebra Puzzle using SolverFoundation
#r @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\Microsoft.Solver.Foundation.dll"
module ZebraPuzzle =
open System
open Microsoft.SolverFoundation.Services
let solve() =
let context = SolverContext.GetContext()
let rootModel = context.CreateModel()
let person = rootModel.CreateSubModel("Person")
let languages = Domain.Enum("English", "Spanish", "Japanese", "Italian", "Norwegian")
let language = Decision(languages, "Language")
person.AddDecision(language)
let colors = Domain.Enum("Red", "Green", "White", "Blue", "Yellow")
let color = Decision(colors, "Color")
person.AddDecision(color)
let animals = Domain.Enum("Dog", "Snails", "Fox", "Horse", "Zebra")
let animal = Decision(animals, "Animal")
person.AddDecision(animal)
let actors = Domain.Enum("Painter", "Sculptor", "Diplomat", "Violinist", "Doctor")
let actor = Decision(actors, "Actor")
person.AddDecision(actor)
let beverages = Domain.Enum("Tea", "Coffee", "Milk", "Juice", "Water")
let beverage = Decision(beverages, "Beverage")
person.AddDecision(beverage)
let (==) (x: Decision) (y: string) = Term.op_Equality(x, y)
let (!=) (x: Decision) (y: string) = Term.op_Inequality(x, y)
let (==>) x y = Model.Implies(x, y)
let (|||) x y = Model.Or(x, y)
let (+^) s i = sprintf "%s%i" s i
person.AddConstraints("constraints",
language == "English" ==> (color == "Red"),
language == "Spanish" ==> (animal == "Dog"),
language == "Japanese" ==> (actor == "Painter"),
language == "Italian" ==> (beverage == "Tea"),
color == "Green" ==> (beverage == "Coffee"),
actor == "Sculptor" ==> (animal == "Snails"),
actor == "Diplomat" ==> (color == "Yellow"),
actor == "Violinist" ==> (beverage == "Juice")) |> ignore
let persons = Array.init 5 (sprintf "person%i" >> person.CreateInstance)
let allDifferent (decision: Decision) = Array.init 5 (fun i -> persons.[i].[decision] :> Term)
rootModel.AddConstraints("constraints",
Model.AllDifferent (allDifferent language),
Model.AllDifferent (allDifferent color),
Model.AllDifferent (allDifferent actor),
Model.AllDifferent (allDifferent animal),
Model.AllDifferent (allDifferent beverage),
persons.[0].[language] == "Norwegian",
persons.[2].[beverage] == "Milk",
persons.[4].[color] != "Green") |> ignore
for i in 0..3 do
rootModel.AddConstraint("GreenWhite" +^ i, persons.[i].[color] == "Green" ==> (persons.[i+1].[color] == "White")) |> ignore
for i in 0..4 do
if i = 0 then
rootModel.AddConstraint("NorwegianBlue" +^ i, persons.[0].[language] == "Norwegian" ==> (persons.[1].[color] == "Blue")) |> ignore
rootModel.AddConstraint("FoxDoctor" +^ i, persons.[0].[animal] == "Fox" ==> (persons.[1].[actor] == "Doctor")) |> ignore
rootModel.AddConstraint("HorseDiplomat" +^ i, persons.[0].[animal] == "Horse" ==> (persons.[1].[actor] == "Diplomat")) |> ignore
elif i = 4 then
rootModel.AddConstraint("NorwegianBlue" +^ i, persons.[4].[language] == "Norwegian" ==> (persons.[3].[color] == "Blue")) |> ignore
rootModel.AddConstraint("FoxDoctor" +^ i, persons.[4].[animal] == "Fox" ==> (persons.[3].[actor] == "Doctor")) |> ignore
rootModel.AddConstraint("HorseDiplomat" +^ i, persons.[4].[animal] == "Horse" ==> (persons.[3].[actor] == "Diplomat")) |> ignore
else
rootModel.AddConstraint("NorwegianBlue" +^ i, persons.[i].[language] == "Norwegian" ==> ((persons.[i-1].[color] == "Blue") ||| (persons.[i + 1].[color] == "Blue"))) |> ignore
rootModel.AddConstraint("FoxDoctor" +^ i, persons.[i].[animal] == "Fox" ==> ((persons.[i-1].[actor] == "Doctor") ||| (persons.[i+1].[actor] == "Doctor"))) |> ignore
rootModel.AddConstraint("HorseDiplomat" +^ i, persons.[i].[animal] == "Horse" ==> ((persons.[i-1].[actor] == "Diplomat") ||| (persons.[i+1].[actor] == "Diplomat"))) |> ignore
let solution = context.Solve(ConstraintProgrammingDirective())
while (solution.Quality <> SolverQuality.Infeasible) do
solution.GetReport() |> printfn "RESULT:\n %A"
solution.GetNext()
#time "on";;
let z = ZebraPuzzle.solve();;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment