Commit 5daefdc6 authored by Steven Cordwell's avatar Steven Cordwell
Browse files

use the new InvalidMDPError exception class, and redo the error handling in the example module

parent 8bfd8e84
...@@ -96,11 +96,11 @@ def forest(S=3, r1=4, r2=2, p=0.1, is_sparse=False): ...@@ -96,11 +96,11 @@ def forest(S=3, r1=4, r2=2, p=0.1, is_sparse=False):
""" """
if S <= 1: if S <= 1:
raise ValueError(mdperr["S_gt_1"]) raise ValueError("The number of states 'S' must be greater than 1.")
if (r1 <= 0) or (r2 <= 0): if (r1 <= 0) or (r2 <= 0):
raise ValueError(mdperr["R_gt_0"]) raise ValueError("The rewards must be greater than non-negative.")
if (p < 0) or (p > 1): if (p < 0) or (p > 1):
raise ValueError(mdperr["prob_in01"]) raise ValueError("The probability 'p' must be in [0; 1].")
# Definition of Transition matrix P(:,:,1) associated to action Wait # Definition of Transition matrix P(:,:,1) associated to action Wait
# (action 1) and P(:,:,2) associated to action Cut (action 2) # (action 1) and P(:,:,2) associated to action Cut (action 2)
# | p 1-p 0.......0 | | 1 0..........0 | # | p 1-p 0.......0 | | 1 0..........0 |
...@@ -173,15 +173,16 @@ def rand(S, A, is_sparse=False, mask=None): ...@@ -173,15 +173,16 @@ def rand(S, A, is_sparse=False, mask=None):
""" """
# making sure the states and actions are more than one # making sure the states and actions are more than one
if (S < 1) or (A < 1): if (S < 1) or (A < 1):
raise ValueError(mdperr["SA_gt_1"]) raise ValueError("The number of states S and the number of actions A "
"must be greater than 1.")
# if the user hasn't specified a mask, then we will make a random one now # if the user hasn't specified a mask, then we will make a random one now
if mask is not None: if mask is not None:
# the mask needs to be SxS or AxSxS # the mask needs to be SxS or AxSxS
try: try:
if mask.shape not in ((S, S), (A, S, S)): if mask.shape not in ((S, S), (A, S, S)):
raise ValueError(mdperr["mask_SbyS"]) raise ValueError("'mask' must have dimensions S×S or A×S×S.")
except AttributeError: except AttributeError:
raise TypeError(mdperr["mask_numpy"]) raise TypeError("'mask' must be a numpy array or matrix.")
# generate the transition and reward matrices based on S, A and mask # generate the transition and reward matrices based on S, A and mask
if is_sparse: if is_sparse:
# definition of transition matrix : square stochastic matrix # definition of transition matrix : square stochastic matrix
......
...@@ -10,16 +10,11 @@ from numpy import absolute, ones ...@@ -10,16 +10,11 @@ from numpy import absolute, ones
# These need to be fixed so that we use classes derived from Error. # These need to be fixed so that we use classes derived from Error.
mdperr = { mdperr = {
"mat_nonneg" : "mat_nonneg" :
"Probabilities must be non-negative.", "Transition probabilities must be non-negative.",
"mat_square" : "mat_square" :
"The matrix must be square.", "A transition probability matrix must be square, with dimensions S×S.",
"mat_stoch" : "mat_stoch" :
"Rows of the matrix must sum to one (1).", "Each row of a transition probability matrix must sum to one (1).",
"mask_numpy" :
"mask must be a numpy array or matrix; i.e. type(mask) is "
"ndarray or type(mask) is matrix.",
"mask_SbyS" :
"The mask must have shape SxS; i.e. mask.shape = (S, S).",
"obj_shape" : "obj_shape" :
"Object arrays for transition probabilities and rewards " "Object arrays for transition probabilities and rewards "
"must have only 1 dimension: the number of actions A. Each element of " "must have only 1 dimension: the number of actions A. Each element of "
...@@ -37,22 +32,13 @@ mdperr = { ...@@ -37,22 +32,13 @@ mdperr = {
"actions greater than 0. i.e. R.shape = (A, S, S)", "actions greater than 0. i.e. R.shape = (A, S, S)",
"PR_incompat" : "PR_incompat" :
"Incompatibility between P and R dimensions.", "Incompatibility between P and R dimensions.",
"prob_in01" :
"Probability p must be in [0; 1].",
"R_type" : "R_type" :
"The rewards must be in a numpy array; i.e. type(R) is " "The rewards must be in a numpy array; i.e. type(R) is "
"ndarray, or numpy matrix; i.e. type(R) is matrix.", "ndarray, or numpy matrix; i.e. type(R) is matrix.",
"R_shape" : "R_shape" :
"The reward matrix R must be an array of shape (A, S, S) or " "The reward matrix R must be an array of shape (A, S, S) or "
"(S, A) with S : number of states greater than 0 and A : number of " "(S, A) with S : number of states greater than 0 and A : number of "
"actions greater than 0. i.e. R.shape = (S, A) or (A, S, S).", "actions greater than 0. i.e. R.shape = (S, A) or (A, S, S)."
"R_gt_0" :
"The rewards must be greater than 0.",
"S_gt_1" :
"Number of states S must be greater than 1.",
"SA_gt_1" :
"The number of states S and the number of actions A must be "
"greater than 1."
} }
def check(P, R): def check(P, R):
...@@ -98,7 +84,7 @@ def check(P, R): ...@@ -98,7 +84,7 @@ def check(P, R):
# continue checking from there # continue checking from there
raise AttributeError raise AttributeError
else: else:
raise ValueError(mdperr["P_shape"]) raise InvalidMDPError(mdperr["P_shape"])
except AttributeError: except AttributeError:
try: try:
aP = len(P) aP = len(P)
...@@ -106,9 +92,9 @@ def check(P, R): ...@@ -106,9 +92,9 @@ def check(P, R):
for aa in xrange(1, aP): for aa in xrange(1, aP):
sP0aa, sP1aa = P[aa].shape sP0aa, sP1aa = P[aa].shape
if (sP0aa != sP0) or (sP1aa != sP1): if (sP0aa != sP0) or (sP1aa != sP1):
raise ValueError(mdperr["obj_square"]) raise InvalidMDPError(mdperr["obj_square"])
except AttributeError: except AttributeError:
raise TypeError(mdperr["P_shape"]) raise InvalidMDPError(mdperr["P_shape"])
except: except:
raise raise
# Checking R # Checking R
...@@ -122,7 +108,7 @@ def check(P, R): ...@@ -122,7 +108,7 @@ def check(P, R):
# A hack so that we can go into the next try-except statement # A hack so that we can go into the next try-except statement
raise AttributeError raise AttributeError
else: else:
raise ValueError(mdperr["R_shape"]) raise InvalidMDPError(mdperr["R_shape"])
except AttributeError: except AttributeError:
try: try:
aR = len(R) aR = len(R)
...@@ -130,18 +116,18 @@ def check(P, R): ...@@ -130,18 +116,18 @@ def check(P, R):
for aa in range(1, aR): for aa in range(1, aR):
sR0aa, sR1aa = R[aa].shape sR0aa, sR1aa = R[aa].shape
if ((sR0aa != sR0) or (sR1aa != sR1)): if ((sR0aa != sR0) or (sR1aa != sR1)):
raise ValueError(mdperr["obj_square"]) raise InvalidMDPError(mdperr["obj_square"])
except AttributeError: except AttributeError:
raise ValueError(mdperr["R_shape"]) raise InvalidMDPError(mdperr["R_shape"])
except: except:
raise raise
# Checking dimensions # Checking dimensions
if (sP0 < 1) or (aP < 1) or (sP0 != sP1): if (sP0 < 1) or (aP < 1) or (sP0 != sP1):
raise ValueError(mdperr["P_shape"]) raise InvalidMDPError(mdperr["P_shape"])
if (sR0 < 1) or (aR < 1) or (sR0 != sR1): if (sR0 < 1) or (aR < 1) or (sR0 != sR1):
raise ValueError(mdperr["R_shape"]) raise InvalidMDPError(mdperr["R_shape"])
if (sP0 != sR0) or (aP != aR): if (sP0 != sR0) or (aP != aR):
raise ValueError(mdperr["PR_incompat"]) raise InvalidMDPError(mdperr["PR_incompat"])
# Check that the P's are square and stochastic # Check that the P's are square and stochastic
for aa in xrange(aP): for aa in xrange(aP):
checkSquareStochastic(P[aa]) checkSquareStochastic(P[aa])
...@@ -260,20 +246,20 @@ def checkSquareStochastic(Z): ...@@ -260,20 +246,20 @@ def checkSquareStochastic(Z):
except AttributeError: except AttributeError:
raise TypeError("Matrix should be a numpy type.") raise TypeError("Matrix should be a numpy type.")
except ValueError: except ValueError:
raise ValueError(mdperr["mat_square"]) raise InvalidMDPError(mdperr["mat_square"])
# check that the matrix is square, and that each row sums to one # check that the matrix is square, and that each row sums to one
if s1 != s2: if s1 != s2:
raise ValueError(mdperr["mat_square"]) raise InvalidMDPError(mdperr["mat_square"])
elif (absolute(Z.sum(axis=1) - ones(s2))).max() > 10e-12: elif (absolute(Z.sum(axis=1) - ones(s2))).max() > 10e-12:
raise ValueError(mdperr["mat_stoch"]) raise InvalidMDPError(mdperr["mat_stoch"])
# make sure that there are no values less than zero # make sure that there are no values less than zero
try: try:
if (Z < 0).any(): if (Z < 0).any():
raise ValueError(mdperr["mat_nonneg"]) raise InvalidMDPError(mdperr["mat_nonneg"])
except AttributeError: except AttributeError:
try: try:
if (Z.data < 0).any(): if (Z.data < 0).any():
raise ValueError(mdperr["mat_nonneg"]) raise InvalidMDPError(mdperr["mat_nonneg"])
except AttributeError: except AttributeError:
raise TypeError("Matrix should be a numpy type.") raise TypeError("Matrix should be a numpy type.")
except: except:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment