Ces
Ces

Reputation: 343

SWI-prolog to C# assert not working

I'm working on a solution using the SbsSW.SwiPlCs dll for integration between a C# application and a prolog .pl source file, however I'm facing a problem with the assert(atom) command.

My prolog file is a set of airports and flights between airports, during my running time I assert new airports and flights like this:

        internal void alta(Flight new)
    {
        try
        {
            PlEngine.Initialize(new string[] { "" });
            //PlEngine.Initialize(param);

            PlQuery.PlCall("consult(vuelos)");

            //comando
            //flight(v01,bra,ams,1000)
            PlQuery q = new PlQuery("assert(fligth(" + new.id + "," + new.airportFrom.id + "," + new.airportTo.id + "," + new.price + "))");
        }
        catch (PlException e)
        {
            Console.WriteLine(e.MessagePl);
            Console.WriteLine(e.Message);
        }
        finally
        {
            PlEngine.PlCleanup();
        }
    }

This runs fine, and I don't get any error message nor exceptions (I used to get one, but it was because my flight/4 and airport/2 statements were static, I changed both to dynamic at the beggining of my file and no errors were thrown).

My problem is when I try to consult something involving the new asserts I got at runtime.

internal List<string> directFlight(Airport from, Airport to)
    {
        List<string> list = new List<string>();

        try
        {
            PlEngine.Initialize(new string[] { "" });
            //PlEngine.Initialize(param);

            PlQuery.PlCall("consult(vuelos)");

            //comando
            //una_escala(W,from,to)
            using (PlQuery q = new PlQuery("directF(W," + from.id + "," + to.id + ")"))
            {
                foreach (PlQueryVariables v in q.SolutionVariables)
                {
                    list.Add(v["W"].ToString());
                }
            }
        }
        catch (PlException e)
        {
            Console.WriteLine(e.MessagePl);
            Console.WriteLine(e.Message);
        }
        finally
        {
            PlEngine.PlCleanup();
        }

        return list;
    }

My List<string> list variable should return the list of all the flight id's which go from from to to, and this works with pre-loaded flights (the ones on my vuelos.pl which I call on PlQuery.PlCall("consult(vuelos)");), but I doesn't take into account any of my new flights created at runtime and I can't figure out why.

Upvotes: 1

Views: 517

Answers (1)

Ces
Ces

Reputation: 343

My error consisted on two malpractices. First, I cleaned my PlEngine everytime I executed a query

        finally
    {
        PlEngine.PlCleanup();
    }

What I did in order to fix this, is to just initialize my PlEngine one time at my class constructor Class Prolog, that way I can use the same PlEngine for all my methods. I've looked around and seemingly another solution would be to use the ? tell('file.pl'), append(listing(atom)), told. to save the file at runtime, but I'm not aware if it can corrupt my previous data, so I chose the PlEngine workaround. It doesn't save volatile data, but works fine for one Prolog session. I still created a method to clean the engine, which I call when I terminate my program.

The other issue I found, is that I tried to execute the assert parameters like this:

PlQuery q = new PlQuery("assert(fligth(" + new.id + "," + new.airportFrom.id + "," + new.airportTo.id + "," + new.price + "))");

When I should have done:

PlQuery.PlCall("assert(fligth(" + new.id + "," + new.airportFrom.id + "," + new.airportTo.id + "," + new.price + "))");

PlQuery is exclusive for requests who return variables from what I could grasp, while PlCall is used for simple consults or instructions which return a true/false.

Hope this helps anyone.

Upvotes: 0

Related Questions