Numberlink/Flow Game: How to spot NP-Complete problems? - algorithm

I was trying to find a way to solve the problem in the famous game Flow. http://moh97.us/flow/
After googling I find out that this is a NP-complete problem. A good solution would make use of heuristics and cuts. How can I spot a NP-complete problem easily? Sometimes when I block, I can't see the obvious solution. When this happens with an NP-complete, it's better to recognise it quickly and move on to the next problem.

When you have an explosion of objects (say objects whose count grows
exponentially based on some parameter or parameters), this should point
you in the direction that it's an NP-complete problem. When you
have to inspect, check too many objects (combinatorial or others).
Usually these objects are subsets or sub-spaces of some initial
object space. You should build some intuition for this. But as usual,
the intuition lies sometimes (I've been lied like this by my intuition
on 2-3 occasions).
Then once you suspect some problem is NP-complete, just
Google for it and try finding more information about
the same or about a similar problem.
This is what I do at least and I've been
solving quite a few algorithmic problems
some time ago.
Here is a nice problem which I am pretty sure
is NP-complete but which can be solved through
a genetic algorithm for example.
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=973
And as Dukeling said, there's no generic way of doing this.

There's no easy generic way of doing this. It basically comes down to reducing some known NP-complete problem to solving this problem, or showing that they are equivalent.
So, learn more about well-known NP-complete problems and get more experience with reducing a problem to solving another problem and identifying equivalent problems.
Disclaimer: You just have to be careful of special cases of NP-complete problems - while the generic case of the problem may require exponential time to be solved, these special cases may actually be solvable in polynomial time.

Related

NP-complete problems

I have come into NP-complete problems and I can't tell when the problem is NP-complete.
Is there a shortcut to know whether a given problem is NP-complete or not so that I don't waste time thinking about a fast algorithm?
The only easy way to show that a problem is NP-Hard is to convert an already known NP-complete problem into this problem in polynomial time. Meaning the conversion should be calculated in polynomial time with respect to the size of the input. In this case, you know that the problem you have is NP-Hard, which means it is at least as hard as NP-Complete but may be more difficult.
At this point, you could stop trying to find a solution for it.
But if you also need to show that it is NP-complete, then you need to show that a solution could be check in polynomial time.
There is no easy way.
If you can transform a known NP-complete problem in an instance of your problem in polynomial time, than you know that your problem is also an NP-complete problem.
If you cannot find such a transformation, you simply don't know if it is NP-complete.

Is applying AI ok and/or practical to finding the optimal solution to the algorithmic problem

Both in learning environment and practice, from time to time I had to use different algorithms to solve problems. But the more I use them, the more it seems like the AI could be deployed to try finding the optimal solution, especially to the NP-complete problems, since the AI "progression" is easily tracked
If we, for example, never knew how to solve knapsack problem efficiently; I wonder, is applying AI practical and/or ever OK to finding the optimal solution to the given problem?
AI algorithms in general can find an approximation to basically any function. They are so powerful because this is true even for extremely complex functions with many input parameters and/or many output parameters and/or a very complicated internal structure.
On the other hand, there is no known way to solve NP-complete problems "quickly". In practice, you would often have to search through a huge solution space for finding the optimal solution. This is why people use heuristic methods and approximation algorithms to efficiently find a "sufficiently good" solution.
So yes, you can use AI to find a good approximate solution (and possibly even a better one than with traditional heuristics) to a computationally hard problem.
But no, if the problem is NP-complete, you still cannot know that you have found the optimal solution.

Example of an undecidable that is not NP-hard?

Can someone give me an example of an undecidable problem that is not NP-hard?
I'm unable to understand the difference between the two.
Thanks very much!
An NP-hard problem is one such that every problem in NP can be reduced to it. In fact, it is "at least as hard as" the problems in NP class. For example, TSP (Traveling Sales Person) is NP-hard. However, undecidable is a problem for which there is no algorithm that always decide correctly. For example, the question of whether a program halts at some point or not is undecidable. In fact, you may not have an algorithm that can answer this question correctly for all programs in the world. (This can be proved)
So, in brief, an undecidable problem is logically hard; no matter how strong your computers or algorithms are, they cannot be solved. But, NP-hard problems have algorithms to be solved with but those algorithms are not polynomial in time.

How to spot a "greedy" algorithm?

