Skip to content

Commit

Permalink
Experiment with using an onIdle like combinator in my solver.
Browse files Browse the repository at this point in the history
This discovered a bug in the interpreter: issue #190.
  • Loading branch information
arthurp committed Feb 17, 2017
1 parent 584b16d commit 4934848
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 7 deletions.
70 changes: 63 additions & 7 deletions OrcExamples/objects/sudoku_solver.orc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ import class ConcurrentHashMap = "java.util.concurrent.ConcurrentHashMap"

def Set() = ConcurrentHashMap.newKeySet()

-- Implement something similar to the onIdle combinator.
-- This is not the same since it does not prevent f from restarting while
-- g is running.
def onIdle[A](f :: lambda() :: A, g :: lambda() :: A) :: A =
{|
Vclock(IntegerTimeOrder) >> (
Vawait(0) >> f() |
Vawait(1) >> g()
)
|}

def seq(n) =
def h(i) if (i <: n) = i : h(i+1)
def h(_) = []
Expand Down Expand Up @@ -62,6 +73,9 @@ class Grid {
acc + foldl(lambda(acc, x) =
acc + get(x, y).toString() + ", ", "", seq(n)) + "\n",
"", seq(n)) + "]"

def shallowForce() =
upto(n) >x> upto(m) >y> get(x, y) >> stop ; signal
}

{-
Expand Down Expand Up @@ -155,6 +169,17 @@ class SudokuCell {

val number = value + 1
def toString() = number.toString()

def remainingIfUnknown() = stop
}

class UnknownSudokuCell extends SelectLastValue with SudokuCell {
val possibilities = collect(allNumbers)

def force(x) =
Ift(remaining.contains(x)) >> valueCell.write(x)

def remainingIfUnknown() = Ift(remaining.size() :> 1) >> iterableToList(remaining)
}

{-
Expand All @@ -164,7 +189,7 @@ the class will go quiescent, so onIdle could be used to detect this case and app
guessing or heuristics.
-}

val solver = new Grid {
class SudokuSolver extends Grid {
val n = N
val m = N

Expand All @@ -177,9 +202,7 @@ val solver = new Grid {
else
None()

def makeUnknown(myX, myY) = new (SelectLastValue with SudokuCell) {
val possibilities = collect(allNumbers)

def makeUnknown(myX, myY) = new UnknownSudokuCell {
val _ = {|
(
allNumbers() >x> (x, myY) |
Expand All @@ -203,9 +226,43 @@ val solver = new Grid {
val v = getPuzzleCell(myX, myY)
v >Some(n)> makeKnown(myX, myY, n) |
v >None()> makeUnknown(myX, myY)
}

def copy() =
val orig = this
val c = new Grid {
val n = N
val m = N

def compute(x, y) =
onIdle({
makeKnown(x, y, orig.get(x, y).value >x> x)
}, {
makeUnknown(x, y)
})
}
c.shallowForce() >>
c
}

-- This is initial work on handling the case where the simple propogation of values fails.
-- This is not completed.
def solve(solver :: lambda() :: SudokuSolver) =
val s = Cell()
onIdle({ s := solver() >> s?.toString() }, {
-- == Find a location with the smallest number of remaining possibilities
-- For now just pick an arbitrary location with multiple possibilities.
val (x, y, ps) = {| allNumbers() >x> allNumbers() >y> (x, y, s?.get(x, y).remainingIfUnknown()) |}
val _ = Println((x, y, ps))
-- == Force that location to one value in each copy
--val s2 = s.copy()
--val s1 = s2.shallowForce() >> s

-- == Recursively call this on the copies
-- == Publish the completed version
Error("Not Implemented")
})

Println(solver.toString()) >> stop
Println(new SudokuSolver.toString()) >> stop

{-
OUTPUT:
Expand All @@ -220,5 +277,4 @@ OUTPUT:
2, 4, 8, 9, 5, 7, 1, 3, 6,
7, 6, 3, 4, 1, 8, 2, 5, 9,
]
signal
-}
24 changes: 24 additions & 0 deletions OrcTests/test_data/functional_valid/onidle.orc
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
-- Run g if f becomes idle/quiescent but not halted. Kill the whole mess when either half publishes.
def ifIdle[A](f :: lambda() :: A, g :: lambda() :: A) :: A =
{|
Vclock(IntegerTimeOrder) >> (
(Vawait(0) >> Some(f()) ; None() ) |
Vawait(1) >> Some(g())
)
|} >Some(x)> x

val c = Channel()

def test() =
--ifIdle({ c.get() }, { Println("get idle") }) |
--ifIdle({ stop }, { Println("FAIL: stop idle") }) |
ifIdle({ "Publish from left" }, { Println("FAIL: publication idle") }) |
stop

def f(n) if (n :> 0) =
test() >x> Println(x) >> stop ; Println("============") >> f(n-1)

f(1000)

-- TODO: Once https://github.com/orc-lang/orc/issues/190 is fixed this should be made into a real regression test.
-- It's not a test at the moment because I really don't want to deal with a deadlock in the testing harness.

0 comments on commit 4934848

Please sign in to comment.