Wrapping C# with Prolog Dameon G Rogers Workflow Team – Prolog to C# Abstract The goal of getting the logical functionality of Prolog converted in a C# environment has been achieved and now the logical functionality that is required in OpenSim can be implemented for the medical simulation. 1. Problem The infrastructure teams’ main task is to assist and build all the tools and pieces that other teams may use to support their own work in OpenSim and Second Life. This includes: browser, cell phone, database, lisp, ontology and prolog integration and use along with the programs and or work that can help support the effort of integration into the OpenSim environment. The specific task of the sub-team (which includes Jerry Maine working on Lisp to C#) is to attempt the use of the advantageous properties of Lisp and Prolog, ported into C#, to affect the OpenSim world to assist with any programmed behaviors that may be desired to complete the goal of workflow implementation within a medical simulation. 2. Objective The infrastructure team is attempting on several fronts to implement certain behaviors into the OpenSim platform. These behaviors relate to infrastructure the workflow team has created to implement behaviors that would and will be useful in a medical setting to simulate the function of RFID tagging in a hospital setting. The tools are programmed for specific tasks: get blanket, push button and chat that will assist in the accurate simulation of a medical environment and allow data to be gathered with RFID. The specific task of my sub team, which includes Jerry Maine, is to try to port Prolog, which May Zeineldin created, and Lisp scripts into the OpenSim platform and allow the versatile functionality within the language type of Prolog and Lisp. Prolog is excellent for logic and state based programming, the basis of the OpenSim platform and Lisp is excellent at ordering lists which is extremely useful for the implementation of tasks that must be completed in order get the desired functionality in the virtual world. 3. Related Work Prolog Scripts. May Zeineldin. 7 Nov. 2008. http://www.csce.uark.edu/~cwt/COURSES/200808--CSCE-4313--PL/STATUS-REPORTS/HW3b/. Lisp Parsings. Jerry Maine. 7 Nov. 2008. http://www.csce.uark.edu/~cwt/COURSES/2008-08-CSCE-4313--PL/STATUS-REPORTS/HW3b/. 4. Architecture 4.1 Design The overall design of the project was ‘Workflow’ and this team was responsible for making the actual workflow of the system functional and able to complete some useful functions. The design of my subproject was to try to code some prolog functionality into C# code. C# code will run in the OpenSim platform so the process is two fold. First the Prolog code is ported into C# and then the C# is ported into OpenSim using the DotNet Engine. This allows functionality to be added to the OpenSim environment and lays groundwork for the successful testing and deployment of a virtual RFID network to improve and further explore a medical environment in OpenSim. 4.2 Testing Testing included writing C# code in Visual Studio 2008 and making sure that it compiled and was logically identical or very similar to the prolog scripts that May had written for the OpenSim platform. It compiled and ran on both Mono for Windows and Visual Studio. I also noticed that if the ‘cut’ operator is not used there will be warnings in both Mono and Visual Studio but those can be ignored. This warning message is generated because if the ‘cut’ operator is not used then those values in the parser and compiler are not used. 5. Results The testing of the conversion of Prolog to C# is a success and within the testing environments of Visual Studio and Mono the code functions correctly and also gives interesting output that will be useful to the state-based virtual world. 6. Yield Prolog Details Yield Prolog is a set of C# Windows tools that allows for the logic functionality of prolog to be coded with a DotNet Engine. When this project began, prolog was completely unknown to the sub team. The first step was to visit the main library and discover any resources that the library may have, this included a short list of books on prolog: syntax, grammar, functionality and code examples. This step took about half a month. At this point there was no viable connection between any Windows suite, web interface and prolog functionality. After a very informative and useful meeting with Dr. Thompson and Jerry Maine ‘yield prolog’ was mentioned as a possible viable synthesis of this schema to create logic behavior and functionality. Yield prolog allows almost ‘all’ the logic functionality of prolog including the cut operator for limiting the search space with prolog. It also allows for the linking of two components known as ‘atoms’ inside an object. This will let any two data structures exist in a logically linked manner. This relationship is very helpful when coding logic parameters to get a logical behavior. There are two basic methods to wrap and translate the prolog language into C# which greatly increases the available implementation and usefulness of prolog. 6.1 Method One – Translation This method allows a direct translation from prolog to the C# language and will assist with encoding prolog functions and larger prolog code, including the search limiting ‘cut’ operator. Prolog Function – Author: May Zeineldin ‘scenario10’ request(patient,'Order dinner'):-push(patient,'Call button'). push(patient,'Call button'):chat_command('Can I help you'), chat_command('Yes,I would like to order my dinner'), chat_command('Let me check the doctor’s orders'), chat_command('Yes, you can now have a regular diet,I will be right in to help you order'), goto(free_nurse,room), get(menu), chat_command('You can order one item from each category'), chat_command('What kind of soup would you like,Tomato or chicken noodle'), chat_command('chicken noodle'), chat_command('Would you like pasta, chicken or beef'), chat_command('I will take the pasta'), chat_command('That comes with a small salad,What kind of dressing would you like'), chat_command('blue cheese'), chat_command('We will bring that on the side'), chat_command('What would you like for dessert,There is chocolate cake, ice cream or apple pie'), chat_command('No dessert'), chat_command('what would you like to drink,There is coffee, tea, cola or milk'), chat_command('I will take coffee with cream and sugar'), chat_command('I will put your order in,A new menu for each meal will be on your food tray,Just turn it in with your tray each meal'), chat_command('Thank you'). Translate to C# /* * Dinner_Prolog * * This class specifies the behavior allow a patient to order dinner. * * Author: Dameon G Rogers */ using System; using System.Collections.Generic; using YieldProlog; class Dinner_Prolog { static void Main(string[] args) { Console.WriteLine("Return an action for a patient:"); Variable Request = new Variable(); foreach (bool l1 in nurseRequest("patient", "push", Request)) Console.WriteLine("Connect = " + Request.getValue()); Console.WriteLine("Unify push with action:"); Variable Action = new Variable(); Variable Move = new Variable(); Console.WriteLine("Can I help you?"); Console.WriteLine("Yes, I would like to order dinner."); Console.WriteLine("Let me check the doctor’s orders."); Console.WriteLine("Yes, you can now have a regular diet, I will be right in to help you order."); foreach (bool l1 in nurseMovement("nurse", Move, new ListPair("nurse", new ListPair("free_room", Atom.NIL)))) Console.WriteLine("The nurse location is " + Move.getValue()); foreach (bool l1 in nurseRequest("patient", Action, new ListPair("patient", new ListPair("'get menu'", Atom.NIL)))) Console.WriteLine("The action is " + Action.getValue()); Console.WriteLine("You can order one item from each category."); Console.WriteLine("What kind of soup would you like,Tomato or chicken noodle."); Console.WriteLine("Chicken noodle..."); Console.WriteLine("Would you like pasta, chicken or beef."); Console.WriteLine("I will take the pasta."); Console.WriteLine("That comes with a small salad. What kind of dressing would you like?"); Console.WriteLine("blue cheese"); Console.WriteLine("We will bring that on the side."); Console.WriteLine("What would you like for dessert? There is chocolate cake, ice cream or apple pie."); Console.WriteLine("No dessert, please."); Console.WriteLine("what would you like to drink? There is coffee, tea, cola or milk."); Console.WriteLine("I will take coffee with cream and sugar"); Console.WriteLine("I will put your order in. A new menu for each meal will be on your food tray. Just turn it in with your tray each meal."); Console.WriteLine("Thank you."); foreach (bool l1 in nurseMovement("nurse", Move, new ListPair("nurse", new ListPair("nurse_room", Atom.NIL)))) Console.WriteLine("The nurse location is " + Move.getValue()); Console.WriteLine("\nPress Enter to finish."); Console.ReadLine(); } static IEnumerable<bool> nurseRequest(object patient, object Action, object Request) { ListPair action1 = new ListPair(Action, Atom.NIL); ListPair result = new ListPair(patient, action1); foreach (bool l1 in YP.unify(Request, result)) yield return false; } static IEnumerable<bool> nurseMovement(object nurse, object Move, object Location) { ListPair move1 = new ListPair(Move, Atom.NIL); ListPair location = new ListPair(nurse, move1); foreach (bool l1 in YP.unify(Location, location)) yield return false; } } 6.2 Method Two – Wrapping This method allows a wrapping of prolog to the C# language and will assist with encoding prolog functions and larger prolog code, including the search limiting ‘cut’ operator. Prolog Function – Author: May Zeineldin ‘ scenario10‘ request(patient,sit_up):-push(patient,'Call button'). push(patient,'Call button'):chat_command('Can I help you'), chat_command('Yes,I would like to sit up'), goto(free_nurse,room), action('Bed upright position'). Prolog Function using Wrapping /* * CallNurse_Prolog * * This class specifies the behavior allow a patient to call a nurse * for assistance. * * Author: Dameon G Rogers */ using using using using System; System.IO; System.Collections.Generic; YieldProlog; class CalllNurse { static void Main(string[] args) { YP.assertFact(Atom.a("request"), new object[] { Atom.a("patient"), Atom.a("sit up") }); YP.assertFact(Atom.a("push"), new object[] { Atom.a("patient"), Atom.a("Call button") }); YP.assertFact(Atom.a("goto"), new object[] { Atom.a("nurse"), Atom.a("free room") }); YP.assertFact(Atom.a("action"), new object[] { Atom.a("patient"), Atom.a("Bed upright position")}); Variable Request = new Variable(); Console.WriteLine("Using dynamic assert:"); foreach (bool l1 in YP.matchDynamic (Atom.a("request"), new object[] { Atom.a("patient"), Request})) Console.WriteLine("Patient has request " + Request.getValue() + "."); Variable Push = new Variable(); Console.WriteLine("Using dynamic assert:"); foreach (bool l1 in YP.matchDynamic (Atom.a("push"), new object[] { Atom.a("patient"), Push})) Console.WriteLine("Patient has pushed " + Push.getValue() + "."); string prologCode = "request(Patient, sit_up) :- \n" + "push(patient,’Call button’). \n” + "goto(free_nurse, room), \n” + "action(‘Bed upright’). \n”; Console.WriteLine("\n// Compiled code:"); compileAndWrite(prologCode); Console.WriteLine("Calling compiled code having a dynamic goal:"); Variable Patient = new Variable(); Variable Request = new Variable(); foreach (bool l1 in uncle(Patient, Request)) Console.WriteLine(Patient.getValue() + " has request " + Request.getValue() + "."); Console.WriteLine("\nPress Enter to finish."); Console.ReadLine(); } static void compileAndWrite(string prologCode) { YP.tell(Console.Out); YP.see(new StringReader(prologCode)); Variable TermList = new Variable(); Variable PseudoCode = new Variable(); foreach (bool l1 in Parser.parseInput(TermList)) { foreach (bool l2 in Compiler.makeFunctionPseudoCode (TermList, PseudoCode)) Compiler.convertFunctionCSharp(PseudoCode); } YP.seen(); } public class YPInnerClass { } public static Type getDeclaringClass() { return typeof(YPInnerClass).DeclaringType; } public static IEnumerable<bool> action (object Patient, object Action) { foreach (bool l1 in YP.unify (Patient, Atom.a("Patient"))) { foreach (bool l2 in YP.unify (Action, Atom.a("Call Button"))) yield return false; } foreach (bool l1 in YP.unify (Patient, Atom.a("Patient"))) { foreach (bool l2 in YP.unify (Action, Atom.a("Upright Position"))) yield return false; } } } This code only asserts two facts dynamically for display that are actions from a patient to help to define the actions that a patient is able to perform in this specific instance to call a nurse to place a patient in the upright position. The main difference between this form of wrapper and the translation is that the facts are asserted at the beginning of the code, then the prolog code is wrapper and then inner classes are constructed to logically link and define the patient actions. More information and complete tutorials available at: http://yieldprolog.sourceforge.net/ If possible it is be to get a minimum understanding of prolog and the use of the ‘cut’ operator here: http://cs.union.edu/~striegnk/learn-prolog-now/ 7. Conclusions 7.1 Summary It was challenging to code on C# since it was a new language for this assignment but it was fun to get the functionality that is possible with Prolog into a different language and discover that the Prolog code can be wrapped with C# or converted into C# as they both work. It is also possible to code into Mono instead and not uses Visual Studio in any way. 7.2 Impact Since the logical functionality of Prolog is possible as a C# import to OpenSim this means that any and all of the functions needed to make the hospital actually work will able to support the actions needed. This means that the workflow goal of my sub team is solved and success has been achieved. 7.3 Future Work The next person needs to try to get a bigger idea of the logic needed for this project, for example, a basic set of actions and tasks that are needed to make the hospital simulation function. This will allow C# code, which behaves like Prolog, to support all the tasks and actions that are required to make the hospital function to assist in the research of workflow in a medical setting. References [1] Yield Prolog. Sourceforge.NET. 15 Oct. 2008 http://yieldprolog.sourceforge.net/index.html/.