I am reading a tutorial about "greedy" algorithms but I have a hard time spotting them solving real "Top Coder" problems.
If I know that a given problem can be solved with a "greedy" algorithm it is pretty easy to code the solution. However if I am not told that this problem is "greedy" I can not spot it.
What are the common properties and patterns of the problems solved with "greedy" algorithms? Can I reduce them to one of the known "greedy" problems (e.g. MST)?
Formally, you'd have to prove the matroid property of course. However, I assume that in terms of topcoder you rather want to find out quickly if a problem can be approached greedily or not.
In that case, the most important point is the optimal sub-structure property. For this, you have to be able to spot that the problem can be decomposed into sub-problems and that their optimal solution is part of the optimal solution of the whole problem.
Of course, greedy problems come in such a wide variety that it's next to impossible to offer a general correct answer to your question. My best advice would hence be to think somewhere along these lines:
Do I have a choice between different alternatives at some point?
Does this choice result in sub-problems that can be solved individually?
Will I be able to use the solution of the sub-problem to derive a solution for the overall problem?
Together with loads and loads of experience (just had to say that, too) this should help you to quickly spot greedy problems. Of course, you may eventually classify a problem as greedy, which is not. In that case, you can only hope to realize it before working on the code for too long.
(Again, for reference, I assume a topcoder context.. for anything more realistic and of practical consequence I strongly advise to actually verify the matroid structure before selecting a greedy algorithm.)
A part of your problem may be caused by thinking of "greedy problems". There are greedy algorithms and problems where there is a greedy algorithm, that leads to an optimal solution. There are other hard problems that can also be solved by greedy algorithms but the result will not necessarily be optimal.
For example, for the bin packing problem, there are several greedy algorithms all of them with much better complexity than the exponential algorithm, but you can only be sure that you'll get a solution that is below a certain threshold compared to the optimal solution.
Only regarding problems where greedy algorithms will lead to an optimal solution, my guess would be that an inductive correctness proof feels totally natural and easy. For every single one of your greedy steps, it is quite clear that this was the best thing to do.
Typically problems with optimal, greedy solutions are easy anyway, and others will force you to come up with a greedy heuristic, because of complexity limitations. Usually a meaningful reduction would be showing that your problem is in fact at least NP-hard and hence you know you'll have to find a heuristic. For those problems, I'm a big fan of trying out. Implement your algorithm and try to find out if solutions are "pretty good" (ideal if you also have a slow but correct algorithm you can compare results against, otherwise you might need manually created ground truths). Only if you have something that works well, try to think why and maybe even try to come up with proof of boundaries. Maybe it works, maybe you'll spot border cases where it doesn't work and needs refinement.
"A term used to describe a family of algorithms. Most algorithms try to reach some "good" configuration from some initial configuration, making only legal moves. There is often some measure of "goodness" of the solution (assuming one is found).
The greedy algorithm always tries to perform the best legal move it can. Note that this criterion is local: the greedy algorithm doesn't "think ahead", agreeing to perform some mediocre-looking move now, which will allow better moves later.
For instance, the greedy algorithm for egyptian fractions is trying to find a representation with small denominators. Instead of looking for a representation where the last denominator is small, it takes at each step the smallest legal denominator. In general, this leads to very large denominators at later steps.
The main advantage of the greedy algorithm is usually simplicity of analysis. It is usually also very easy to program. Unfortunately, it is often sub-optimal."
--- ariels
(http://www.everything2.com/title/greedy+algorithm?searchy=search)

DP approach for the n-puzzle problem

is there a DP approach for the n-puzzle problem
thanks all, appreciate that...
rajan
Dynamic Programming is a technique used to solve problems by reducing difficult cases to simpler cases, recursively, until you reach a case simple enough to solve "by inspection". Therefore, there can only be a sensible DP approach to the n-puzzle problem if, at each stage, you can consider a move which reduces the complexity of the problem.
For instance, if the first "move" in a n-puzzle always made it into an "(n-1)-puzzle" (for some concrete definition of "move", and assuming an (n-1)-puzzle made sense), then you could apply DP, eventually solving the "1-puzzle", and composing back upwards to solve the n-puzzle.
I don't know of any such simplification process for the n-puzzle; and I can't think of one at the moment. However, that doesn't mean one doesn't exist.

Resources