Recursive loop exit statement needed - search

this is a simple prolog example of recursion. I cannot figure out where, and more or less how, to declare the exit statement. The test flight(sofia, dublin) should return true, but it keeps checking at the last steps if you can directFlight(dublin, dublin). Here is the code:
directFlight(sofia, varna).
directFlight(sofia, paris).
directFlight(sofia, london).
directFlight(london, edinburg).
directFlight(paris, new_york).
directFlight(new_york, seattle).
directFlight(london, dublin).
flight(City1, City2) :-
directFlight(City1, City3),
flight(City3, City2).
The output:
[trace] ?- flight(sofia, dublin).
Call: (8) flight(sofia, dublin) ? creep
Call: (9) directFlight(sofia, _878) ? creep
Exit: (9) directFlight(sofia, varna) ? creep
Call: (9) flight(varna, dublin) ? creep
Call: (10) directFlight(varna, _878) ? creep
Fail: (10) directFlight(varna, _878) ? creep
Fail: (9) flight(varna, dublin) ? creep
Redo: (9) directFlight(sofia, _878) ? creep
Exit: (9) directFlight(sofia, paris) ? creep
Call: (9) flight(paris, dublin) ? creep
Call: (10) directFlight(paris, _878) ? creep
Exit: (10) directFlight(paris, new_york) ? creep
Call: (10) flight(new_york, dublin) ? creep
Call: (11) directFlight(new_york, _878) ? creep
Exit: (11) directFlight(new_york, seattle) ? creep
Call: (11) flight(seattle, dublin) ? creep
Call: (12) directFlight(seattle, _878) ? creep
Fail: (12) directFlight(seattle, _878) ? creep
Fail: (11) flight(seattle, dublin) ? creep
Fail: (10) flight(new_york, dublin) ? creep
Fail: (9) flight(paris, dublin) ? creep
Redo: (9) directFlight(sofia, _878) ? creep
Exit: (9) directFlight(sofia, london) ? creep
Call: (9) flight(london, dublin) ? creep
Call: (10) directFlight(london, _878) ? creep
Exit: (10) directFlight(london, edinburg) ? creep
Call: (10) flight(edinburg, dublin) ? creep
Call: (11) directFlight(edinburg, _878) ? creep
Fail: (11) directFlight(edinburg, _878) ? creep
Fail: (10) flight(edinburg, dublin) ? creep
Redo: (10) directFlight(london, _878) ? creep
Exit: (10) directFlight(london, dublin) ? creep
Call: (10) flight(dublin, dublin) ? creep
Call: (11) directFlight(dublin, _878) ? creep
Fail: (11) directFlight(dublin, _878) ? creep
Fail: (10) flight(dublin, dublin) ? creep
Fail: (9) flight(london, dublin) ? creep
Fail: (8) flight(sofia, dublin) ? creep
false.
The issue is here at: Fail: (10) flight(dublin, dublin) ? creep.
Any ideas how to fix this?

