File: sol_ranges.ml

package info (click to toggle)
hol88 2.02.19940316-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 63,052 kB
  • ctags: 19,365
  • sloc: ml: 199,939; ansic: 9,300; sh: 7,118; makefile: 6,076; lisp: 2,747; yacc: 894; sed: 201; cpp: 87; awk: 5
file content (151 lines) | stat: -rw-r--r-- 7,320 bytes parent folder | download | duplicates (11)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
%****************************************************************************%
% FILE          : sol_ranges.ml                                              %
% DESCRIPTION   : Functions for determining the ranges of the solutions to   %
%                 linear programming problems, and whether there are natural %
%                 number solutions.                                          %
%                                                                            %
% READS FILES   : <none>                                                     %
% WRITES FILES  : <none>                                                     %
%                                                                            %
% AUTHOR        : R.J.Boulton                                                %
% DATE          : 18th April 1991                                            %
%                                                                            %
% LAST MODIFIED : R.J.Boulton                                                %
% DATE          : 1st July 1992                                              %
%****************************************************************************%

%----------------------------------------------------------------------------%
% less_bound : bound -> bound -> bool                                        %
%----------------------------------------------------------------------------%

let less_bound b1 b2 =
   (case (b1,b2)
    of (Neg_inf,Neg_inf) . fail
     | (Neg_inf,Bound (_,[])) . true
     | (Neg_inf,Pos_inf) . true
     | (Bound (_,[]),Neg_inf) . false
     | (Bound (r1,[]),Bound (r2,[])) . (rat_less r1 r2)
     | (Bound (_,[]),Pos_inf) . true
     | (Pos_inf,Neg_inf) . false
     | (Pos_inf,Bound (_,[])) . false
     | (Pos_inf,Pos_inf) . fail
   ) ? failwith `less_bound`;;

%----------------------------------------------------------------------------%
% is_neg_bound : bound -> bool                                               %
%----------------------------------------------------------------------------%

let is_neg_bound b =
   (case b
    of (Bound (r,[])) . (rat_less r rat_zero)
     | Pos_inf . false
     | Neg_inf . true
   ) ? failwith `is_neg_bound`;;

%----------------------------------------------------------------------------%
% is_finite_bound : bound -> bool                                            %
%----------------------------------------------------------------------------%

let is_finite_bound b =
   (case b
    of (Bound (_,[])) . true
     | Pos_inf . false
     | Neg_inf . false
   ) ? failwith `is_finite_bound`;;

%----------------------------------------------------------------------------%
% rat_of_bound : bound -> rat                                                %
%----------------------------------------------------------------------------%

let rat_of_bound b =
   (case b
    of (Bound (r,[])) . r
   ) ? failwith `rat_of_bound`;;

%----------------------------------------------------------------------------%
% is_int_range : rat -> rat -> bool                                          %
%----------------------------------------------------------------------------%

let is_int_range r1 r2 =
   let i1 = upper_int_of_rat r1
   and i2 = lower_int_of_rat r2
   in  not (i2 < i1);;

%----------------------------------------------------------------------------%
% non_neg_int_between : bound -> bound -> int                                %
%----------------------------------------------------------------------------%

let non_neg_int_between b1 b2 =
   (case (b1,b2)
    of (Neg_inf,Neg_inf) . fail
     | (Neg_inf,Bound (r,[])) . (if (rat_less r rat_zero) then fail else 0)
     | (Neg_inf,Pos_inf) . 0
     | (Bound (_,[]),Neg_inf) . fail
     | (Bound (r1,[]),Bound (r2,[])) .
          (let i1 = upper_int_of_rat r1
           and i2 = lower_int_of_rat r2
           in  let i1' = if (i1 < 0) then 0 else i1
           in  if (i2 < i1') then fail else i1')
     | (Bound (r,[]),Pos_inf) .
          (if (rat_less r rat_zero) then 0 else upper_int_of_rat r)
     | (Pos_inf,Neg_inf) . fail
     | (Pos_inf,Bound (_,[])) . fail
     | (Pos_inf,Pos_inf) . fail
   ) ? failwith `non_neg_int_between`;;

%----------------------------------------------------------------------------%
% inst_var_in_coeffs : (string # int) ->                                     %
%                      (int # (string # int) list) list ->                   %
%                      (int # (string # int) list) list                      %
%                                                                            %
% Substitute a constant for a variable in a set of coefficients.             %
%----------------------------------------------------------------------------%

letrec inst_var_in_coeffs (v:string,c) coeffsl =
   if (null coeffsl)
   then []
   else let (const,bind) = hd coeffsl
        in  let ((_,coeff),bind') =
               (remove (\(name,_). name = v) bind ? ((v,0),bind))
        in  (const + (c * coeff),bind').
               (inst_var_in_coeffs (v,c) (tl coeffsl));;

%----------------------------------------------------------------------------%
% Shostak : (int # (string # int) list) list -> (string # int) list          %
%                                                                            %
% Uses SUP-INF in the way described by Shostak to find satisfying values     %
% (natural numbers) for the variables in a set of inequalities (represented  %
% as bindings). The function fails if it can't find such values.             %
%                                                                            %
% The function tries permutations of the variables, because the ordering can %
% affect whether or not satisfying values are found. Lazy evaluation is used %
% to avoid computing all the permutations before they are required. This     %
% should help to avoid problems due to enormously long lists, but even so,   %
% for a large number of variables, the function could execute for a very     %
% long time.                                                                 %
%----------------------------------------------------------------------------%

let Shostak coeffsl =
   let vars_of_coeffs coeffsl = setify (flat (map ((map fst) o snd) coeffsl))
   in
   letrec Shostak' coeffsl vars =
      let no_vars = filter (null o snd) coeffsl
      in  let falses = filter (\(n,_). n < 0) no_vars
      in  if (null falses)
          then if (null vars)
               then []
               else let coeffsl' = filter (\(n,l). not (null l)) coeffsl
                    in  let var = hd vars
                    in  let b = Bound (rat_zero,[var,rat_one])
                    in  let sup = eval_bound (SIMP (SUP coeffsl' (b,[])))
                        and inf = eval_bound (SIMP (INF coeffsl' (b,[])))
                    in  let val = non_neg_int_between inf sup
                    in  let new_coeffsl = inst_var_in_coeffs (var,val) coeffsl'
                    in  (var,val).(Shostak' new_coeffsl (tl vars))
          else fail
   and try f s = case s () of (Stream (x,s')) . (f x ? try f s')
   in  let vars = vars_of_coeffs coeffsl
   in  (if (null vars)
        then Shostak' coeffsl []
        else try (Shostak' coeffsl) (permutations vars))
    ?  failwith `Shostak`;;