Slashdot Mirror


Building Intelligent, Rule-Based Applications?

Donald Hughes asks: "What are good approaches for building intelligent, rule-based applications? In particular, I typically build ASP.Net applications. I came across P#, which translates Prolog into C#. I also came across NxBRE, which touts itself as the first open-source rules engine for the .Net platform. Currently, the intelligence in my applications consist of data stored in the database, which is either processed in T-SQL or in a C# class using linear conditional logic. This approach works fine to a point, after which the complexity of the if/then statements becomes extremely difficult to manage. This is especially problematic when returning to a project after several months of not looking at it, or when someone needs to be introduced to it for the first time. Does anyone have some helpful advice?"

57 comments

  1. Generator? by Usquebaugh · · Score: 2, Interesting

    I'm not an AI or Prolog type person. But if there are a lot of conditional statements that are based upon some know steps then generating them might be an idea.

    Of course I tend to be slightly biased towards generators as they save me days of coding and testing in my current job.

    1. Re:Generator? by Anonymous Coward · · Score: 0

      I am surprised nobody said anything about CLIPS... http://www.ghg.net/clips/CLIPS.html

      If the problem is complex, then this may be the right annswer...

  2. Here's what you do: by Anonymous Coward · · Score: 0

    Create some intelligent rules, then base your application on them. It is easier than making a peanut, butter and jelly sandwich.

  3. P# / LISP by johaness · · Score: 3, Interesting

    there is a prolog compiler for .net around:
    http://www.dcs.ed.ac.uk/home/jjc/psharp/psharp-1.1 .3/dlpsharp.html

    as you can implement a prolog interpreter in 30 lines of lisp, you might also want to check lisp.net compilers ;)

    1. Re:P# / LISP by Anonymous Coward · · Score: 0

      Errr, he mentioned P# in his post...

  4. just start refactoring by Anonymous Coward · · Score: 5, Interesting

    I'm not sure I understand the question but you definitely don't want if/then statements in rule-based programming. You basically want to create a separate function for each "if" and each "then", and then declare the relationship between them.

    For example (I'm just making this up off the top of my head, and using Ruby syntax), you might want to call "customer.save" to send a customer object to the database. You can't call this function until the customer object has had certain things happen to it, for instance "not customer.empty?" must return true. "customer.agreed_to_terms?" must return true. Each of these tests might itself depend on other tests, and so forth. And some tests might need input from the user, or the result of a complex calculation, or whatever.

    Just write a function for each and then write some generic code that doesn't call a function until all the dependencies return true. This is like, 5 lines of code.

    You can configure the relationships with a simple text file. This is a very powerful system. An analogous system for shell scripts would be Makefiles.

    This is super-easy in Lisp, Ruby, etc., not sure about .NET languages, but I'm sure it can be done with a little reflection (pun intended).

    This is a really easy and powerful concept once you figure it out. Basically your code will "discover" the proper order to do things in based on the dependencies.

    A further step is to encode the state of your app in a tuple (an array), and use tuple spaces to distribute work among many machines. It's quite magical when you've got it all working right.

    Study the prolog examples as well, Prolog basically generalizes this procedure even more.

    1. Re:just start refactoring by Enonu · · Score: 2, Insightful

      Yes. Re-invent the wheel. A wheel that weakly does something specialized languages do extremely well. Let me go get that hammer to do the welding while we're at it.

    2. Re:just start refactoring by Derleth · · Score: 2, Insightful
      Yes. Re-invent the wheel. A wheel that weakly does something specialized languages do extremely well. Let me go get that hammer to do the welding while we're at it.

      You're exactly right: Most languages have very weak support for that kind of dynamic, introspective, functional programming. It would be ugly in C, for example, and impossible in Fortran. (In theory, everything is possible in every Turing-equivalent language. But eventually you blow out all your tendons and have to be put in a madhouse.) You should always fit the language to the strategy.

      Except when that would be even more painful. Calling system APIs from Lisp, for example, is getting a hell of a lot better on most systems from most Lisps, but there are systems where it's even more of a pain of the ass than coding up data-driven code in C. Perl and Ruby and Python have taken off because they've made it possible to use a moderately pleasant language without screaming in agony every time you need to touch an API, but very few of the specialized languages are that obliging on most systems.

      So by all means advocate the right language for the job, but remember that the job may be more complex than you think.

      --
      How can you use my intestines as a gift? -Actual Hong Kong subtitle.
    3. Re:just start refactoring by Anonymous Coward · · Score: 0

      "I'm not sure I understand the question but ..."

      don't let that stop you.

  5. Book by bearclaw · · Score: 3, Informative

    You might want to check out Enterprise Patterns and MDA : Building Better Software with Archetype Patterns and UML (Addison-Wesley Object Technology Series) by Jim Arlow and Ila Neustadt. They present a decent model to describe rules.

    --
    -- bearclaw
  6. Newbie C++ Programmer Question From The Fat Guy... by __aaclcg7560 · · Score: 1

    What's intelligent, rule-based application design? Is it different from pattern design?

  7. Constraints by suricatta · · Score: 0, Redundant

    Maybe make another data structure which contains a list of constraints, sort of like a data representation of all of those if-then-else statements. You can customise the data structure and make it as simple or as complicated as it needs to be to support the processing of those rules.

    That way, you can also associate comments and descriptions with those rules which might make it easier to come back to or introduce new people to. Especially if you represent the rules in a particularly user-friendly way (eg. In a database or an XML file as opposed to a binary dump of your data structure into a file) then you allow for simple editting of these constraints using existing tools, and as an added bonus, avoid the need for a recompile each time the constraints need to be changed.

    Of course, the disadvantage of this approach is slower execution of your code. If that is a priority then this wouldn't be the best idea :)

  8. Finite State Machine by the+eric+conspiracy · · Score: 3, Informative


    Depending on what you are doing a finite state machine could be a good answer. Take a look at the state machine compiler (SMC) on sourceforge.

    1. Re:Finite State Machine by townbully · · Score: 0

      Check out the spirit parser for the boost project. Define your grammars and parse your way to the end of the rainbow.

    2. Re:Finite State Machine by thelibrarian · · Score: 1

      Here is a good article on implementing State Machines (PDF link):

      http://www.pragmaticprogrammer.com/articles/nov_02 _state.pdf

    3. Re:Finite State Machine by clone22 · · Score: 1

      I'm a big fan of state modeling and state machines and use them for creation of natural voice processing applications. It sounds like the OP may have difficulty formulating complex transition conditions. One solution is to encode the transition rules (T) and rule space (R) as bit fields, such that a transition occurs where:
      T & R = T

      --
      Ask me about my vow of silence!
  9. Mercury .NET by aminorex · · Score: 1

    Mercury might almost be considered a dialect of Prolog, and offers a .NET compiler, in case you need it. http://mercury.sf.net/

    --
    -I like my women like I like my tea: green-
  10. Re:Newbie C++ Programmer Question From The Fat Guy by Sam+Ritchie · · Score: 1

    Roughly (and correct me if I'm wrong), a rule-based application is one that stores formulae, business/validation rules, process orchestration steps etc as dynamic data, usually in a database.
    The application will load and interpret the rules in order to perform processing functions; and the rules can be modified at runtime, typically by expert users or adminsitrators.

    --
    This sig is false.
  11. Questions by Anonymous Coward · · Score: 0

    What is this application?

    What kind of "rule based" application has so many if/else tests that it becomes unmanagable?

    I know of Prolog and I have seen expert systems running based on this type of logic but I have always seen that type of design as flawed. It is much better to write a simple algorithm that can then more generically handle rules which are stored somewhere else (possibly not in the code at all). I don't see the point of building complex rules right into the code. All that does is add bloat and make the code unmanagable.

  12. basic question by astrashe · · Score: 2, Interesting

    What kinds of problems would you solve with a prolog type system?

    I've read about prolog, going back for years (it was a scare, a long time ago, in the '80's, I think -- the japanese were spending government money on prolog type logic systems, and they were going to bury us), but I've never really understood how it plugs into the real world.

    I mean, if you're doing something practical, what does it do for you?

    Even this question is pretty vague... I don't have any idea of what the poster wants the thing to do.

    1. Re:basic question by dlakelan · · Score: 2, Informative

      Rule based programming's purpose is to solve a problem that requires complicated logic by declaring what the relationships are, instead of describing a procedure that solves the problem.

      The advantage in these sorts of uses is that you can reason about the declarative program much easier than you can about the set of steps that you would write down in a procedural language.

      SQL is a kind of declarative language that you might be familiar with. Although it is much less powerful than say prolog, its advantages for searching for information over something like a bunch of perl code are clear. Instead of describing how to search through the tables, you tell the database what the properties are that you're looking for.

      Code that becomes nearly trivial in prolog often would look like some kind of nested case statement with exception handling in C++ for example.

      Like many thing in programming, the declarative method is good for some things and less good for others.

      --
      ((lambda (x) (x x)) (lambda (x) (x x))) http://www.endpointcomputing.com a scientific approach to custom computing.
    2. Re:basic question by astrashe · · Score: 1

      I understand that (sort of), but could you give an example of a specific problem that fits this type of solution?

    3. Re:basic question by darnok · · Score: 4, Informative

      How about this: consider an institutional currency trading system, such as those used by banks to hedge their currency positions.

      You need a set of rules about when traders can go ahead and execute a particular trade. For example, if the bank already has a huge stash of Japanese yen, they might not want to buy any more (regardless of the price); they'll have a particular risk profile that each trade must fall into.

      Now, the people who write the code to check how much the bank holds in Japanese yen at a particular point in time, will almost certainly NOT be the people who create and maintain the risk profiles that the bank needs to trade under when it buys or sells yen. The first set of guys will probably be full-time "normal" programmers who reference stuff out of one or more databases; the second set of guys will be trading management type people. While there's obviously a level of synergy required between the two, they're unlikely to (want to) sit and work together on a regular basis.

      So far, it's not that unusual a problem.

      Where it gets interesting is that both areas tend to be very dynamic: the definition of a good risk profile tends to vary over time, and the way of calculating current positions in Japanese yen may also change over time (as the bank starts/stops trading in different exchanges, as the bank opens/closes trading rooms in different parts of the world and different timezones, and so on).

      Where rule-based apps shine in this scenario is that the two requirements can (and should) be largely separated. Provided the data coming from the data guys can be kept valid (which can be a huge challenge in itself), there's no reason for the risk management guys to be aware of where that data comes from or to question its integrity; they should be adjusting risk profiles via a rules-based mechanism rather than a programming mechanism that requires them to understand anything more than the actual values of the data.

      Their rules may include things like "if we're going to buy more yen, we have to sell Brazilian real because we believe there's a relation between the two"; sure, you could employ a regular OO-type coder to do this stuff, but it's much quicker/safer for the guys making such rules to implement them in a rules engine. In this scenario, when a trader puts in a request to buy more yen, it will have to be matched with the amount of Brazilian real that has been sold to see if the appropriate ratios exist to allow the yen trade to go through.

      Frequently, things get much more complicated than that, and maybe you'll have to deal with half a dozen other factors as well; this is a simplistic example that could probably be done with a few Excel macros and stored procs, but hopefully you can see how the complexity could scale to the point that a rules-based approach becomes significantly better than "traditional" alternatives as the problem becomes less and less trivial.

    4. Re:basic question by astrashe · · Score: 1

      That's actually pretty helpful, and a good illustration.

      Thanks very much for taking the trouble.

    5. Re:basic question by Zebra_X · · Score: 1

      Wow. The first civil post ever on slashdot!

      Is the sky falling?

    6. Re:basic question by Anonymous Coward · · Score: 0

      maybe a new mod for civil rewards.

      we have funny rewards, insightful, troll, why not a civil....

  13. Table Oriented Programming by Tablizer · · Score: 2, Interesting

    One approach is to have a database table with the rules in them. Example schema:

    table: rules
    ----------------
    ruleID
    ruleDescript
    expression // example: "x > 3 and y == 7"
    ifTrueSnippet // what to execute if true
    priority // order of execution

    This allows one to easily create a log of the of the rules and their result. Note that it takes a fairly dynamic language to impliment this so that it can execute code snippets from a database. You probably would want to go with something like Python or PHP instead of C++.

    However, I am skeptical any such tool can be as flexible as just plain IF statements in code. But it may be useful for non-programmers, yet power-users to manage the rules themselves. The "ifTrueSnippet" may instead be predefined operation names rather than code in that case. And, maybe a parameter column or two may be in order, depending on the domain.

    -T-

    1. Re:Table Oriented Programming by daveinthesky · · Score: 1

      Note that it takes a fairly dynamic language to impliment this so that it can execute code snippets from a database

      Hence you'd probably want to write it in lisp so you can do away with that whole useless data vs. code dichotemy ;-)

      You can probably find some decent rule-system implementations floating near academia if you dig.

    2. Re:Table Oriented Programming by Tablizer · · Score: 1

      Yes, but Lisp tends not to have good RDBMS drivers and tools for it; and also it's native expression syntax is too foreign to most power users. People grow up in an infix world for good or bad.

      Hmmm. What about TCL?

    3. Re:Table Oriented Programming by ZenFu · · Score: 2, Interesting

      I haven't thought this through, but after reading your post and following through on the path of another post, I came across the following regarding the Rete alogorithm.

      The rete algorithm appears to relate to creating a tree structure where each node is a rule and each leaf is a function. So, as the process goes from node to node, and the process evaluates rule after rule, the process comes to the final leaf and calls the desired function.

      Celko's books deal with the implementation of trees in databases and he's written some other articles as well.

      So, perhaps a person could also handle the rules in the database by a Rete (there's also a Rete 2) algorithm based on nested sets.

    4. Re:Table Oriented Programming by jbplou · · Score: 1

      Your not suggesting he move away from .NET to PHP are you to perform better business logic?

    5. Re:Table Oriented Programming by Anonymous Coward · · Score: 0

      You think lisp doesn't have good RDBMS tools??? CLSQL http://www.cliki.net/CLSQL runs rings around most any other DB interface I've seen, while AP5 (http://www.ap5.com/) has been the "real relational system, not pseudo-relational SQL" you tend to drone on about for YEARS already (though its licensing is problematic for Open Source people, as it's not freely redistributable, the author just publishes the source without a copyright license as far as I can see (so AFAIK it defaults to closed under the current (stupid) copyright system)).

      A "power user" is NOT a power user if he can't cope with prefix syntax - e.g. almost all of C is prefix syntax: print("xyzzy"), OpenWindow(x,y,z) etc. Only difference is in lisp, the function name is the first thing inside the bracket, spaces as argument separators instead of commas, and C has a SMALL number of infix operators that you COULD emulate with macros in lisp if you were a masochist. APL on the other hand is a pervasively-infix language.

  14. Ilog by popeyethesailor · · Score: 1

    If you have a complex enough set of rules, it might be better to pony up the licensing costs for Ilog. It's native .NET code, and very capable.

    1. Re:Ilog by smileyy · · Score: 1

      As long as you're ready to pay licensing costs in the 6 figures. Ouch!

      --
      pooptruck
    2. Re:Ilog by popeyethesailor · · Score: 1

      Yep.. But insignificant for a $10M project isnt it ;)

  15. Switch methodologies by Anonymous Coward · · Score: 0

    if/then rules systems (aka expert systems) are know to have this kind of problem.
    There's no magical bullet, just switch methodologies, ej, statistical rule construction methods.

  16. Regression testing by EvilAndrew · · Score: 2, Interesting

    As other people have suggested, one path is to invest in an expert system. You haven't mentioned how many rules your expert system consists of, and you may switch to some other expert system to find that it hasn't improved your capability to manage your rules. Regardless of whether you switch or not, I cannot overemphasize the importance of having a good suite of regression tests for your rules.

  17. Java Rules Engines by Nazrax · · Score: 4, Informative

    I know the original poster typically builds .NET applications, but for those times when you want to do this in Java, there are at least two good engines: http://www.mandarax.org/ is a backwards-chained engine (like Prolog), and http://www.drools.org/ is a forward-chained engine (takes action based on input).

  18. SQL Server 2005 Recursive Queries by toady · · Score: 1

    I haven't used these in real life, but they seem like they could be quite useful in your rule-based situation:

    Recursive queries in SQL Server 2005

    --
    In Soviet Russia, the readers moderate YOU! Wait a second...
  19. Take a look at CLIPS by DarkCoffee · · Score: 1

    http://www.ghg.net/clips/CLIPS.html It's C based, mature, multi platformed and easy to interface to (if you can code in C). Currently it has interfaces to Python, PHP and Java.

    --
    -- Before you do anything you can't undo, always understand all the things you can't do once you've done it.
  20. intelligent approach? depends on the given problem by ranjix · · Score: 2, Interesting

    I'll keep it short.

    1. there is no way to completely get rid of if/then statements. they'll be somewhere. What's good with CLIPS or so is that there is not much else than the if/thens of the rules, so you don't get lost in memory allocation and the rest of the bull. On the other hand, the rules (and facts) tend to be localized in the same file, you don't have to read 200 classes of assembler (:-)) files to find all of them

    2. depending on the nature of dynamics of your rules , if you don't have that many rules (20-30???) you can use simple (or complicated) if-then statements as long as you DOCUMENT THEM WELL!!! so the next john (or yourself) can pick up the work from there. hmm, this kind'a makes me think

    3. if the rules are VERY dynamic (or just too many of them), a more general approach will be needed. Welcome CLIPS or other rule-based expert system. I heard fairy-tales with systems with tens of thousands of rules, so probably it works.

    4. How you store the rules, is completely your business, I don't see any problem storing them in a database, file or on a rice, written by a very old and pacient chinese.

    5. from the practical standpoint, the problem with the rules is a very general one. how do you connect a lot of facts with a lot of rules? answer? algorithms - check RETE, check hashes, I'll stop here gasping for air short of ideas.

    6. how do you apply the rules, in which order? this is another issue, related to the given problem. see the depth, width or jumpy :-) searches... all the rules based systems have this issue, again the answer will be depending on the problem.

    7. another issue, thread safety, parallelism. how do you synchronize all of these?

    and I think I forget something... hmmm... did I turn off the stove...?

    --
    I had another sig before, but this one is better
  21. A few practical questions... by LWATCDR · · Score: 1

    Who is going to maintain the code you write? Is this just for you, a company you work for or a company you are starting?
    If it is just for you it really does not matter.
    If it a company you work for you may want to check. I had a guy working for me that wanted to write everything in FoxPro because that is what he knew. I told him no but he wrote some little utilities for a different department. He left and no one knows how modify his code. That goodness they were trivial.
    If it is a company you are starting. Will you have the time to support your own code? How hard will it be to find someone that can do it for you if you get too busy.

    --
    See my blog http://ilovecookes.blogspot.com/ for light hearted technical information.
  22. Rules Engine... by Trubetskoy · · Score: 2, Informative

    I am a PROLOG practitioner and I work in the field of AI, specializing in complex systems. Prolog is an excellent choice when the rules become unusually complex. You don't need a translator or compiler if you use Amzi! Prolog. You can generate compiled modules and call them via a DLL. No problem there. Check them out at www.Amzi.com. As to maintainability, any complex system can become formidable. Prolog will make long-term maintenance easier, not harder. Let me know if I can help. Best wishes, Burt Pierce

  23. BizTalk Server if you have MSDN by Anonymous Coward · · Score: 0

    Amzi and ILog, mentioned by other posters, are superior, but if you have an MSDN subscription, BizTalk has a built-in forward-chaining rules engine. However, the problem of maintaining a large amount of rules doesn't go away just because you use a rules engine, Prolog, or what-have-you. One of the problems with expert systems is that the explicit un-coupling of rules from execution logic can lead to surprises. If the developer then tries to fix the problem by adding new rules to patch the issue, things can get baroque very fast. Often, a "rules patch" is an attempt to impose imperative flow-control via rules, which is a foolish thing to do. That's why the best rules-based systems almost always use a hybrid of imperative code and rules.

  24. Off topic, of course... by cr0sh · · Score: 2, Funny
    Let me go get that hammer to do the welding while we're at it.

    Actually - this is possible - it is called (IIRC) "forge welding" - basically, you get both of your pieces of steel super red hot, place them one on top of the other on an anvil, and pound them as hard as you can with your blacksmith's hammer. This may require more than one person to accomplish, and you need some good strength, because you have to pound that shit HARD. Plus, you need to keep it red hot as you work it. In the end, though, with a bit of patience and skill you will end up with a single piece of steel which can then be worked further.

    BTW - this was one of the steps in the making of the "folded steel" (can't remember its true name) samuri swords - basically, getting the steel red hot, folding it over, pounding it flat (and welding it together), pounding it out and stretching it, folding it again, pounding it (welding), etc - until you had the material ready, then continue shaping it into the sword (actually, these swords are much more complicated than this - but that is the basic process - the original method was lost, but they have recreated the method in modern times)...

    --
    Reason is the Path to God - Anon
  25. Domain-Specific Language by Vagary · · Score: 1

    Depending on what kind of logic you're trying to code up, you might find it easier to create a domain-specific language that allows coding in whatever paradigm is most appropriate rather than having to shoehorn everything into logic-language assertions. Haskell is considered one of the best languages for create DSLs (my favourite example is a DSL for financial contracts which I was reminded of by this post); however, like most non-Microsoft, non-trivial languages, it is very difficult to port to the .Net CLR.

  26. Die, Anti-Lisp Bigot! by Vagary · · Score: 1

    Lisp might not be good for RDBMS, but the close correspondance between S-expressions and XML might be extremely helpful if the application is distributed. And anyone who is willing to code rules in Prolog should have no problem with prefix syntax and higher-order functions.

    High-end programmers should have no problem switching between prefix and infix: it's only cog-like code monkeys who insist that the most popular languages have C-like syntax. Experts will continue to implement obscure applications in obscure languages for obscene pay.

  27. Ruby Cowboys by Vagary · · Score: 1
    What is it with script programmers with delusions that their languages are panaceas? The languages are created for rapid prototyping and tiny applications, then they get crufted into larger and larger domains. Repeat after me:
    OO is not the one true paradigm.
    Weak and Dynamic is not the one true typing.
    Interpreted is not the one true execution mode.
    My language is not the one language to rule them all.
    This could be a mature application with business analysts and real money on the line, he doesn't care about your toy solution.
    1. Re:Ruby Cowboys by szaz · · Score: 1

      What a load of bollocks. I assume you're out of work at the moment... right?

    2. Re:Ruby Cowboys by Vagary · · Score: 1

      Even worse: I get paid to write C#! :(

  28. You Mean Translator? by Vagary · · Score: 1

    Why would you write rules that get translated into an intermediate language when you could write what academics call a "compiler" for translating the rules directly into an executable or an "interpreter" for evaluating the rules on the fly? Generators are a sign of an inflexible, poorly designed language (I should know: I get paid to write C#!).

  29. Seconded by SteeldrivingJon · · Score: 1


    A friend of mine used CLIPS in a system for a drug store chain, which provided suggestions to customers depending on what they purchased.

    --
    September 2011: Looking for Cocoa/iOS work in Boston area Cocoa Programmer Quincy, MA
  30. CLIPS by donpellegrino · · Score: 1

    "CLIPS: A Tool for Building Expert Systems"
    http://www.ghg.net/clips/CLIPS.html

  31. Usually you don't need it by Alex+Belits · · Score: 1

    Very rarely the answer is Prolog.

    For the rest of cases, building your own rule processing engine that serves a particular purpose and interacts with the rest of the system, is such an easy task, it is not worth generalizing.

    For $deity sake, netfilter has some (simple) rule-based processing, and it's merely a small piece of code inside the Linux kernel.

    --
    Contrary to the popular belief, there indeed is no God.
  32. The mods are IDIOTS!!!!! by cr0sh · · Score: 1
    Funny? Why is this post modded as "funny"? Do the mods think that the method of "forge welding" is something that I picked out of thin air after playing one too many sessions of WoW? Not that I have ever played that game; I actually have a life and I learn about and practice real-world skills, like welding!

    Need proof that this is a real form of welding? HERE IS YOUR PROOF

    A couple of excerpts from the site:

    Forge welding is the core technique involved in creating Damascus steels. It is a solid-phase bonding technique that uses heat and pressure to make the weld. To make Damascus steels the current method is to stack alternating pieces of steel, each with a contrasting composition, heat the billet in a fire and at the proper temperature apply pressure to make the weld.

    and

    You may vary the way you fold the billet. The Japanese method of making sword steel involves forging the billet wide and cutting down the middle and folding side to side. Any change will affect the look of the steel and may yield some interesting patterns.

    I know in general the population is filled with masses of individuals ignorant in how the world came to be shaped by mankind over the centuries. I would expect responses of laughter and jeering "from the pit" on a site like Fark, for instance, where you have a more homogenous mix of the ignorant and the intelligent.

    I expect more from the denizens Slashdot, though. I find it absurd that a site supposedly for geeks, by geeks, a site set up for intelligent people to express and judge each other's comments about posted articles and other comments about the world; is rapidly becoming a site which is attracting the unintelligent, the unimaginative, and the uninspired, while simultaneously slowing pushing out those who are 180 degrees opposite in nature.

    This is a truely sad observation, one which I know others have noted and lamented on in the past...

    --
    Reason is the Path to God - Anon