Do not think in terms of loops needing exit statements. In fact, don't use the debugger at all, it's mightily confusing even if you DO know what is going on in the Prolog Processor.
You start off with a network of nodes connected by a set of edges (the relation).
In this case, the nodes are represented by atoms (denoting cities), the set of edges the relation called directFlight/2.
Now you want to overlay another set of edges, called flight/2.
So you have to ask yourself when do I have a flight/2 edge between two atoms A and B
There are two cases:
If there is a directFlight/2 between them (the base case)
If there is an intermediate node I such that there is a flight/2 from A to I and a directFlight/2 between I and B.
Alternatively, if there is an intermediate node I such that there is a directFlight/2 between A and I and a flight/2 from I to B.
Prolog will find the flight/2 edge by itself when asked for
flight(sofia, dublin).
(same as a relational database finds the result of an SQL query) but you have to pay some attention to termination. The alternative case (3) above will lead to a successful search or "false". The case (2) will lead to non-termination - entirely due to Prolog's search strategy (where decisions have to be taken on how a real-world machine searches through a network, in this case, depth-first, leftmost first).
Here is the base case for flight/2 (first image), all the flight/2 deduced by recursion of 1 call deep, and all the flight/2 deduced by recursion of 2 calls deep.
So:
directFlight(sofia, varna).
directFlight(sofia, paris).
directFlight(sofia, london).
directFlight(london, edinburg).
directFlight(paris, new_york).
directFlight(new_york, seattle).
directFlight(london, dublin).
flight(City1, City2) :- directFlight(City1, City2).
flight(City1, City2) :- directFlight(City1, City3), flight(City3, City2).
And then:
?- flight(sofia,dublin).
true ;
false.
?- flight(sofia,X).
X = varna ;
X = paris ;
X = london ;
X = new_york ;
X = seattle ;
X = edinburg ;
X = dublin ;
false.
?- flight(X,sofia).
false.
Addendum 1
The above program can be read:
"from LEFT :- to RIGHT" (as Prolog does). It is a search to ascertain whether a flight/2 fact holds or whether values can be found that make it true.
"from RIGHT -: to LEFT". The mental image is of continually accumulating new facts about flight/2 until one has collected them all and nothing is added anymore: bottom-up search (this is somehow easier on the brain, at least for me). Safer than search as you don't risk hitting an infinite recursion sinkhole just because the clauses are arranged in an unfortunate way, and is what some Datalog implementations do.
The logical reading is of a (or two) statement ("the program") that gives constraints about how flight/2 is supposed to be structured:
∀(City1, City2) :
(flight(City1, City2) <=
directFlight(City1, City2))
∧
∀(City1, City2) :
(flight(City1, City2) <=
(∃City3: directFlight(City1, City3) ∧ flight(City3, City2))
Note that there is nothing in the above that precludes that flight(X,Y) might hold for OTHER reasons than the one stated. We assume, however, that we know everything about when flight(X,Y) holds: Closed-World Assumption.
Addendum 2
Something one often forgets is that there need not be a recursive call at all. The recursion can be "unrolled" and the edge-to-edge linking made explicit:
directFlight(sofia, varna).
directFlight(sofia, paris).
directFlight(sofia, london).
directFlight(london, edinburg).
directFlight(paris, new_york).
directFlight(new_york, seattle).
directFlight(london, dublin).
flight(City1, City2) :- directFlight(City1, City2).
flight(City1, City2) :- directFlight(City1, Ia),
directFlight(Ia, City2).
flight(City1, City2) :- directFlight(City1, Ia),
directFlight(Ia, Ib),
directFlight(Ib, City2).
flight(City1, City2) :- directFlight(City1, Ia),
directFlight(Ia, Ib),
directFlight(Ib, Ic),
directFlight(Ic, City2).
None of the cities are more than 3 hops apart, so the above program will find all flight/2 connections.
In fact, another exercise would be to generate the above program, giving it as argument the "max depth" to consider.

Related

Raku: Attempt to divide by zero when coercing Rational to Str

I am crunching large amounts of data without a hitch until I added more data. The results are written to file as strings, but I received this error message and I am unable to find programming error after combing my codes for 2 days; my codes have been working fine before new data were added.
Died with the exception:
Attempt to divide by zero when coercing Rational to Str
in sub analyzeData at /home/xyz/numberCrunch.p6 line 2720
in block at /home/xyz/numberCrunch.p6 line 3363
Segmentation fault (core dumped)
The line 2720 is the line that outputs to file: $fh.say("$result");
So, Rational appears to be a delayed evaluation. Is there a way to force immediate conversion of Rational to decimals? Or make Rational smarter by enabling it to detect 0 denominators early?
First of all: a Rat with a denominator of 0 is a perfectly legal Rational value. So creating a Rat with a 0 denominator will not throw an exception on creation.
I see two issues really:
how do you represent a Rat with a denominator of 0 as a string?
how do you want your program to react to such a Rat?
When you represent a Rats as a string, there is a good chance you will lose precision:
say 1/3; # 0.333333
So the problem with Rat to string conversion is more general. Fortunately, there's the .raku method that will not throw:
say (1/3).raku; # <1/3>
say (42/0).raku; # <42/0>
Now, if you want your program to just not print the value to the file handle if the denominator is 0, then you have several options:
prefix with try
try $fh.say($result)
check for 0 denominator explicitly
$fh.say($result) if $result.denominator
Finally, the final error message: "Segmentation fault (core dumped)" is a bit worrying. If this is not a multi-threaded program, we should probably try to find out why that is happening: an execution error should not create a segfault. If it is, then maybe we need to look at your code closer to find out if there are any race conditions on structures such as arrays and hashes.
There is a perfectly logical reason that 1/0 doesn't immediately throw.
Let's say you have a floating point number that you want to coerce into a Rat, and back again.
my Num() $a = Inf;
my Rat() $b = $a;
my Num() $c = $b;
say $c;
What do you expect the say $c statement to print?
Inf
What would happen if you wrote say $b?
say $b;
Attempt to divide by zero when coercing Rational to Str
What are the contents of $b?
say $b.nude.join('/');
1/0
Now what if you do a division and immediately coerce it to a Num?
say ( 1/0).Num;
say ( 0/0).Num;
say (-1/0).Num;
Inf
NaN
-Inf

Create JuMP model with multi-threading in Julia

I have an optimization model which turns to be very difficult to build. This model has many if-else conditions and many loops as well. So I was thinking of using multi-threading for building this single JuMP model object.
A very simplified version of one loop of the code looks like this:
Threads.#threads for g in sets["A"]
Array_1 = [gg for gg in [sets["B"];sets["A"]] if data2[gg] == g]
Array_2 = [gg for gg in sets["B"] if data[gg] == g]
for t in STAGES
Array_3 = [gg for gg in [sets["B"];sets["A"]] if data2[gg] == g && (gg, t) in sets["C"] ]
for b in BLOCKS
name = #constraint( model, ((g, t, b) in sets["C"] ? X1[(g,t,b)] : 0)
- sum(X1[(gg,t,b)] for gg in Array_3 )
+ X2[(g,t,b)] - sum(X2[(gg,t,b)] for gg in Array_1)
- sum(data3[gg] for gg in Array_2) == data4[(g, t, b)])
end
end
a=string("con_",g,"_",t,"_",b)
JuMP.set_name(name,a)
end
I have many of those loops with many if-else conditions inside. So I added #Threads.threads before the first for g in sets["A"] aiming to reduce the time of building the model.
The problem is that I obtain an ERROR: LoadError: TaskFailedException: UndefRefError: access to undefined reference when renaming the constraint. Is there any problem about my approach? If I don't put the Threads.#threads there isn't any problem at all, it just works very slow.
Some information about the infrastructure:
julia> versioninfo()
Julia Version 1.4.1
Commit 381693d3df* (2020-04-14 17:20 UTC)
Platform Info:
OS: Linux (x86_64-pc-linux-gnu)
CPU: Intel(R) Xeon(R) CPU E5-2660 v3 # 2.60GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-8.0.1 (ORCJIT, haswell)
Environment:
JULIA_NUM_THREADS = 40
and packages:
(#v1.4) pkg> status
Status `~/.julia/environments/v1.4/Project.toml`
[c7e460c6] ArgParse v1.1.0
[a076750e] CPLEX v0.6.6
[336ed68f] CSV v0.7.7
[e2554f3b] Clp v0.8.1
[a93c6f00] DataFrames v0.21.7
[5789e2e9] FileIO v1.4.3
[2e9cd046] Gurobi v0.8.1
[033835bb] JLD2 v0.2.1
[4076af6c] JuMP v0.21.5
[438e738f] PyCall v1.91.4
[2913bbd2] StatsBase v0.33.1
[bd369af6] Tables v1.0.5
[6dd1b50a] Tulip v0.6.2
[1a1011a3] SharedArrays
[10745b16] Statistics
Thanks in advance!
Full stacktrace:
ERROR: LoadError: TaskFailedException:
UndefRefError: access to undefined reference
Stacktrace:
[1] getindex at ./array.jl:788 [inlined]
[2] ht_keyindex2!(::Dict{MathOptInterface.ConstraintIndex,String}, ::MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64},MathOptInterface.EqualTo{Float64}}) at ./dict.jl:326
[3] setindex!(::Dict{MathOptInterface.ConstraintIndex,String}, ::String, ::MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64},MathOptInterface.EqualTo{Float64}}) at ./dict.jl:381
[4] set at /home/user/.julia/packages/MathOptInterface/k7UUH/src/Utilities/model.jl:349 [inlined]
[5] set at /home/user/.julia/packages/MathOptInterface/k7UUH/src/Utilities/universalfallback.jl:354 [inlined]
[6] set(::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.AbstractOptimizer,MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}, ::MathOptInterface.ConstraintName, ::MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64},MathOptInterface.EqualTo{Float64}}, ::String) at /home/user/.julia/packages/MathOptInterface/k7UUH/src/Utilities/cachingoptimizer.jl:646
[7] set(::Model, ::MathOptInterface.ConstraintName, ::ConstraintRef{Model,MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64},MathOptInterface.EqualTo{Float64}},ScalarShape}, ::String) at /home/user/.julia/packages/JuMP/qhoVb/src/JuMP.jl:903
[8] set_name(::ConstraintRef{Model,MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64},MathOptInterface.EqualTo{Float64}},ScalarShape}, ::String) at /home/user/.julia/packages/JuMP/qhoVb/src/constraints.jl:68
[9] macro expansion at /home/user/code/model_formulation.jl:117 [inlined]
[10] (::var"#20#threadsfor_fun#255"{Dict{Any,Any},Dict{Any,Any},JuMP.Containers.DenseAxisArray{VariableRef,1,Tuple{Array{Tuple{String,Int64,Int64},1}},Tuple{Dict{Tuple{String,Int64,Int64},Int64}}},JuMP.Containers.DenseAxisArray{VariableRef,1,Tuple{Array{Tuple{String,Int64,Int64},1}},Tuple{Dict{Tuple{String,Int64,Int64},Int64}}},Array{String,1}})(::Bool) at ./threadingconstructs.jl:61
[11] (::var"#20#threadsfor_fun#255"{Dict{Any,Any},Dict{Any,Any},JuMP.Containers.DenseAxisArray{VariableRef,1,Tuple{Array{Tuple{String,Int64,Int64},1}},Tuple{Dict{Tuple{String,Int64,Int64},Int64}}},JuMP.Containers.DenseAxisArray{VariableRef,1,Tuple{Array{Tuple{String,Int64,Int64},1}},Tuple{Dict{Tuple{String,Int64,Int64},Int64}}},Array{String,1}})() at ./threadingconstructs.jl:28
Stacktrace:
[1] wait(::Task) at ./task.jl:267
[2] macro expansion at ./threadingconstructs.jl:69 [inlined]
[3] model_formulation(::Dict{Any,Any}, ::Dict{Any,Any}, ::Dict{Any,Any}, ::Dict{String,Bool}, ::String) at /home/user/code/model_formulation.jl:102
[4] functionA(::Dict{Any,Any}, ::Dict{Any,Any}, ::Dict{Any,Any}, ::String, ::Dict{String,Bool}) at /home/user/code/functionA.jl:178
[5] top-level scope at /home/user/code/main.jl:81
[6] include(::Module, ::String) at ./Base.jl:377
[7] exec_options(::Base.JLOptions) at ./client.jl:288
[8] _start() at ./client.jl:484
in expression starting at /home/user/code/main.jl:81
You have two options to parallelize a JuMP optimization model
Run a multi-threaded version of the Solver (provided that the solver supports it) - in that case the parallelism is fully handled by the external solver library and your Julia process remains single-threaded.
Run several single-threaded solver processes in parallel threads controlled by Julia. In this case several copies of the model need to be separately created which you can try to send to the solver at the same time.
#1:
Solvers support parameters including multi-threading control (on the other hand they might be simply using all available threads by default). Here is an example with Gurobi:
using JuMP, Gurobi
m = Model(optimizer_with_attributes(Gurobi.Optimizer, "Threads" => 2))
#variable(m, 0 <= x <= 2)
#variable(m, 0 <= y <= 30)
#objective(m, Max, 5x + 3 * y)
#constraint(m, con, 1x + 5y <= 3)
optimize!(m) # the model will be optimized using 2 threads
#2:
Running many solver copies in parallel you need to have separate model copies. In my code they differ by the range for x parameter:
Threads.#threads for z in 1:4
m = Model(optimizer_with_attributes(Gurobi.Optimizer, "Threads" => 1))
#variable(m, 0 <= x <= z)
#variable(m, 0 <= y <= 30)
#objective(m, Max, 5x + 3 * y)
#constraint(m, con, 1x + 5y <= 3)
optimize!(m)
#todo collect results
end
These are two separate approaches and you cannot mix them. If you parallelize execution each thread needs to get a separate model copy because JuMP mutates the Model object.

