src/HOL/Matrix/cplex/FloatSparseMatrixBuilder.ML
changeset 21056 2cfe839e8d58
parent 20485 3078fd2eec7b
child 22578 b0eb5652f210
equal deleted inserted replaced
21055:e053811d680e 21056:2cfe839e8d58
    28     val sign_term : term -> cterm
    28     val sign_term : term -> cterm
    29 
    29 
    30     val v_elem_at : vector -> int -> string option
    30     val v_elem_at : vector -> int -> string option
    31     val m_elem_at : matrix -> int -> vector option
    31     val m_elem_at : matrix -> int -> vector option
    32     val v_only_elem : vector -> int option
    32     val v_only_elem : vector -> int option
    33     val v_fold : ('a * (int * string) -> 'a) -> 'a -> vector -> 'a
    33     val v_fold : (int * string -> 'a -> 'a) -> vector -> 'a -> 'a
    34     val m_fold : ('a * (int * vector) -> 'a) -> 'a -> matrix -> 'a
    34     val m_fold : (int * vector -> 'a -> 'a) -> matrix -> 'a -> 'a
    35 
    35 
    36     val transpose_matrix : matrix -> matrix
    36     val transpose_matrix : matrix -> matrix
    37 
    37 
    38     val cut_vector : int -> vector -> vector
    38     val cut_vector : int -> vector -> vector
    39     val cut_matrix : vector -> (int option) -> matrix -> matrix
    39     val cut_matrix : vector -> (int option) -> matrix -> matrix
   127 
   127 
   128 fun cons_spmat h t = Cons_spmat_const $ h $ t 
   128 fun cons_spmat h t = Cons_spmat_const $ h $ t 
   129 
   129 
   130 fun approx_vector_term prec pprt vector = 
   130 fun approx_vector_term prec pprt vector = 
   131     let 	 
   131     let 	 
   132 	fun app ((vlower, vupper), (index, s)) = 
   132 	fun app (index, s) (vlower, vupper) = 
   133 	    let
   133 	    let
   134 		val (flower, fupper) = approx_value_term prec pprt s
   134 		val (flower, fupper) = approx_value_term prec pprt s
   135 		val index = mk_intinf HOLogic.natT (IntInf.fromInt index)
   135 		val index = mk_intinf HOLogic.natT (IntInf.fromInt index)
   136 		val elower = HOLogic.mk_prod (index, flower)
   136 		val elower = HOLogic.mk_prod (index, flower)
   137 		val eupper = HOLogic.mk_prod (index, fupper)
   137 		val eupper = HOLogic.mk_prod (index, fupper)
   138 	    in
   138 	    in
   139 		(Cons_spvec_const $ elower $ vlower,
   139 		(Cons_spvec_const $ elower $ vlower,
   140 		 Cons_spvec_const $ eupper $ vupper)	
   140 		 Cons_spvec_const $ eupper $ vupper)	
   141 	    end
   141 	    end
   142     in
   142     in
   143 	Inttab.foldl app ((empty_vector_const, empty_vector_const), vector)	
   143 	Inttab.fold app vector (empty_vector_const, empty_vector_const)
   144     end
   144     end
   145 
   145 
   146 fun approx_matrix_term prec pprt matrix =
   146 fun approx_matrix_term prec pprt matrix =
   147     let 	 
   147   let
   148 	fun app ((mlower, mupper), (index, vector)) = 
   148     fun app (index, vector) (mlower, mupper) =
   149 	    let
   149       let
   150 		val (vlower, vupper) = approx_vector_term prec pprt vector  
   150         val (vlower, vupper) = approx_vector_term prec pprt vector  
   151 		val index = mk_intinf HOLogic.natT (IntInf.fromInt index)
   151         val index = mk_intinf HOLogic.natT (IntInf.fromInt index)
   152 		val elower = HOLogic.mk_prod (index, vlower)
   152         val elower = HOLogic.mk_prod (index, vlower)
   153 		val eupper = HOLogic.mk_prod (index, vupper)
   153         val eupper = HOLogic.mk_prod (index, vupper)
   154 	    in
   154       in
   155 		(Cons_spmat_const $ elower $ mlower,
   155         (Cons_spmat_const $ elower $ mlower, Cons_spmat_const $ eupper $ mupper)
   156 		 Cons_spmat_const $ eupper $ mupper)		
   156       end
   157 	    end
   157     val (mlower, mupper) = Inttab.fold app matrix (empty_matrix_const, empty_matrix_const)
   158 		
   158   in Inttab.fold app matrix (empty_matrix_const, empty_matrix_const) end;
   159 	val (mlower, mupper) = Inttab.foldl app ((empty_matrix_const, empty_matrix_const), matrix)
       
   160     in
       
   161 	Inttab.foldl app ((empty_matrix_const, empty_matrix_const), matrix)	
       
   162     end
       
   163 
   159 
   164 fun approx_vector prec pprt vector =
   160 fun approx_vector prec pprt vector =
   165     let
   161     let
   166 	val (l, u) = approx_vector_term prec pprt vector
   162 	val (l, u) = approx_vector_term prec pprt vector
   167     in
   163     in
   202 (* dual stuff *)
   198 (* dual stuff *)
   203 
   199 
   204 structure cplex = Cplex
   200 structure cplex = Cplex
   205 
   201 
   206 fun transpose_matrix matrix = 
   202 fun transpose_matrix matrix = 
   207     let
   203   let
   208 	fun upd m j i x =
   204     fun upd j (i, s) =
   209 	    case Inttab.lookup m j of
   205       Inttab.map_default (i, Inttab.empty) (Inttab.update (j, s));
   210 		SOME v => Inttab.update (j, Inttab.update (i, x) v) m
   206     fun updm (j, v) = Inttab.fold (upd j) v;
   211 	      | NONE => Inttab.update (j, Inttab.update (i, x) Inttab.empty) m
   207   in Inttab.fold updm matrix empty_matrix end;
   212 
       
   213 	fun updv j (m, (i, s)) = upd m i j s
       
   214 
       
   215 	fun updm (m, (j, v)) = Inttab.foldl (updv j) (m, v)
       
   216     in
       
   217 	Inttab.foldl updm (empty_matrix, matrix)
       
   218     end
       
   219 
   208 
   220 exception No_name of string;
   209 exception No_name of string;
   221 
   210 
   222 exception Superfluous_constr_right_hand_sides
   211 exception Superfluous_constr_right_hand_sides
   223 
   212 
   249 	    in
   238 	    in
   250 		if p then prod else cplex.cplexNeg prod
   239 		if p then prod else cplex.cplexNeg prod
   251 	    end
   240 	    end
   252 
   241 
   253 	fun vec2sum vector =
   242 	fun vec2sum vector =
   254 	    cplex.cplexSum (Inttab.foldl (fn (list, (index, s)) => (mk_term index s)::list) ([], vector))
   243 	    cplex.cplexSum (Inttab.fold (fn (index, s) => fn list => (mk_term index s) :: list) vector [])
   255 		       		       
   244 		       		       
   256 	fun mk_constr index vector c = 
   245 	fun mk_constr index vector c = 
   257 	    let 
   246 	    let 
   258 		val s = case Inttab.lookup c index of SOME s => s | NONE => "0"
   247 		val s = case Inttab.lookup c index of SOME s => s | NONE => "0"
   259 		val (p, s) = split_numstr s
   248 		val (p, s) = split_numstr s
   262 		(NONE, cplex.cplexConstr (cplex.cplexLeq, (vec2sum vector, num)))
   251 		(NONE, cplex.cplexConstr (cplex.cplexLeq, (vec2sum vector, num)))
   263 	    end
   252 	    end
   264 
   253 
   265 	fun delete index c = Inttab.delete index c handle Inttab.UNDEF _ => c
   254 	fun delete index c = Inttab.delete index c handle Inttab.UNDEF _ => c
   266 
   255 
   267 	val (list, b) = Inttab.foldl 
   256 	val (list, b) = Inttab.fold
   268 			    (fn ((list, c), (index, v)) => ((mk_constr index v c)::list, delete index c))
   257 			    (fn (index, v) => fn (list, c) => ((mk_constr index v c)::list, delete index c))
   269 			    (([], b), A)
   258 			    A ([], b)
   270 	val _ = if Inttab.is_empty b then () else raise Superfluous_constr_right_hand_sides
   259 	val _ = if Inttab.is_empty b then () else raise Superfluous_constr_right_hand_sides
   271 
   260 
   272 	fun mk_free y = cplex.cplexBounds (cplex.cplexNeg cplex.cplexInf, cplex.cplexLeq, 
   261 	fun mk_free y = cplex.cplexBounds (cplex.cplexNeg cplex.cplexInf, cplex.cplexLeq, 
   273 					   cplex.cplexVar y, cplex.cplexLeq,
   262 					   cplex.cplexVar y, cplex.cplexLeq,
   274 					   cplex.cplexInf)
   263 					   cplex.cplexInf)
   275 
   264 
   276 	val yvars = Inttab.foldl (fn (l, (i, y)) => (mk_free y)::l) ([], !ytable)
   265 	val yvars = Inttab.fold (fn (i, y) => fn l => (mk_free y)::l) (!ytable) []
   277 
   266 
   278 	val prog = cplex.cplexProg ("original", cplex.cplexMaximize (vec2sum c), list, yvars)
   267 	val prog = cplex.cplexProg ("original", cplex.cplexMaximize (vec2sum c), list, yvars)
   279     in
   268     in
   280 	(prog, indexof)
   269 	(prog, indexof)
   281     end
   270     end
   302 	    in
   291 	    in
   303 		if p then prod else cplex.cplexNeg prod
   292 		if p then prod else cplex.cplexNeg prod
   304 	    end
   293 	    end
   305 
   294 
   306 	fun vec2sum vector =
   295 	fun vec2sum vector =
   307 	    cplex.cplexSum (Inttab.foldl (fn (list, (index, s)) => (mk_term index s)::list) ([], vector))
   296 	    cplex.cplexSum (Inttab.fold (fn (index, s) => fn list => (mk_term index s)::list) vector [])
   308 		       		       
   297 		       		       
   309 	fun mk_constr index vector c = 
   298 	fun mk_constr index vector c = 
   310 	    let 
   299 	    let 
   311 		val s = case Inttab.lookup c index of SOME s => s | NONE => "0"
   300 		val s = case Inttab.lookup c index of SOME s => s | NONE => "0"
   312 		val (p, s) = split_numstr s
   301 		val (p, s) = split_numstr s
   315 		(NONE, cplex.cplexConstr (cplex.cplexEq, (vec2sum vector, num)))
   304 		(NONE, cplex.cplexConstr (cplex.cplexEq, (vec2sum vector, num)))
   316 	    end
   305 	    end
   317 
   306 
   318 	fun delete index c = Inttab.delete index c handle Inttab.UNDEF _ => c
   307 	fun delete index c = Inttab.delete index c handle Inttab.UNDEF _ => c
   319 
   308 
   320 	val (list, c) = Inttab.foldl 
   309 	val (list, c) = Inttab.fold 
   321 			    (fn ((list, c), (index, v)) => ((mk_constr index v c)::list, delete index c))
   310 			    (fn (index, v) => fn (list, c) => ((mk_constr index v c)::list, delete index c))
   322 			    (([], c), transpose_matrix A)
   311 			    (transpose_matrix A) ([], c)
   323 	val _ = if Inttab.is_empty c then () else raise Superfluous_constr_right_hand_sides
   312 	val _ = if Inttab.is_empty c then () else raise Superfluous_constr_right_hand_sides
   324 
   313 
   325 	val prog = cplex.cplexProg ("dual", cplex.cplexMinimize (vec2sum b), list, [])
   314 	val prog = cplex.cplexProg ("dual", cplex.cplexMinimize (vec2sum b), list, [])
   326     in
   315     in
   327 	(prog, indexof)
   316 	(prog, indexof)
   328     end
   317     end
   329 
   318 
   330 fun cut_vector size v = 
   319 fun cut_vector size v = 
   331     let
   320   let
   332 	val count = ref 0 
   321     val count = ref 0;
   333 	fun app (v, (i, s)) = 
   322     fun app (i, s) =  if (!count < size) then
   334 	    if (!count < size) then
   323         (count := !count +1 ; Inttab.update (i, s))
   335 		(count := !count +1 ; Inttab.update (i,s) v)
   324       else I
   336 	    else
   325   in
   337 		v
   326     Inttab.fold app v empty_vector
   338     in
   327   end
   339 	Inttab.foldl app (empty_vector, v)
       
   340     end
       
   341 
   328 
   342 fun cut_matrix vfilter vsize m = 
   329 fun cut_matrix vfilter vsize m = 
   343     let 
   330   let
   344 	fun app (m, (i, v)) = 
   331     fun app (i, v) = 
   345 	    if Inttab.lookup vfilter i = NONE then 
   332       if is_none (Inttab.lookup vfilter i) then I
   346 		m 
   333       else case vsize
   347 	    else 
   334        of NONE => Inttab.update (i, v)
   348 		case vsize of
   335         | SOME s => Inttab.update (i, cut_vector s v)
   349 		    NONE => Inttab.update (i,v) m
   336   in Inttab.fold app m empty_matrix end
   350 		  | SOME s => Inttab.update (i, cut_vector s v) m
   337 
   351     in
       
   352 	Inttab.foldl app (empty_matrix, m)
       
   353     end
       
   354 		 
       
   355 fun v_elem_at v i = Inttab.lookup v i
   338 fun v_elem_at v i = Inttab.lookup v i
   356 fun m_elem_at m i = Inttab.lookup m i
   339 fun m_elem_at m i = Inttab.lookup m i
   357 
   340 
   358 fun v_only_elem v = 
   341 fun v_only_elem v = 
   359     case Inttab.min_key v of
   342     case Inttab.min_key v of
   360 	NONE => NONE
   343 	NONE => NONE
   361       | SOME vmin => (case Inttab.max_key v of
   344       | SOME vmin => (case Inttab.max_key v of
   362 			  NONE => SOME vmin
   345 			  NONE => SOME vmin
   363 			| SOME vmax => if vmin = vmax then SOME vmin else NONE)
   346 			| SOME vmax => if vmin = vmax then SOME vmin else NONE)
   364 
   347 
   365 fun v_fold f a v = Inttab.foldl f (a,v) 
   348 fun v_fold f = Inttab.fold f;
   366 
   349 fun m_fold f = Inttab.fold f;
   367 fun m_fold f a m = Inttab.foldl f (a,m)
       
   368 
   350 
   369 end;
   351 end;