I'm a physics PhD student solving lubrication equations (non-linear PDEs) related to the evaporation of binary droplets in a cylindrical pixel in order to simulate the shape evolution. So I split the system into N ODEs, each representing the height evolution (dh/dt) at point i, write as finite differences, and solve simultaneously using NDSolve. For single-liquid droplets this works perfectly, the droplet evaporates cleanly.
However for binary droplets I include N additional ODEs for the composition fraction evolution (dX/dt) at each point. This also adds a new term (marangoni stress) to the dh/dt equations. Immediately NDSolve says:
At t == 0.00029140763302667777`, step size is effectively zero;
singularity or stiff system suspected.
I plot the droplet height at this t-value and it shows a narrow spike at the origin (clearly exploding, hence the stiffness); plotting the composition shows a narrow plummet at the origin (also exploding, just negative. Also, the physics obviously shouldn't permit the composition fraction to be below 0).
Finally, both sets of equations have terms depending on dX/dr, the composition gradient. If this is set to zero and I also set the evaporation interaction to zero (meaning the two liquids evaporate at the same rate and there can be no X gradient) there should be no change in X anywhere and it should reduce to the single liquid case (dX/dt = 0 and dh/dt no longer depends on X). However, the procedure is introducing some small gradient in X nonetheless, which explodes and causes the same numerical instability.
My question is this: is there anything about NDSolve that might be causing this? I've been over the equations and discretisation a hundred times and am sure it's correct. I've also looked into the documentation of NDSolve, but didn't find anything that helps me. Could it be introducing a small numerical error in the composition gradient?
I can post an MRE code below, but it's pretty dense and obviously written in mathematica code (doesn't transfer to the real world well...) so I don't know how much it'd help. Anyway thank you for reading this!
I've been given as an assignment to write using prolog a solver for
the battleships solitaire puzzle. To those unfamiliar, the puzzle deals
with a 6 by 6 grid on which a series of ships are placed according to the provided
constraints on each row and column, i.e. the first row must contain 3 squares with ships, the second row must contain 1 square with a ship, the third row must contain 0 squares etc for the other rows and columns.
Each puzzle comes with it's own set of constraints and revealed squares, typically two. An example can be seen here:
battleships
So, here's what I've done:
step([ShipCount,Rows,Cols,Tiles],[ShipCount2,Rows2,Cols2,Tiles2]):-
ShipCount2 is ShipCount+1,
nth1(X,Cols,X1),
X1\==0,
nth1(Y,Rows,Y1),
Y1\==0,
not(member([X,Y,_],Tiles)),
pairs(Tiles,TilesXY),
notdiaglist(X,Y,TilesXY),
member(T,[1,2,3,4,5,6]),
append([X,Y],[T],Tile),
append([Tile],Tiles,Tiles2),
dec_elem1(X,Cols,Cols2),dec_elem1(Y,Rows,Rows2).
dec_elem1(1,[A|Tail],[B|Tail]):- B is A-1.
dec_elem1(Count,[A|Tail],[A|Tail2]):- Count1 is Count-1,dec_elem1(Count1,Tail,Tail2).
neib(X1,Y1,X2,Y2) :- X2 is X1,(Y2 is Y1 -1;Y2 is Y1+1; Y2 is Y1).
neib(X1,Y1,X2,Y2) :- X2 is X1-1,(Y2 is Y1 -1;Y2 is Y1+1; Y2 is Y1).
neib(X1,Y1,X2,Y2) :- X2 is X1+1,(Y2 is Y1 -1;Y2 is Y1+1; Y2 is Y1).
notdiag(X1,Y1,X2,Y2) :- not(neib(X1,Y1,X2,Y2)).
notdiag(X1,Y1,X2,Y2) :- neib(X1,Y1,X2,Y2),((X1 == X2,t(Y1,Y2));(Y1 == Y2,t(X1,X2))).
notdiaglist(X1,Y1,[]).
notdiaglist(X1,Y1,[[X2,Y2]|Tail]):-notdiag(X1,Y1,X2,Y2),notdiaglist(X1,Y1,Tail).
t(X1,X2):- X is abs(X1-X2), X==1.
pairs([],[]).
pairs([[X,Y,Z]|Tail],[[X,Y]|Tail2]):-pairs(Tail,Tail2).
I represent a state with a list: [Count,Rows,Columns,Tiles]. The last state must be
[10,[0,0,0,0,0,0],[0,0,0,0,0,0], somelist]. A puzzle starts from an initial state, for example
initial([1, [1,3,1,1,1,2] , [0,2,2,0,0,5] , [[4,4,1],[2,1,0]]]).
I try to find a solution in the following manner:
run:-initial(S),step(S,S1),step(S1,S2),....,step(S8,F).
Now, here's the difficulty: if i restrict myself to one type of ship parts by using member(T,[1])
instead of
member(T,[1,2,3,4,5,6])
it works fine. However, when I use the full range of possible values for T which are needed
later, the query never ends since it runs for too long. this puzzles me, since :
(a) it works for 6 types of ships but only for 8 steps instead of 9
(b) going from a single type of ship to 6 types increases the number
of options for just the last step by a factor of 6, which
shouldn't have such a dramatic effect.
So, what's going on?
To answer your question directly, what's going on is that Prolog is trying to sift through an enormous space of possibilities.
You're correct that altering that line increases the search space of the last call by a factor of six, note that the size of the search space of, say, nine calls, isn't proportional to 9 times the size of one call. Prolog will backtrack on failure, so it's proportional (bounded above, actually) to the size of the possible results of one call raised to the ninth power.
That means we can expect the size of the space Prolog needs to search to grow by at most a factor of 6^9 = 10077696 when we allow T to take on 6 times as many values.
Of course, it doesn't help that (as far as I was able to tell) a solution doesn't exist if we call step 9 times starting with initial anyways. Since that last call is going to fail, Prolog will keep trying until it's exhausted all possibilities (of which there are a great many) before it finally gives up.
As far as a solution goes, I'm not sure I know enough about the problem. If the value if T is the kind of ship that fits in the grid (e.g. single square, half of a 2-square-ship, part of a 3-square-ship) you should note that that gives you a lot more information than the numbers on the rows/columns.
Right now, in pseudocode, your step looks like this:
Find a (X,Y) pair that has non-zero markings on its row/column
Check that there isn't already a ship there
Check that it isn't diagonal to a ship
Pick a kind of ship-part for it to be.
I'd suggest you approach like this:
Finish any already placed ship-bits to form complete ships (if we can't: fail)
Until we're finished:
Find acceptable places to place ship
Check that the markings on the row/column aren't zero
Try to place an entire ship here. (instead of a single part)
By using the most specific information that we have first (in this case, the previously placed parts), we can reduce the amount of work Prolog has to do and make things return reasonably fast.
Tic-Tac-Toe seems to be a fairly solved problem space, most 100% solutions seem to search through a finite tree of possibilities to find a path to winning.
However, I came across something from a computer-simulation toy from the 60's, The MiniVac 601. http://en.wikipedia.org/wiki/Minivac_601
This 'comptuer' consisted of 6 relays that could be hooked up to solve various solutions. It had a game section, which had this description on a program for Tic-Tac-Toe, that claims to be unbeatable as long as the Minivac went first.
Since most solutions to this seem to require lots of memory or computational power, its surprising to see a solution using a computer of 6 relays. Obviously I haven't seen this algorithm before, not sure I can figure it out. Attempts to solve this on a pad and paper seem to indicate a fairly easy win against the computer.
http://www.ccapitalia.net/descarga/docs/1961-minivac601-book5&6.pdf
"with this program, MINI VAC can not lose. The human opponent may
tie the game, but he can never win. This is because of the decision
rules which are the basis of the program. The M IN IV A C is so
programmed that the machine will move 5 squares to the right of its
own last move if and only if the human opponent has blocked that last
move by moving 4 squares to the right of the machine's last move. If
the human player did not move 4 squares to the right of the machine's
last move, M IN IV A C will move into that square and indicate a win.
If the hu man player consistently follows the "move 4 to the right"
rule, every game will end in a tie. This program requires that M IN IV
A C make the first move; the machine's first move will always be to
the center of the game matrix. A program which would allow the human
opponent to move first would require more storage and processing
capacity than is available on M IN IV A C
601. Such a program would, of course, be much more complex than the program which permits the machine to move first"
EDIT: OK so the Question a little more explicitly: Is this a real solution to solving Tic-Tac-Toe? Does anyone recognize this algorithm, it seems very very simple to not be easily searchable.
I think it is all in the layout of the "board". If you look at the 601 units tic-tac-toe area, 9 is in the middle and 1 is top left numbered sequentially clockwise around 9.
The "computer" goes first in the 9 position. The user then goes next.
If the user hasn't gone in position 1 (top left) then that is the next position for the computer. The user then goes next. Then the computer tries to go in position 1+4 (5 - bottom right). If the position is not available it will go in 1+5 (6 - bottom middle). x + 4 is always opposite the previous move, and since the computer has the center position it will be a winning move.
I'm trying to solve the following problem:
I'm analyzing an image and I obtain from this analysis a set of segments
I want to know the intersection of these lines (best fit)
I'm using for this opencv's function cvSolve. For reasonably good input everything works fine.
The problem that I have comes from the fact that when I have just a single bad segment as input the result is different from the one expected.
Details:
Upper left image show the "lonely" purple lines influencing the result (all lines are used as input).
Upper right image shows how a single purple line (one removed) can influence the result.
Lower left image show what we want - the intersection of lines as expected (both purple lines eliminated).
Lower right image show how the other purple line (the other is removed) can influence the result.
As you can see only two lines and the result is completely different from the one expected. Any ideas on how to avoid this are appreciated.
Thanks,
Iulian
The algorithm you are using finds, as described in the link, the least square error solution to the problem. This means that if there are more intersection points, the result will be an average (for a reasonable definition of average) of the real solutions.
I would try an iterative solution: if the error of the first solution is too large, remove from the set of segments the one farthest to the solution, and iterate until the error is acceptably small. This should remove one of the many intersection point, and converge on the one with most lines nearby.
A general answer to this kind of problems is the RANSAC algorithm (question dealing with this), however it has a few disadvantages, for example you need to estimate things like "the expected number of outliers" beforehand. Another Problem I see with your sample is that removing the two green lines also results in a pretty good fit, so that might be a more general problem.
you can solve using SVD incase line1 =(x1,y1)-(x2,y2) ; line2 =(x2,y2)-(x3,y3)
let Ax = b where;
A = [-(y2-y1) (x2-x1);
-(y3-y2) (x3-x2);
.................
.................] -->(nx2)
x = transpose[s t] -->(2x1)
b = [-(y2-y1)x1 + (x2-x1)y1 ;
-(y3-y2)x2 + (x3-x2)y2 ;
........................
........................] --> (nx1)
Example; Matlab Code
line1=[0,10;5,10]
line2=[10,0;10,5]
line3=[0,0;5,5]
A=[-(line1(2,2)-line1(1,2)),(line1(2,1)-line1(1,1));
-(line2(2,2)-line2(1,2)),(line2(2,1)-line2(1,1));
-(line3(2,2)-line3(1,2)),(line3(2,1)-line3(1,1))];
b=[(line1(1,1)*A(1,1))+ (line1(1,2)*A(1,2));
(line2(1,1)*A(2,1))+ (line2(1,2)*A(2,2));
(line3(1,1)*A(3,1))+ (line3(1,2)*A(3,2))];
[U D V] = svd(A)
bprime = U'*b
y=[bprime(1)/D(1,1);bprime(2)/D(2,2)]
x=V*y
Recently I wrote a Ruby program to determine solutions to a "Scramble Squares" tile puzzle:
I used TDD to implement most of it, leading to tests that looked like this:
it "has top, bottom, left, right" do
c = Cards.new
card = c.cards[0]
card.top.should == :CT
card.bottom.should == :WB
card.left.should == :MT
card.right.should == :BT
end
This worked well for the lower-level "helper" methods: identifying the "sides" of a tile, determining if a tile can be validly placed in the grid, etc.
But I ran into a problem when coding the actual algorithm to solve the puzzle. Since I didn't know valid possible solutions to the problem, I didn't know how to write a test first.
I ended up writing a pretty ugly, untested, algorithm to solve it:
def play_game
working_states = []
after_1 = step_1
i = 0
after_1.each do |state_1|
step_2(state_1).each do |state_2|
step_3(state_2).each do |state_3|
step_4(state_3).each do |state_4|
step_5(state_4).each do |state_5|
step_6(state_5).each do |state_6|
step_7(state_6).each do |state_7|
step_8(state_7).each do |state_8|
step_9(state_8).each do |state_9|
working_states << state_9[0]
end
end
end
end
end
end
end
end
end
So my question is: how do you use TDD to write a method when you don't already know the valid outputs?
If you're interested, the code's on GitHub:
Tests: https://github.com/mattdsteele/scramblesquares-solver/blob/master/golf-creator-spec.rb
Production code: https://github.com/mattdsteele/scramblesquares-solver/blob/master/game.rb
This isn't a direct answer, but this reminds me of the comparison between the Sudoku solvers written by Peter Norvig and Ron Jeffries. Ron Jeffries' approach used classic TDD, but he never really got a good solution. Norvig, on the other hand, was able to solve it very elegantly without TDD.
The fundamental question is: can an algorithm emerge using TDD?
From the puzzle website:
The object of the Scramble Squares®
puzzle game is to arrange the nine
colorfully illustrated square pieces
into a 12" x 12" square so that the
realistic graphics on the pieces'
edges match perfectly to form a
completed design in every direction.
So one of the first things I would look for is a test of whether two tiles, in a particular arrangement, match one another. This is with regard to your question of validity. Without that method working correctly, you can't evaluate whether the puzzle has been solved. That seems like a nice starting point, a nice bite-sized piece toward the full solution. It's not an algorithm yet, of course.
Once match() is working, where do we go from here? Well, an obvious solution is brute force: from the set of all possible arrangements of the tiles within the grid, reject those where any two adjacent tiles don't match. That's an algorithm, of sorts, and it's pretty certain to work (although in many puzzles the heat death of the universe occurs before a solution).
How about collecting the set of all pairs of tiles that match along a given edge (LTRB)? Could you get from there to a solution, quicker? Certainly you can test it (and test-drive it) easily enough.
The tests are unlikely to give you an algorithm, but they can help you to think about algorithms, and of course they can make validating your approach easier.
dunno if this "answers" the question either
analysis of the "puzzle"
9 tiles
each has 4 sides
each tile has half a pattern / picture
BRUTE FORCE APPROACH
to solve this problem
you need to generate 9! combinations ( 9 tiles X 8 tiles X 7 tiles... )
limited by the number of matching sides to the current tile(s) already in place
CONSIDERED APPROACH
Q How many sides are different?
IE how many matches are there?
therefore 9 X 4 = 36 sides / 2 ( since each side "must" match at least 1 other side )
otherwise its an uncompleteable puzzle
NOTE: at least 12 must match "correctly" for a 3 X 3 puzzle
label each matching side of a tile using a unique letter
then build a table holding each tile
you will need 4 entries into the table for each tile
4 sides ( corners ) hence 4 combinations
if you sort the table by side and INDEX into the table
side,tile_number
ABcd tile_1
BCda tile_1
CDab tile_1
DAbc tile_1
using the table should speed things up
since you should only need to match 1 or 2 sides at most
this limits the amount of NON PRODUCTIVE tile placing it has to do
depending on the design of the pattern / picture
there are 3 combinations ( orientations ) since each tile can be placed using 3 orientations
- the same ( multiple copies of the same tile )
- reflection
- rotation
God help us if they decide to make life very difficult
by putting similar patterns / pictures on the other side that also need to match
OR even making the tiles into cubes and matching 6 sides!!!
Using TDD,
you would write tests and then code to solve each small part of the problem,
as outlined above and write more tests and code to solve the whole problem
NO its not easy, you need to sit and write tests and code to practice
NOTE: this is a variation of the map colouring problem
http://en.wikipedia.org/wiki/Four_color_theorem