Prolog - Calculate fastest travel between 2 locations given different travel modes

I'm trying to figure out how to calculate the fastest journey between two places, given different travel modes. My factbase starts with a predicate route(Src, Dest, Distance, TravelMode) and input is via the predicate journey(Src, Dest, TravelMode) which should output the fastest travel mode to use. (Basically whichever has the shortest time.)
However, it says that TravelMode is a string and if it contains f, it means the path can be traveled on foot, c for car, t for train and p for plane. This has me confused since I don't really understand how to search the String TravelMode and only run the corresponding time functions for the travel modes included.
Below is my code and right now, it's only able to calculate the time between places (time_f, etc), although I believe my time predicate is wrong since I think it's supposed to be just one general function.
I also did try coding the journey predicate however, it only seems to output true / false and no values which probably means my route / speed predicate is wrong.
Am I on the right path? I've been stuck on this and I'd really appreciate any help to steer me in the correct direction / help explain what I have gotten wrong in here.
Not sure if everyone understands but I added the program specs just so that it could be clearer to understand
/* Sample set of facts */
route(dublin, cork, 200, 'fct').
route(cork, dublin, 200, 'fct').
route(cork, corkAirport, 20, 'fc').
route(corkAirport, cork, 25, 'fc').
route(dublin, dublinAirport, 10, 'fc').
route(dublinAirport, dublin, 20, 'fc').
route(dublinAirport, corkAirport, 225, 'p').
route(corkAirport, dublinAirport, 225, 'p').
/* Speed of mode of transport used */
speed(foot, 5).
speed(car, 80).
speed(train, 100).
speed(plane, 500).
/* Time between 2 cities, given specified transportation mode */
time_f(City1, City2, Time) :-
route(City1, City2, Distance, _),
speed(foot, Speed),
Time is (Distance / Speed),
write('Time travelling between '), write(City1), write(' and '), write(City2), write(' via foot is: '), write(Time), nl.
time_c(City1, City2, Time) :-
route(City1, City2, Distance, _),
speed(car, Speed),
Time is (Distance / Speed),
write('Time travelling between '), write(City1), write(' and '), write(City2), write(' via car is: '), write(Time), nl.
time_t(City1, City2, Time) :-
route(City1, City2, Distance, _),
speed(train, Speed),
Time is (Distance / Speed),
write('Time travelling between '), write(City1), write(' and '), write(City2), write(' via train is: '), write(Time), nl.
time_p(City1, City2, Time) :-
route(City1, City2, Distance, _),
speed(plane, Speed),
Time is (Distance / Speed),
write('Time travelling between '), write(City1), write(' and '), write(City2), write(' via plane is: '), write(Time), nl.
/* Solve for fastest journey */
journey(City1, City2, TravelModes) :-
route(City1, City2, Distance, TravelModes),
speed('TravelModes', Speed),
Time is (Distance / Speed),
write('Time travelling between '), write(City1), write(' and '), write(City2), write(' via '), write(TravelModes),
write(' is: '), write(Time), nl.
EDIT:
I tried to implement some changes. Especially that of detecting if mode is part of the string.
/* Sample set of facts */
route(dublin, cork, 200, fct).
route(dublin, dublinAirport, 10, fc).
route(dublinAirport, corkAirport, 225, p).
/* Speed of mode of transport used */
speed(f, 5).
speed(c, 80).
speed(t, 100).
speed(p, 500).
/* Program Flow
1. Input journey(City1, City2, TravelModes).
2. Check if City1 and City2 can be traveled (or path exists between them)
3. Access time function
4. Get travel time between City1 and City2 for TravelModes used
5. Select lowest travel time and output it.
*/
/* Checks if mode is in string */
availableMode(Mode, TravelModes) :- forall(sub_atom(Mode,_,1,_,C), sub_atom(TravelModes,_,1,_,C)).
/* Check mode of transport */
journey(City1, City2, TravelModes) :-
route(City1, City2, Distance, TravelModes),
availableMode(Mode, TravelModes),
speed(Mode, Speed),
Time is (Distance / Speed),
write('Time between '), write(City1), write(' and '), write(City2), write(' via '), write(Mode), write(' is: '),
write(Time), n1.
EDIT 2:
Currently, this is able to check the TravelMode input and calculate the necessary time. However, it doesn't store the output in a list of which the goal is to select the lowest time between routes and output that time.
/* Sample set of facts */
route(dublin, cork, 200, fct).
route(dublin, dublinAirport, 10, fc).
route(dublinAirport, corkAirport, 225, p).
/* Speed of mode of transport used */
speed(f, 5).
speed(c, 80).
speed(t, 100).
speed(p, 500).
/* Checks if mode is in string */
availableMode(Mode, TravelModes) :- sub_atom(TravelModes,_,1,_,Mode).
/* Read journey user input */
journey(City1, City2, TravelModes) :-
route(City1, City2, Distance, TravelModes),
availableMode(Mode, TravelModes),
speed(Mode, Speed),
Time is (Distance / Speed),
write('Time between '), write(City1), write(' and '), write(City2), write(' via '), write(Mode), write(' is: '),
write(Time), nl.
EDIT 3:
Implemented time variable to secondary journey predicate. Tried to implement all(Solutions) and finding the minimum variable, though I believe I am still missing out something since it only outputs true / false.
/* Sample set of facts */
route(dublin, cork, 200, fct).
route(dublinAirport, dublin, 20, fc).
route(dublinAirport, corkAirport, 225, p).
/* Speed of mode of transport used */
speed(f, 5).
speed(c, 80).
speed(t, 100).
speed(p, 500).
/* Checks if mode is in string */
availableMode(Mode, TravelModes) :- sub_atom(TravelModes,_,1,_,Mode).
journey(City1, City2, TravelModes) :-
route(City1, City2, Distance, TravelModes),
availableMode(Mode, TravelModes),
speed(Mode, Speed),
Time is (Distance / Speed),
write('Time between '), write(City1), write(' and '), write(City2), write(' via '), write(Mode), write(' is: '),
write(Time), nl.
/* Keep definition of journey but include a time variable that can be utilized */
journey(City1, City2, TravelModes) :- journey(City1, City2, TravelModes, _Time).
/* journey using time variable */
journey(City1, City2, TravelModes, Time) :-
route(City1, City2, Distance, TravelModes),
availableMode(Mode, TravelModes),
speed(Mode, Speed),
Time is (Distance / Speed).
/* Collecting all solutions */
all(Solutions) :- findall([City1, City2, TravelModes, Time], journey(City1, City2, TravelModes, Time), Solutions).
/* Finding minimum solution */
find_min(S, Solutions) :- all(Solutions).
EDIT 4:
Implemented (solving for the solutions recursively and storing them in a list). Also removed the redundant journey/3. Currently in the process of fixing the code to show just one solution set (aka the final solution with the lowest time).
/* Sample set of facts */
route(dublin, cork, 200, fct).
route(cork, dublin, 200, fct).
route(cork, corkAirport, 20, fc).
route(corkAirport, cork, 25, fc).
route(dublin, dublinAirport, 10, fc).
route(dublinAirport, dublin, 20, fc).
route(dublinAirport, corkAirport, 225, p).
route(corkAirport, dublinAirport, 225, p).
/* Speed of mode of transport used */
speed(f, 5).
speed(c, 80).
speed(t, 100).
speed(p, 500).
/* Checks if mode is in string */
availableMode(Mode, TravelModes) :- sub_atom(TravelModes,_,1,_,Mode).
/* Keep definition of journey but include a time variable that can be utilized */
journey(City1, City2, TravelModes) :- journey(City1, City2, TravelModes, _Time).
/* journey using time variable */
journey(City1, City2, TravelModes, Time) :-
route(City1, City2, Distance, TravelModes),
availableMode(Mode, TravelModes),
speed(Mode, Speed),
Time is (Distance / Speed),
write('Time between '), write(City1), write(' and '), write(City2), write(' via '), write(Mode), write(' is: '),
write(Time), nl.
/* Collecting all solutions */
all(Solutions) :- findall([City1, City2, TravelModes, Time], journey(City1, City2, TravelModes, Time), Solutions).
/* Recursion to find minimum travel time */
% Using the \+ (not provable operator) which discards the unnecessary solution
% Allowing us to retain the solutions with lowest time
% After recursively going thru the list, the accumulator list is set to the final solution list (aka the lowest time)
minimize([],Sol,Sol).
minimize([S|Ss],SolAcc,FinSol) :- S = [Cy1, Cy2, _, _],
\+ member([Cy1, Cy2, _, _], SolAcc),
minimize(Ss,[S|SolAcc],FinSol).
minimize([S|Ss],SolAcc,FinSol) :- S = [Cy1, Cy2, _MyMd, MyTi],
member([Cy1, Cy2, _OtherMd, OtherTi], SolAcc),
OtherTi < MyTi,
minimize(Ss,SolAcc,FinSol).
minimize([S|Ss],SolAcc,FinSol) :- S = [Cy1, Cy2, _MyMd, MyTi],
member([Cy1, Cy2, _OtherMd, OtherTi], SolAcc),
OtherTi >= MyTi,
delete(SolAcc, [Cy1, Cy2,_,_], SolAcc2),
minimize(Ss,[S|SolAcc2],FinSol).
/* Finding minimum solution */
find_min(MinimizedSolutions) :- all(Solutions),minimize(Solutions,[],MinimizedSolutions).
Answer to adding "minimization" predicate which selects those City-City paths that have lowest time. (This predicate is now in "Edit 4" of the question)
The SWI Prolog documentation for findall or bagof is here.
Note that findall belows is given the expression journey(City1, City2, TravelModes, Time) as a term but "elevates" it to a goal (i.e. a callable predicate). This is meta-call functionality and very much beyond first-order logic, similar to building Java code through string appends, compiling it, then running it. Editors should highlight that part in inverse...
/* Collecting all solutions */
all(Solutions) :- findall([City1, City2, TravelModes, Time], journey(City1, City2, TravelModes, Time), Solutions).
minimize([],Sol,Sol).
minimize([S|Ss],SolAcc,FinSol) :- S = [Cy1, Cy2, _, _],
\+ member([Cy1, Cy2, _, _], SolAcc),
minimize(Ss,[S|SolAcc],FinSol).
minimize([S|Ss],SolAcc,FinSol) :- S = [Cy1, Cy2, _MyMd, MyTi],
member([Cy1, Cy2, _OtherMd, OtherTi], SolAcc),
OtherTi < MyTi,
minimize(Ss,SolAcc,FinSol).
minimize([S|Ss],SolAcc,FinSol) :- S = [Cy1, Cy2, _MyMd, MyTi],
member([Cy1, Cy2, _OtherMd, OtherTi], SolAcc),
OtherTi >= MyTi,
delete(SolAcc, [Cy1, Cy2,_,_], SolAcc2),
minimize(Ss,[S|SolAcc2],FinSol).
/* Finding minimum solution */
find_min(MinimizedSolutions) :- all(Solutions),minimize(Solutions,[],MinimizedSolutions).
Clarification to answer question in comments
If you think of the program as defining a flow of data (see lovingly hand-drawn diagram below), then first Solutions is set-to (or "unified-with") a list of all possible solutions for journey(C1,C2,Tm,Ti), each formatted itself as list [C1,C2,Tm,Ti].
The list Solutions flows into a box representing minimize. That box also takes an empty list [] and is meant to unify its third argument with-the-eventual solution MinimizedSolutions. minimize calls itself (creating a new minimize box within itself) and behaves differently in each of the 4 cases of input it can receive as values of Solutions and SolAcc.
The idea is that minimize removes an element from its first input value, (a list) and adds 1 or 0 elements to its second input value, the accumulator (also a list), before calling itself. In that way when the first input value finally turns out to be [], minimize just needs to short-circuit the second value (input) to the third value (output), which then flows outwards through the recursively imbricated boxes towards the top goal.
In fact Prolog allows nasty (but compact) code to be written because it allows the expressions for case distinctions in minimze/3 to be carcrashed into the rule head. To make minimize clearer and show intention, in an imaginary Prolog which only allows variables as predicate arguments in the rule head and has "guard expressions" to perform case testing to the left of an | in the rule body, we would have the following code:
% Hide the fact that we need an accumulator value by
% defining minimize/2 which calls minimize/3
% This is the "public" part of minimize and can also be done in Prolog.
minimize(SolIn,SolOut) :- minimize(SolIn,[],SolOut).
% This is the "private" part of minimize and uses non-Prolog "guard" syntax
minimize(SolIn,SolAcc,SolOut) :- SolIn = [] |
SolOut = SolAcc.
minimize(SolIn,SolAcc,SolOut) :- SolIn = [S|Ss],
S = [Cy1, Cy2, _, _],
\+ member([Cy1, Cy2, _, _], SolAcc) |
minimize(Ss,[S|SolAcc],SolOut).
minimize(SolIn,SolAcc,SolOut) :- SolIn = [S|Ss],
S = [Cy1, Cy2, _MyMd, MyTi],
member([Cy1, Cy2, _OtherMd, OtherTi], SolAcc),
OtherTi < MyTi |
minimize(Ss,SolAcc,FinSol).
% etc. for the other two cases
The minimize(SolIn,SolOut) rule is just there to show to the next guy who has to maintain this that the arity-2 predicate minimize/2 is what "client code" would use. minimize/2 passes the work directly to the actual "implementation" which is an arity-3 predicate minimize/3: minimize(SolIn,SolAcc,SolOut).
For the latter, the recursive traversal through the SolIn list is kicked off by the body minimize(SolIn,[],SolOut).
If the program were modularized, minimize(SolIn,SolOut) would be what's being exported by the module. One would also mark what the implementation regards has "in" and "out" variables (sadly only in the comment, the compiler doesn't handle those) according to mode flags: minimize(+SolIn,-SolOut)
Again, this has aspects of imperative programming style "procedure calls" but I always visualize the thread or flow of information going into the "predicate box" at certain argument position and coming back out at another position, much like stitching. (Add things like freeze/2 and the thread needs to have tokens moving along it too, but that's for another time)

How to division operator scenario when denominator is zero , or both numerator and denominator are zero?

I am trying to do TDD in haskell using HSpec. So while writing special case scenario for division operator for example:
3 / 0 => Infinity
0 / 0 => Nan
How to test the above cases using Hspec ?
Use the functions isInfinite and isNaN:
Prelude> isInfinite (3 / 0.0)
True
Prelude> isNaN (0.0/0.0)
True

What is the difference between == and === in Verilog?

What is the difference between:
if (dataoutput[7:0] == 8'bx) begin
and
if (dataoutput[7:0] === 8'bx) begin
After executing dataoutput = 52'bx, the second gives 1, but the first gives 0. Why? (0 or 1 is the comparison result.)
Some data types in Verilog, such as reg, are 4-state. This means that each bit can be one of 4 values: 0,1,x,z.
With the "case equality" operator, ===, x's are compared, and the result is 1.
With ==, the result of the comparison is not 0, as you stated; rather, the result is x, according to the IEEE Std (1800-2009), section 11.4.5 "Equality operators":
For the logical equality and logical
inequality operators (== and !=), if,
due to unknown or high-impedance bits
in the operands, the relation is
ambiguous, then the result shall be a
1-bit unknown value (x).
In Verilog:
== tests logical equality (tests for 1 and 0, all other will result in x)
=== tests 4-state logical equality (tests for 1, 0, z and x)
== For comparing bits (0 or 1)
=== For comparing all 4 states (0, 1, x, z)
== can be synthesized into a hardware (x-nor gate), but === can't be synthesized as x is not a valid logic level in digital, it is infact having voltages in between 0 and 1. And z is not itself any logic, it shows disconnection of the circuit.
As many already commented, in case a signal has an X, the "normal" comparison operator can led to unknow states/answers. Therefore, if you are comparing from a RAM that can deliver U or X states and you want to really check a match, then you should use the "===" and "!==" operators.
See picture from the systemverilog reference documentation.

Resources