File Coverage

blib/lib/Decision/Markov.pm
Criterion Covered Total %
statement 96 97 98.9
branch 21 28 75.0
condition 3 6 50.0
subroutine 19 19 100.0
pod 9 13 69.2
total 148 163 90.8


line stmt bran cond sub pod time code
1             package Decision::Markov;
2              
3             #
4             # Copyright (c) 1998-2002 Alan Schwartz . All rights
5             # reserved. This program is free software; you can redistribute it and/or
6             # modify it under the same terms as Perl itself.
7             #
8              
9             require 5.000;
10 1     1   44314 use strict;
  1         3  
  1         35  
11 1     1   1102 use diagnostics;
  1         222018  
  1         214  
12 1     1   508 use Carp;
  1         10  
  1         90  
13 1     1   833 use Decision::Markov::State;
  1         3  
  1         68  
14 1     1   6 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
  1         3  
  1         736  
15              
16             require Exporter;
17             require AutoLoader;
18              
19             @ISA = qw(Exporter AutoLoader);
20             @EXPORT = qw();
21             $VERSION = "0.03";
22              
23              
24             sub new {
25 1     1 1 423 my $this = shift;
26 1   33     8 my $class = ref($this) || $this;
27 1         4 my $self = {};
28 1         3 bless $self, $class;
29 1         11 $self->{'states'} = []; # List of states
30 1         6 $self->DiscountRate(0);
31 1         5 $self->Reset;
32 1         3 return $self;
33             }
34              
35             sub AddState {
36 3     3 1 528 my $self = shift;
37 3         6 my $name = shift;
38 3         4 my $utility = shift;
39 3         15 my $state = new Decision::Markov::State($name,$utility);
40 3         5 push(@{ $self->{'states'} }, $state);
  3         6  
41 3         7 return $state;
42             }
43              
44 88     88 0 90 sub States { @{ $_[0]->{'states'} } };
  88         2050  
45             sub CurrentState {
46 31     31 0 47 my $self = shift;
47 31 100       569 @_ ? $self->{'currentstate'} = shift : $self->{'currentstate'}
48             };
49             sub CumUtility {
50 359     359 0 417 my $self = shift;
51 359 100       4921 @_ ? $self->{'cumutility'} = shift : $self->{'cumutility'}
52             };
53             sub PatientsLeft {
54 6     6 0 10 my $self = shift;
55 6 100       15 @_ ? $self->{'patientsleft'} = shift : $self->{'patientsleft'}
56             };
57             sub DiscountRate {
58 188     188 1 192 my $self = shift;
59 188 100       4648 @_ ? $self->{'discount'} = shift : $self->{'discount'}
60             };
61              
62             sub AddPath {
63 7     7 1 809 my $self = shift;
64 7         8 my $from = shift; # source state
65 7         8 my $to = shift; # destination state
66 7         7 my $prob = shift; # transition probability/function
67 7 50       16 return "AddPath: From state '$from' isn't a State object" unless ref($from);
68 7 50       14 return "AddPath: To state '$to' isn't a State object" unless ref($to);
69 7         18 return $from->AddTransition($to,$prob);
70             }
71              
72             # Check that transition probabilities for every node add up to 1.
73             # If the probabilities are functions of time, try calling them
74             # for t = 3 and make sure that works. Return undef if no good, otherwise 1.
75             sub Check {
76 1     1 1 256 my $self = shift;
77 1         4 foreach my $state ($self->States) {
78 3         9 my $total = $state->SumProbs;
79 3 50       11 return "Check: " . $state->Name . " has probabilities totalling $total, not 1"
80             unless ($total == 1);
81             }
82 1         4 return undef;
83             }
84              
85              
86             sub Reset {
87 4     4 1 650 my $self = shift;
88 4         13 $self->CurrentState("");
89 4         9 $self->CumUtility(0);
90 4         13 $self->PatientsLeft(0);
91 4         12 foreach my $state ($self->States) {
92 9         25 $state->Reset;
93             }
94 4 100       22 $self->StartingState(@_) if @_;
95             }
96              
97             sub StartingState {
98 3     3 1 5 my $self = shift;
99 3         4 my $initial_state = shift;
100 3         5 my $numpatients = shift;
101 3 50       10 return "StartingState: Initial state '$initial_state' isn't a State object"
102             unless ref($initial_state);
103 3 50 66     14 return "StartingState: Invalid number of patients: $numpatients"
104             if ($numpatients && ($numpatients < 0));
105 3         9 $self->CurrentState($initial_state);
106 3 100       9 if ($numpatients) {
107 1         3 $self->PatientsLeft($numpatients);
108 1         3 $initial_state->NumPatients($numpatients);
109             }
110 3         7 return undef;
111             }
112              
113              
114             1;
115             __END__