I'm trying to solve time dependent ASP problem using Clingo (version 5.7.1). Imagine that some project can start any year (2025, 2026 or 2027), and depending on this, its value in a given year can be 0 (if it hasn't started yet), or 30 (if started this year), 31 or 32 (if started in the previous year). At the end I want to sum up the obtained values. Here is my ASP/clingo code:
% Time horizon
horizon(2025..2027).
% q(value, years from start)
q(30, 0; 31, 1; 32, 2).
% choice of start year
{ start(Year) : horizon(Year) } 1.
% possible values depending on the year of start
value(Value, Year)
:- q(Value, Year - YearStart), YearStart <= Year, start(YearStart), horizon(Year).
% summation of values (in a real program, summation is performed for different objects, but it doesn't matter here)
summation(Q, Year)
:- Q = #sum { Value : value(Value, Year) }, horizon(Year).
I expected the code grounding to be small, so that the possible variants of the sum constitute one of the values, namely 0, 30, 31 or 32.
But grounding (obtained with --text flag) is inflating at a factorial rate. Here is the result of grounding:
summation(0,2025):-#sum{30:value(30,2025)}=0.
summation(30,2025):-#sum{30:value(30,2025)}=30.
summation(0,2026):-#sum{30:value(30,2026);31:value(31,2026)}=0.
summation(30,2026):-#sum{30:value(30,2026);31:value(31,2026)}=30.
summation(31,2026):-#sum{30:value(30,2026);31:value(31,2026)}=31.
summation(61,2026):-#sum{30:value(30,2026);31:value(31,2026)}=61.
summation(0,2027):-#sum{30:value(30,2027);31:value(31,2027);32:value(32,2027)}=0.
summation(30,2027):-#sum{30:value(30,2027);31:value(31,2027);32:value(32,2027)}=30.
summation(31,2027):-#sum{30:value(30,2027);31:value(31,2027);32:value(32,2027)}=31.
summation(61,2027):-#sum{30:value(30,2027);31:value(31,2027);32:value(32,2027)}=61.
summation(32,2027):-#sum{30:value(30,2027);31:value(31,2027);32:value(32,2027)}=32.
summation(62,2027):-#sum{30:value(30,2027);31:value(31,2027);32:value(32,2027)}=62.
summation(63,2027):-#sum{30:value(30,2027);31:value(31,2027);32:value(32,2027)}=63.
summation(93,2027):-#sum{30:value(30,2027);31:value(31,2027);32:value(32,2027)}=93.
The reason is that gringo pre-sums all possible combinations of numbers. For example, in 2026 the value cannot be 61, but gringo grounds such an option (see above). In a time dependent problem this causes it to slow down considerably. The question is, how to avoid excessive grounding of meaningless combinations to reduce overall calculation time?
I'm trying to solve time dependent ASP problem using Clingo (version 5.7.1). Imagine that some project can start any year (2025, 2026 or 2027), and depending on this, its value in a given year can be 0 (if it hasn't started yet), or 30 (if started this year), 31 or 32 (if started in the previous year). At the end I want to sum up the obtained values. Here is my ASP/clingo code:
% Time horizon
horizon(2025..2027).
% q(value, years from start)
q(30, 0; 31, 1; 32, 2).
% choice of start year
{ start(Year) : horizon(Year) } 1.
% possible values depending on the year of start
value(Value, Year)
:- q(Value, Year - YearStart), YearStart <= Year, start(YearStart), horizon(Year).
% summation of values (in a real program, summation is performed for different objects, but it doesn't matter here)
summation(Q, Year)
:- Q = #sum { Value : value(Value, Year) }, horizon(Year).
I expected the code grounding to be small, so that the possible variants of the sum constitute one of the values, namely 0, 30, 31 or 32.
But grounding (obtained with --text flag) is inflating at a factorial rate. Here is the result of grounding:
summation(0,2025):-#sum{30:value(30,2025)}=0.
summation(30,2025):-#sum{30:value(30,2025)}=30.
summation(0,2026):-#sum{30:value(30,2026);31:value(31,2026)}=0.
summation(30,2026):-#sum{30:value(30,2026);31:value(31,2026)}=30.
summation(31,2026):-#sum{30:value(30,2026);31:value(31,2026)}=31.
summation(61,2026):-#sum{30:value(30,2026);31:value(31,2026)}=61.
summation(0,2027):-#sum{30:value(30,2027);31:value(31,2027);32:value(32,2027)}=0.
summation(30,2027):-#sum{30:value(30,2027);31:value(31,2027);32:value(32,2027)}=30.
summation(31,2027):-#sum{30:value(30,2027);31:value(31,2027);32:value(32,2027)}=31.
summation(61,2027):-#sum{30:value(30,2027);31:value(31,2027);32:value(32,2027)}=61.
summation(32,2027):-#sum{30:value(30,2027);31:value(31,2027);32:value(32,2027)}=32.
summation(62,2027):-#sum{30:value(30,2027);31:value(31,2027);32:value(32,2027)}=62.
summation(63,2027):-#sum{30:value(30,2027);31:value(31,2027);32:value(32,2027)}=63.
summation(93,2027):-#sum{30:value(30,2027);31:value(31,2027);32:value(32,2027)}=93.
The reason is that gringo pre-sums all possible combinations of numbers. For example, in 2026 the value cannot be 61, but gringo grounds such an option (see above). In a time dependent problem this causes it to slow down considerably. The question is, how to avoid excessive grounding of meaningless combinations to reduce overall calculation time?
You could precompute the possible sums instead of dynamically determining them.
% Time horizon
horizon(2025..2027).
% q(value, years from start)
q(30, 0; 31, 1; 32, 2).
% possible values
value(YearStart, Value, Year)
:- q(Value, Year - YearStart), YearStart <= Year, horizon(YearStart), horizon(Year).
% summation of values
summation(YearStart, Q, Year)
:- Q = #sum { Value : value(YearStart, Value, Year) }, horizon(Year), horizon(YearStart).
% choice of start year
{ start(Year) : horizon(Year) } 1.
sumofstartyear(Q, Year) :- start(YearStart), summation(YearStart, Q, Year).
And in the end you select the sum that you want. Depending on your usecase this might reduce your grounding.
But why not simply calculate the value you want:
horizon(2025..2027).
{ start(Year) : horizon(Year) } 1.
summation(0, Year) :- start(YearStart), horizon(Year), Year < YearStart.
summation(30+Year-YearStart, Year) :- start(YearStart), horizon(Year), Year >= YearStart.