-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Creation of AbstractStochasticProgram interface #14
Conversation
Codecov Report
@@ Coverage Diff @@
## master #14 +/- ##
==========================================
+ Coverage 87.93% 88.14% +0.21%
==========================================
Files 14 14
Lines 870 869 -1
==========================================
+ Hits 765 766 +1
+ Misses 105 103 -2
Continue to review full report at Codecov.
|
I'm going to need some time to go through this and understand the internals of your implementation a bit better. |
src/solution.jl
Outdated
@@ -0,0 +1,33 @@ | |||
# π, σ and ρ do not really make sense alone so only | |||
# their product will T, h, d, e is stored | |||
mutable struct Solution |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you expand a bit on these definitions? Provide a doc-string?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have hidden this into the nlds.jl
file and replaced it with an AbstractSolution
interface
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a fan of the direction in stochprog.jl. I think a MOI for SDDP is good
I see a basic form as:
- A SDDPModel is a graph with nodes.
- Each node is a subproblem that has a collection of stagewise independent noises, takes an incoming state, and returns an objective, and dual vector for the state
For a node you want to be able to
- set the state
- query the outgoing state of a solved node
- loop through the noises
- set a particular noise
- solve
- get the objective and dual vector
- add a cut given a list of objectives, dual vectors, probabilities, and an exiting state (and a risk measure)
- run cut selection
For the graph you want to be able to
- identify the root node
- find the children of a node
- find the probability of the exiting arcs
- walk the graph
|
||
Creates a stochastic program from the arguments | ||
""" | ||
function stochasticprogram end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
StochasticProgram? CamelCase?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am open to using CamelCase. I am used to using lowercase in such cases since it is a function and not a type.
|
||
Sets the parent solution of `child` as `sol`, the solution obtained at `node`. | ||
""" | ||
function setchildx! end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what this means? Should it be setchildstate!(sp, parent, child)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes the name is awful and the argument list is even worse :D
For some obscure reason I need to also give the parent as parameter (because of the childT
I used for the EntropicCone to account for the permutation tranformations).
I prefer setchildstate!(sp, child, sol)
because in setchildstate!(sp, parent, child)
, we need to get the outgoing state
of parent
but in the mean time it might have been solved by another thread and the solution might not be the one we want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then it should just be setincomingstate!(sp, child, state::Vector{T})
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In case the parent is unbounded, the solution also contain an unbounded ray (which is composed of a feasible point and an unbounded vector). In this case, passing just a vector is not enough. Passing an AbstractSolution
provides enough flexibility to handle this case.
src/stochprog.jl
Outdated
|
||
Gets the current lower bound to the objective of `node`. | ||
""" | ||
function getobjlb end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should aim for readability over conciseness getobjectivebound
? Because it might be maximization
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, that's better :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done iin 9dafe36
src/stochprog.jl
Outdated
|
||
Sets the lower bounds to the objective of the children of `node` to `θlb`. | ||
""" | ||
function setθlb! end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto. see above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in 9dafe36
|
||
Returns the dimension of the state at `node`. | ||
""" | ||
function statedim end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I prefer statedim(sp)
. The state dimension should not change at different nodes in the graph
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the EntropicCone application, it does :/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is a "state"? If we think about reservoirs, there might be 2 in the first stage, and 3 in the second. However, there really is 3 in every stage, it's just that in the first stage the 3rd reservoir has a volume of 0. State dimension is a constant in a stochastic program.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When it has a physical meaning, I agree but in an abstract mathematical stochastic problem (it is the case with the entropic cone), there is not clear relation between the states from one node to the other one and the number change. In fact with the entropic cone, the graph is infinite and deep down in the graph, there are nodes of infinite number of states !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is because you're only using feasibility cuts right? I still don't fully understand your model haha
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think it is related to feasibility cuts
src/stochprog.jl
Outdated
|
||
Returns the id of `edge` for `src(edge)`. This id should be between 1 and `outdegree(src(edge))`. In case of multiple cuts, the value `θ[edgeid(sp, edge)]` at `src(edge)` corresponds to the lower bound to the objective value of `dst(edge)`. | ||
""" | ||
function edgeid end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It has been now removed :)
src/stochprog.jl
Outdated
|
||
Sets the probability to take the edge `edge` in the stochastic problem `sp`. | ||
""" | ||
function setprobability! end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto about conciseness s/proba/probability
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in da010de
1 similar comment
1 similar comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job! I think this work bring closer a common implementation of SDDP
I have some general comments :
- concerning continuous probability law, I agree that this remains an issue. A solution would be to quantize continuous probability laws (however, I do not know any Julia package that implements the methods of Pagès et al.)
- a main issue is the way we model uncertainty : in this implementation we affect a proba for each edge outgoing a given node, if I understood well. I do not know if it is well suited if we have stagewise independency, that is, we have only a single node per time steps. Maybe we should implement uncertainty inside the node rather than in the edges, and point to the following node directly inside the definition of the uncertainty model. What do you think? The point is that we should be able to model easily both lattice structures and Markov chain model. I have to admit that this point is unclear to me ...
I think that the power of a generic implementation is that it is not specific to SDDP. We may also want to implement a proper Dynamic Programming solver, or other methods (such as the particle methods described by Dallagi, or spatial decomposition algorithms).
Concerning @odow comment, I think we should also be able to define properly measurability constraint inside a given node (e.g Here and Now and Wait and See controls, etc), and be able to fetch easily the Bellman value function affected to this particular node. The SOLIB draft was a good starting point to figure out what elements do we need to model a node in a stochastic program!
If @odow is ok, I would be eager to create a new JuliaStochOpt
organization on Github :)
src/waitandsee.jl
Outdated
@@ -1,7 +1,7 @@ | |||
export waitandsee | |||
|
|||
mutable struct WSPath | |||
node::SDDPNode | |||
mutable struct WSPath{NodeT} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be clearer to write WaitAndSeePath
? I tend to think that explicit is always better than implicit^^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done :)
|
||
Sets the bounds to the objective of the child `child` of `node` to `θlb`. | ||
""" | ||
function setθbound! end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should explicit theta
as BellmanFunction
, but I am not sure. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, bellman function seems better.
Stagewise indepedent noises live inside a node. Nodes are connected by edges which have proabilities associated with them. The edge and noise inside a node are sampled independently. |
+100 |
1 similar comment
The interface tries to be agnostic on the particular representation of the stochastic problem. |
@frapac thinking a bit more about it, there is indeed an important issue here with cut sharing. |
I've moved away from explicit noise nodes to a hazard-decision and a decision-hazard thing https://www.sharelatex.com/project/59556d23c8f18fc31bc955d5 |
Better to solve all the children, then, if another node has the same children, you can recompute the averaged cut (using possibly different probabilities) without resolving. |
What would the interface be ? Something like the following ?
|
Different backward pass sampling schemes would do it differently. One approach is to recurse back up the tree. After adding a cut to a node, check the other children of its parent to see if it is possible to add a cut. That will work best for lattice structures. There are probably a number of optimizations and different heuristics you can use for deciding which nodes (and when) to add a cut. |
I see, so you mean the interface should remain more flexible so that the SDDP algorithm can make the choice. I will make this huge PR now, it does not mean that I consider the discussion closed but rather that we should transition the discussion to a StochasticProgram.jl package :) |
This big refactor improves the decoupling between the SDDP algorithm and the problem representation used by this package.
There is now 5 separate parts
AbstractStochasticProgram <: LightGraphs.AbstractGraph
, this aims to get as close as possible as @odow 's definition. Currently it is lacking Noise (triangle node). Noise cannot always be represented by a graph since the number of possible value of the noise might be infinite (e.g. Normally distributed). In this case, we may rather view the node model as being parametrized by a continuous parameter instead of several different nodes. @frapac @odow Do you preferAbstractStochasticProgram
orAbstractStochasticProblem
? This may be replaced by a separateStochasticProblem.jl
package containing @odow 's definition in Julia.stats.jl
,stopcrit.jl
,cutgen.jl
,sampler.jl
,solution.jl
. Some of these parts may be specific to the SDDP algorithm but some might be replaced by a definition inStochasticProblem.jl
.path.jl
,sddp.jl
.StochasticProgram
: Generic implementation ofAbstractStochasticProgram
using LightGraphs'DiGraph
and MathProgBase to solve the subprograms.StructJuMP
model intoStochasticProgram
.