1% BEGIN LICENSE BLOCK 2% Version: CMPL 1.1 3% 4% The contents of this file are subject to the Cisco-style Mozilla Public 5% License Version 1.1 (the "License"); you may not use this file except 6% in compliance with the License. You may obtain a copy of the License 7% at www.eclipse-clp.org/license. 8% 9% Software distributed under the License is distributed on an "AS IS" 10% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 11% the License for the specific language governing rights and limitations 12% under the License. 13% 14% The Original Code is The List Collection for ECLiPSe. 15% The Initial Developer of the Original Code is Lukasz Domagala. 16% Portions created by the Initial Developer are Copyright (C) 2009. 17% All Rights Reserved. 18 19 20:- module(list_collection). 21 22:- comment(categories, ["Data Structures"]). 23:- comment(summary, "Collection of lists library"). 24:- comment(author, "Lukasz Domagala"). 25:- comment(copyright, "Silesian University of Technology"). 26:- comment(date, "$Date: 2009/07/16 09:11:23 $"). 27 28:- comment(desc,ascii(" 29 A library for creation and management of list collections (LCOL). 30 Internally the library uses either the a hashtable or arrays to store lists and their tails. 31 The advantage of a hash LCOL is that its size does not have to be known in advance and that 32 non number indexes can be used to address lists in the collection. The drawback of a hash LCOL 33 is that access to collection elements is slower than for array LCOL. Elements of array LCOL 34 can be addressed only by positive integers which internally are array indexes. See create/2 35 for more details. 36 37 The motivation for creating this library was to be able to easily build input lists for global 38 constraints from collections of input structures (see example). For this purpose an array(3) LCOL 39 was usually sufficient, and only a limited set of predicates needed (create/2 , append_element/3, 40 terminate_all_lists/2, get_list/3). 41 42 But the idea was extended, additional predicates were added for prefixing the lists, and 43 reinitialisation of lists. The support for hash LCOL has been added. Hash LCOL may be useful for 44 some filtering, grouping predicates in cases when the number of lists may vary or indexing by 45 atoms/ground terms is more readable/convenient. 46 47 ")). 48:- comment(eg," 49llcol_example:- 50 lib(ic), 51 lib(ic_edge_finder), 52 53 ActivityList=[ 54 act(4,7 ,2,machine_1), 55 act(3,4 ,1,machine_2 ), 56 act(2,4 ,2,removed), 57 act(7,10,1,machine_1), 58 act(6,15,3,machine_3) 59 % ... 60 ], 61 62 %create a collection of activity lists for corresponding machines 63 list_collection:create(hash,LCOL_Machines), 64 65 %sort the activities for machines 66 (foreach(Activity,ActivityList), 67 param(LCOL_Machines) do 68 Activity=act(_Start,_End,_Resource,Machine), 69 (Machine \\= removed -> 70 %add an activity to the list for the particular machine 71 list_collection:append_element(LCOL_Machines,Machine,Activity) 72 ;true) 73 ), 74 75 %close the lists get the machine names 76 list_collection:terminate_all_lists(LCOL_Machines,Machines_Indexes), 77 78 %for each machine 79 (foreach(Machines_Index,Machines_Indexes), 80 param(LCOL_Machines) do 81 %Note that get_list/3 can be used even if the lists are not terminated but in such a case the operation 82 %is more time consuming, because all the list elements are copied to new closed list and then returned. 83 %Instead of closing all the lists at once it is also possible to use terminate_and_get_list/3 to ensure 84 %that the list is closed. 85 86 %get the activity list for the machine 87 list_collection:get_list(LCOL_Machines,Machines_Index,MActivityList), 88 89 %create a collection for start,duration and resource variable lists 90 list_collection:create(array(3),LCOL_Start_Dur_Res), 91 92 (foreach(MActivity,MActivityList), 93 param(LCOL_Start_Dur_Res) do 94 95 MActivity=act(Start,End,Resource,_Machine), 96 ic:(Duration #= End - Start), 97 list_collection:append_element(LCOL_Start_Dur_Res, 1, Start), 98 list_collection:append_element(LCOL_Start_Dur_Res, 2, Duration), 99 list_collection:append_element(LCOL_Start_Dur_Res, 3, Resource) 100 ), 101 102 %terminate the start,duration,resource lists 103 list_collection:terminate_all_lists(LCOL_Start_Dur_Res,_Indexes), 104 105 %get the lists for a cumulative constraint 106 list_collection:get_list(LCOL_Start_Dur_Res, 1, StartList), 107 list_collection:get_list(LCOL_Start_Dur_Res, 2, DurationList), 108 list_collection:get_list(LCOL_Start_Dur_Res, 3, ResourceList), 109 110 %post the constraint 111 ic_edge_finder:cumulative(StartList, DurationList, ResourceList, 3) 112 ). 113 "). 114 115:- lib(hash). 116 117 118:- local struct(list_collection( 119 type, 120 open_list_array, 121 tail_array, 122 list_tail_hash 123 )). 124 125:- comment(create/2, 126 [ 127 amode:(create(++,-) is det), 128 args:["Type":"A ground term", "LCOL":"A list collection"], 129 summary:"Creates a list collection", 130 desc:ascii(" 131 If (Type==hash) a LCOL internally uses a hashtable, this is useful when the number of lists is unknown. 132 If (Type=array(Size)) where Size is a natural number, the LCOL internally uses an array to collect lists, 133 the access to any of the lists is faster, but the Size has to be known in advance and only number 134 indexes can be used to identify lists. 0<Index=<Size."), 135 %eg:"", 136 see_also:[append_element/3,terminate_all_lists/2,get_list/3], 137 %fail_if:"" , 138 exceptions:[ 139 5:"Not supported Type." 140 ] 141 ]). 142 143:-export create/2. 144:- mode(create(++,-)). 145create(array(Size),LCOL):- 146 LCOL=list_collection{ 147 type:array(Size), 148 open_list_array:OpenListArray, 149 tail_array :TailArray, 150 list_tail_hash :not_used 151 }, 152 number(Size),0<Size, 153 !, 154 dim(OpenListArray,[Size]), 155 dim(TailArray,[Size]), 156 (count(Index,1,Size), 157 param(OpenListArray,TailArray) do 158 setarg(Index,OpenListArray,ListTail), 159 setarg(Index,TailArray,ListTail) 160 ), 161 true. 162 163create(hash, LCOL):- 164 LCOL=list_collection{ 165 type:hash, 166 open_list_array:not_used, 167 tail_array :not_used, 168 list_tail_hash :ListTailHash 169 }, 170 !, 171 hash_create(ListTailHash), 172 true. 173 174create(_Type, _LCOL):- 175 exc_not_supported_type. 176 177:- comment(append_element/3, 178 [ 179 amode:(append_element(+,++,+) is det), 180 args:["LCOL":"A list collection", "Index":"A ground term or number", 181 "Elem":"Term or variable"], 182 summary:"Append an Elem to the internal list identified by Index.", 183 desc:"Complexity O(1).", 184 %eg:"", 185 see_also:[append_list/3,prefix_element/3,prefix_list/3], 186 %fail_if:"", 187 exceptions:[ 188 5:"LCOL is not a list collection.", 189 5:"Index is not a number or is out of range.", 190 5:"Index is not ground.", 191 1:"List identified by Index is closed." 192 ] 193 ]). 194:-export append_element/3. 195:- mode(append_element(+,++,+)). 196append_element(LCOL, Index, Elem):- 197 check_lcol_exc(LCOL), 198 check_index_exc(LCOL, Index), 199 ensure_entry_exists_4_index(LCOL, Index, LTTerm), 200 check_open_tail_exc(LCOL, Index, LTTerm), 201 202 inner_tail_get(LCOL,Index,LTTerm, [Elem|NewTail]), 203 inner_tail_set(LCOL,Index,LTTerm, NewTail), 204 205 true. 206 207 208 209:- comment(append_list/3, 210 [ 211 amode:(append_list(+,++,+) is det), 212 args:["LCOL":"A list collection", "Index":"A ground term or number", 213 "List":"A list of terms or variables"], 214 summary:"Append a List to the internal list identified by Index.", 215 desc:"Complexity O(|List|).", 216 %eg:"", 217 see_also:[append_element/3,prefix_element/3,prefix_list/3], 218 % fail_if:"", 219 exceptions:[ 220 5:"LCOL is not a list collection.", 221 5:"Index is not a number or is out of range.", 222 5:"Index is not ground.", 223 1:"List identified by Index is closed." 224 ] 225 ]). 226:-export append_list/3. 227:- mode(append_list(+,++,+)). 228append_list(LCOL, Index, List):- 229 check_lcol_exc(LCOL), 230 check_index_exc(LCOL, Index), 231 ensure_entry_exists_4_index(LCOL, Index,LTTerm), 232 check_open_tail_exc(LCOL, Index,LTTerm), 233 234 inner_tail_get(LCOL,Index,LTTerm,OldTail), 235 236 (foreach(Elem,List), 237 fromto(OldTail,[Elem|OldTailOut],OldTailOut,NewTail) do 238 true 239 ), 240 241 inner_tail_set(LCOL,Index,LTTerm,NewTail), 242 243 true. 244 245:- comment(prefix_element/3, 246 [ 247 amode:(prefix_element(+,++,+) is det), 248 args:["LCOL":"A list collection", "Index":"A ground term or number", 249 "Elem":"Term or variable"], 250 summary:"Prefixes the internal list identified by Index with an Elem.", 251 desc:" Complexity O(1)", 252 %eg:"", 253 see_also:[append_element/3,append_list/3,prefix_list/3], 254 % fail_if:"", 255 exceptions:[ 256 5:"LCOL is not a list collection.", 257 5:"Index is not a number or is out of range.", 258 5:"Index is not ground." 259 ] 260 ]). 261:- export prefix_element/3. 262:- mode(prefix_element(+,++,+)). 263prefix_element(LCOL, Index, Elem):- 264 prefix_list(LCOL, Index, [Elem]), 265 true. 266 267 268:- comment(prefix_list/3, 269 [ 270 amode:(prefix_list(+,++,+) is det), 271 args:["LCOL":"A list collection", "Index":"A ground term or number", 272 "List":"A list of terms or variables"], 273 summary:"Prefixes the internal list identified by Index with a List.", 274 desc:"Complexity O(|List|).", 275 %eg:"", 276 see_also:[append_element/3,append_list/3,prefix_list/3], 277 % fail_if:"", 278 exceptions:[ 279 5:"LCOL is not a list collection.", 280 5:"Index is not a number or is out of range.", 281 5:"Index is not ground." 282 ] 283 ]). 284:-export prefix_list/3. 285:- mode(prefix_list(+,++,+)). 286prefix_list(LCOL, Index, List):- 287 check_lcol_exc(LCOL), 288 check_index_exc(LCOL, Index), 289 ensure_entry_exists_4_index(LCOL, Index,LTTerm), 290 291 (foreach(Elem,List), 292 fromto(NewList,[Elem|NewListOut],NewListOut,NewListTail) do 293 true 294 ), 295 296 inner_list_get(LCOL,Index,LTTerm,OldList), 297 inner_list_set(LCOL,Index,LTTerm,NewList), 298 NewListTail = OldList, 299 true. 300 301 302:- comment(get_list/3, 303 [ 304 amode:(get_list(+,++,-) is det), 305 args:["LCOL":"A list collection", "Index":"A ground term or number", 306 "List":"A list of terms"], 307 summary:"Retrieves the list of elements identified by Index", 308 desc:"If the internal list identified by Index is open, the elements from the list are copied to a closed List and returned. The internal list remains open. Complexity O(|List|). 309 If the internal list identified by Index is closed, the internal list is returned immediately as List. Complexity O(1).", 310 %eg:"", 311 see_also:[terminate_all_lists/2,terminate_and_get_list/3], 312 %fail_if:"" , 313 exceptions:[ 314 5:"LCOL is not a list collection.", 315 5:"Index is not a number or is out of range.", 316 5:"Index is not ground." 317 ] 318 ]). 319:-export get_list/3. 320:- mode(get_list(+,++,-)). 321get_list(LCOL, Index, List):- 322 check_lcol_exc(LCOL), 323 check_index_exc(LCOL, Index), 324 ensure_entry_exists_4_index(LCOL, Index,LTTerm), 325 326 inner_list_get(LCOL,Index,LTTerm,OpenList), 327 inner_tail_get(LCOL,Index,LTTerm,OpenListTail), 328 329 (OpenListTail==[] -> 330 %if the list is closed there is no need to copy the elements, just get list 331 List = OpenList 332 ; 333 (free(OpenList)-> 334 %empty list 335 List=[] 336 337 ; 338 (fromto(OpenList,[Elem|OpenListNext],OpenListOut,[]), 339 foreach(Elem,List), 340 param(OpenListTail) do 341 (OpenListNext\==OpenListTail-> 342 OpenListOut = OpenListNext 343 ; 344 OpenListOut=[] 345 ) 346 ) 347 ) 348 ), 349 true. 350 351:- comment(terminate_and_get_list/3, 352 [ 353 amode:(terminate_and_get_list(+,++,-) is det), 354 args:["LCOL":"A list collection", "Index":"A ground term or number", 355 "List":"A list of terms"], 356 summary:"Retrieves the List of elements identified by Index", 357 desc:"Ensures that the internal List of elements identified by Index is terminated, and returns the internal List. Complexity O(1).", 358 %eg:"", 359 see_also:[get_list/3, terminate_all_lists/2,reinit/2], 360 % fail_if:"" , 361 exceptions:[ 362 5:"LCOL is not a list collection.", 363 5:"Index is not a number or is out of range.", 364 5:"Index is not ground." 365 ] 366 ]). 367:-export terminate_and_get_list/3. 368:- mode(terminate_and_get_list(+,++,-)). 369terminate_and_get_list(LCOL, Index, List):- 370 check_lcol_exc(LCOL), 371 check_index_exc(LCOL, Index), 372 ensure_entry_exists_4_index(LCOL, Index,LTTerm), 373 374 inner_tail_get(LCOL,Index,LTTerm,[]), 375 inner_list_get(LCOL,Index,LTTerm,List), 376 true. 377 378:- comment(terminate_all_lists/2, 379 [ 380 amode:(terminate_all_lists(+,-) is det), 381 args:["LCOL":"A list collection", "Indexes":"List of indexes"], 382 summary:"Terminates all internal lists in the collection, and gets the list of indexes", 383 desc:"Complexity O(ListCount).", 384 %eg:"", 385 see_also:[get_list/3,terminate_and_get_list/3,reinit/2,get_indexes/2], 386 %fail_if:"" 387 exceptions:[ 388 5:"LCOL is not a list collection." 389 ] 390 ]). 391 392 393:-export terminate_all_lists/2. 394:- mode(terminate_all_lists(+,-)). 395terminate_all_lists(LCOL,Indexes):- 396 check_lcol_exc(LCOL), 397 LCOL=list_collection{ 398 type:hash, 399 open_list_array:_OpenListArray, 400 tail_array :_TailArray, 401 list_tail_hash :ListTailHash 402 }, 403 !, 404 hash_list(ListTailHash,IndexesUnsorted,LTTermLi), 405 sort(IndexesUnsorted,Indexes), 406 (foreach(list_tail(_,[]),LTTermLi) do 407 true 408 ), 409 true. 410 411terminate_all_lists(LCOL,Indexes):- 412 check_lcol_exc(LCOL), 413 LCOL=list_collection{ 414 type:array(_Size), 415 open_list_array:_OpenListArray, 416 tail_array :TailArray, 417 list_tail_hash :_ListTailHash 418 }, 419 !, 420 (foreacharg([],TailArray,Index), 421 foreach(Index,Indexes) do 422 true 423 ), 424 true. 425 426:- comment(get_indexes/2, 427 [ 428 amode:(get_indexes(+,-) is det), 429 args:["LCOL":"A list collection", "Indexes":"List of indexes"], 430 summary:"Retrieves the list of indexes", 431 desc:"Complexity O(ListCount).", 432 %eg:"", 433 see_also:[get_list/3,terminate_and_get_list/3,terminate_all_lists/2], 434 %fail_if:"" 435 exceptions:[ 436 5:"LCOL is not a list collection." 437 ] 438 ]). 439 440 441:-export get_indexes/2. 442:- mode(get_indexes(+,-)). 443get_indexes(LCOL,Indexes):- 444 check_lcol_exc(LCOL), 445 LCOL=list_collection{ 446 type:hash, 447 open_list_array:_OpenListArray, 448 tail_array :_TailArray, 449 list_tail_hash :ListTailHash 450 }, 451 !, 452 hash_list(ListTailHash,IndexesUnsorted,_LTTermLi), 453 sort(IndexesUnsorted,Indexes), 454 true. 455 456get_indexes(LCOL,Indexes):- 457 check_lcol_exc(LCOL), 458 LCOL=list_collection{ 459 type:array(_Size), 460 open_list_array:_OpenListArray, 461 tail_array :TailArray, 462 list_tail_hash :_ListTailHash 463 }, 464 !, 465 (foreacharg(_Tail,TailArray,Index), 466 foreach(Index,Indexes) do 467 true 468 ), 469 true. 470 471 472 473 474:- comment(reinit/2, 475 [ 476 amode:(reinit(+,++) is det), 477 args:["LCOL":"A list collection", "Index":"A ground term or number"], 478 summary:"Creates a new list identified by Index", 479 desc:"Discards the internal list of elements identified by Index, and replaces with a new list. Complexity O(1).", 480 %eg:"", 481 see_also:[terminate_all_lists/2,terminate_and_get_list/3], 482 %fail_if:"" , 483 exceptions:[ 484 5:"LCOL is not a list collection.", 485 5:"Index is not a number or is out of range.", 486 5:"Index is not ground." 487 ] 488 ]). 489:-export reinit/2. 490:- mode(reinit(+,++)). 491reinit(LCOL, Index):- 492 check_lcol_exc(LCOL), 493 !, 494 check_index_exc(LCOL, Index), 495 ensure_entry_exists_4_index(LCOL, Index,LTTerm), 496 inner_list_set(LCOL,Index,LTTerm,ListTail), 497 inner_tail_set(LCOL,Index,LTTerm,ListTail), 498 true. 499 500inner_tail_get(LCOL,Index,LTTerm,Tail):- 501 LCOL=list_collection{ 502 type:Type, 503 open_list_array:_OpenListArray, 504 tail_array :TailArray, 505 list_tail_hash :_ListTailHash 506 }, 507 (Type == hash, not free(LTTerm) -> 508 LTTerm = list_tail(_OpenList,Tail) 509 ; 510 (instance(Type,array(_Size))-> 511 arg(Index,TailArray,Tail) 512 ; 513 exc_not_supported_type 514 ) 515 ). 516 517inner_tail_set(LCOL,Index,LTTerm,Tail):- 518 LCOL=list_collection{ 519 type:Type, 520 open_list_array:_OpenListArray, 521 tail_array :TailArray, 522 list_tail_hash :_ListTailHash 523 }, 524 (Type == hash,not free(LTTerm) -> 525 setarg(2,LTTerm,Tail) 526 ; 527 (instance(Type,array(_Size))-> 528 setarg(Index,TailArray,Tail) 529 ; 530 exc_not_supported_type 531 ) 532 ). 533inner_list_get(LCOL,Index,LTTerm,OpenList):- 534 LCOL=list_collection{ 535 type:Type, 536 open_list_array:OpenListArray, 537 tail_array :_TailArray 538 }, 539 (Type == hash,not free(LTTerm) -> 540 LTTerm= list_tail(OpenList,_Tail) 541 ; 542 (instance(Type,array(_Size))-> 543 arg(Index,OpenListArray,OpenList) 544 ; 545 exc_not_supported_type 546 ) 547 ). 548inner_list_set(LCOL,Index,LTTerm,OpenList):- 549 LCOL=list_collection{ 550 type:Type, 551 open_list_array:OpenListArray, 552 tail_array :_TailArray, 553 list_tail_hash :_ListTailHash 554 }, 555 (Type == hash,not free(LTTerm) -> 556 setarg(1,LTTerm,OpenList) 557 ; 558 (instance(Type,array(_Size))-> 559 setarg(Index,OpenListArray,OpenList) 560 ; 561 exc_not_supported_type 562 ) 563 ). 564 565 566ensure_entry_exists_4_index(LCOL, Index,LTTerm):- 567 LCOL=list_collection{ 568 type:hash, 569 open_list_array:_OpenListArray, 570 tail_array :_TailArray, 571 list_tail_hash :ListTailHash 572 }, 573 !, 574 575 (hash_contains(ListTailHash,Index)-> 576 hash_get(ListTailHash,Index,LTTerm) 577 ; 578 functor(LTTerm,list_tail,2), 579 setarg(1,LTTerm,ListTail), 580 setarg(2,LTTerm,ListTail), 581 hash_add(ListTailHash,Index,LTTerm) 582 ), 583 true. 584 585ensure_entry_exists_4_index(LCOL, _Index,_LTTerm):- 586 LCOL=list_collection{ 587 type:array(_Size), 588 open_list_array:_OpenListArray, 589 tail_array :_TailArray 590 }, 591 !, 592 true. 593 594check_index_exc(LCOL, Index):- 595 LCOL=list_collection{ 596 type:hash, 597 open_list_array:_OpenListArray, 598 tail_array :_TailArray, 599 list_tail_hash :_ListTailHash 600 }, 601 (ground(Index)-> 602 true 603 ; 604 exc_index_is_not_ground 605 ),!. 606 607check_index_exc(LCOL, Index):- 608 LCOL=list_collection{ 609 type:array(Size), 610 open_list_array:_OpenListArray, 611 tail_array :_TailArray, 612 list_tail_hash :_ListTailHash 613 }, 614 (number(Index),0<Index,Index=<Size-> 615 true 616 ; 617 exc_index_is_not_a_num_or_out_of_range 618 ),!. 619 620check_open_tail_exc(LCOL, Index,LTTerm):- 621 inner_tail_get(LCOL,Index,LTTerm,Tail), 622 (free(Tail)-> 623 true 624 ; 625 exc_list_is_closed 626 ). 627 628check_lcol_exc(LCOL):- 629 (instance(LCOL,list_collection{}), 630 LCOL=list_collection{ 631 type:Type, 632 open_list_array:_OpenListArray, 633 tail_array :_TailArray, 634 list_tail_hash :_ListTailHash 635 }, 636 ground(Type) -> 637 638 true 639 ; 640 exc_lcol_is_not_a_proper_structure 641 ), 642 true. 643 644exc_lcol_is_not_a_proper_structure:- 645 writeln(error,"LCOL is not a list collection."), 646 exit_block(lcol_exception). 647 648exc_not_supported_type:- 649 writeln(error,"Not supported Type."), 650 exit_block(lcol_exception). 651 652exc_list_is_closed:- 653 writeln(error,"List identified by Index is closed."), 654 exit_block(lcol_exception). 655 656exc_index_is_not_a_num_or_out_of_range:- 657 writeln(error,"Index is not a number or is out of range."), 658 exit_block(lcol_exception). 659 660exc_index_is_not_ground:- 661 writeln(error,"Index is not ground."), 662 exit_block(lcol_exception). 663 664 665%---------------------------------------------------------------------- 666end_of_file. 667%---------------------------------------------------------------------- 668 669%just for testing if documentation is generated properly 670lcol_test_generate_doc:- 671 get_flag(cwd, Cwd), 672 concat_string([Cwd,"list_collection.ecl"],File), 673 document:icompile(File), 674 document:eci_to_html("list_collection.eci", Cwd, ""), 675 676 true. 677 678%self testing of the library, the predicate has to be true 679lcol_self_test:- 680 block( 681 lcol_self_test_lcol_type(wrong_type) 682 ,lcol_exception, true), 683 684 lcol_self_test_lcol_type(hash), 685 lcol_self_test_lcol_type(array(3)), 686 true. 687 688lcol_self_test_lcol_type(LCOL_Type):- 689 %Create a Collection Of Lists 690 list_collection:create(LCOL_Type,LCOL), 691 692 %appending elements to List1 and List2 693 list_collection:append_element(LCOL, 1, list_1_elem_1), 694 list_collection:append_element(LCOL, 1, list_1_elem_2), 695 list_collection:append_element(LCOL, 2, list_2_elem_1), 696 list_collection:append_element(LCOL, 2, list_2_elem_2), 697 698 %prefixig the List1 by an element 699 list_collection:prefix_element(LCOL, 1, list_1_pref_1), 700 %prefixing the List2 by a list of elements 701 list_collection:prefix_list(LCOL,2,[list_2_pref_2,list_2_pref_1]), 702 %appending a list of alements to List3 703 list_collection:append_list(LCOL,3,[list_3_elem_1,list_3_elem_2]), 704 705 %getting the List1 elements without closing the internal List1 706 get_list(LCOL,1,List1Elements), 707 List1Elements = [list_1_pref_1,list_1_elem_1,list_1_elem_2], 708 709 %still possible to append to List1 because it is not closed 710 list_collection:append_element(LCOL, 1, list_1_elem_3), 711 %terminating the List1 and retrieving it 712 terminate_and_get_list(LCOL, 1, List1), 713 List1 == [list_1_pref_1,list_1_elem_1,list_1_elem_2,list_1_elem_3], 714 block( 715 %the following would cause an exception because the List1 is closed 716 ( 717 list_collection:append_element(LCOL, 1, list_1_elem_4), 718 fail 719 ) 720 ,lcol_exception, true), 721 %but it is possible to prefix the List1 722 list_collection:prefix_element(LCOL, 1, list_1_pref_2), 723 terminate_and_get_list(LCOL, 1, List1Prefixed), 724 List1Prefixed == [list_1_pref_2,list_1_pref_1,list_1_elem_1,list_1_elem_2,list_1_elem_3], 725 %internally List1 is discarded and a new List1 is created 726 reinit(LCOL,1), 727 get_list(LCOL,1,List1NewElements), 728 List1NewElements == [], 729 list_collection:append_element(LCOL, 1, list_1_elem_1), 730 terminate_and_get_list(LCOL, 1, List1New), 731 List1New == [list_1_elem_1], 732 block( 733 %the following would cause an exception but only for the array(3) LCOL 734 %because the index is out of range 735 (LCOL_Type == array(3) -> 736 terminate_and_get_list(LCOL, 4, _List4Treminated), 737 fail 738 ;true) 739 %for a hash LCOL it would not cause an exception, 740 %a new list for index 4 would be created closed and returned 741 ,lcol_exception, true), 742 743 %terminate all the lists 744 terminate_all_lists(LCOL,Indexes), 745 Indexes = [1,2,3], 746 %check the get_indexes 747 get_indexes(LCOL,Indexes), 748 %after all the lists are terminated get_list/3 does not need to copy the elements 749 %to a new terminated list as above, it just gives back the internal lists 750 get_list(LCOL, 2, List2Treminated), 751 List2Treminated == [list_2_pref_2,list_2_pref_1,list_2_elem_1,list_2_elem_2], 752 get_list(LCOL, 3, List3Treminated), 753 List3Treminated == [list_3_elem_1,list_3_elem_2], 754 755 true. 756 757%example 758lcol_example:- 759 lib(ic), 760 lib(ic_edge_finder), 761 762 ActivityList=[ 763 act(4,7 ,2,machine_1), 764 act(3,4 ,1,machine_2 ), 765 act(2,4 ,2,removed), 766 act(7,10,1,machine_1), 767 act(6,15,3,machine_3) 768 % ... 769 ], 770 771 %create a collection of activity lists for corresponding machines 772 list_collection:create(hash,LCOL_Machines), 773 774 %sort the activities for machines 775 (foreach(Activity,ActivityList), 776 param(LCOL_Machines) do 777 Activity=act(_Start,_End,_Resource,Machine), 778 (Machine \= removed -> 779 %add an activity to the list for the particular machine 780 list_collection:append_element(LCOL_Machines,Machine,Activity) 781 ;true) 782 ), 783 784 %close the lists get the machine names 785 list_collection:terminate_all_lists(LCOL_Machines,Machines_Indexes), 786 787 %for each machine 788 (foreach(Machines_Index,Machines_Indexes), 789 param(LCOL_Machines) do 790 %Note that get_list/3 can be used even if the lists are not terminated but in such a case the operation 791 %is more time consuming, because all the list elements are copied to new closed list and then returned. 792 %Instead of closing all the lists at once it is also possible to use terminate_and_get_list/3 to ensure 793 %that the list is closed. 794 795 %get the activity list for the machine 796 list_collection:get_list(LCOL_Machines,Machines_Index,MActivityList), 797 798 %create a collection for start,duration and resource variable lists 799 list_collection:create(array(3),LCOL_Start_Dur_Res), 800 801 (foreach(MActivity,MActivityList), 802 param(LCOL_Start_Dur_Res) do 803 804 MActivity=act(Start,End,Resource,_Machine), 805 ic:(Duration #= End - Start), 806 list_collection:append_element(LCOL_Start_Dur_Res, 1, Start), 807 list_collection:append_element(LCOL_Start_Dur_Res, 2, Duration), 808 list_collection:append_element(LCOL_Start_Dur_Res, 3, Resource) 809 ), 810 811 %terminate the start,duration,resource lists 812 list_collection:terminate_all_lists(LCOL_Start_Dur_Res,_Indexes), 813 814 %get the lists for a cumulative constraint 815 list_collection:get_list(LCOL_Start_Dur_Res, 1, StartList), 816 list_collection:get_list(LCOL_Start_Dur_Res, 2, DurationList), 817 list_collection:get_list(LCOL_Start_Dur_Res, 3, ResourceList), 818 819 %post the constraint 820 ic_edge_finder:cumulative(StartList, DurationList, ResourceList, 3) 821 ).