1#############################################################################
2##
3##  ToDoListEntry.gi                                 ToolsForHomalg package
4##
5##  Copyright 2007-2012, Mohamed Barakat, University of Kaiserslautern
6##                       Sebastian Gutsche, RWTH-Aachen University
7##                  Markus Lange-Hegermann, RWTH-Aachen University
8##
9##  Entries for ToDo-Lists.
10##
11#############################################################################
12
13InstallValue( TODO_LIST_ENTRIES,
14              rec(
15                  already_installed_immediate_methods := [ ],
16                  implications := [ ]
17              )
18);
19
20DeclareRepresentation( "IsToDoListEntryRep",
21                       IsToDoListEntry and IsAttributeStoringRep,
22                       []
23                     );
24
25DeclareRepresentation( "IsToDoListEntryForEquivalentPropertiesRep",
26                       IsToDoListEntryRep,
27                       []
28                     );
29
30DeclareRepresentation( "IsToDoListEntryForEqualPropertiesRep",
31                       IsToDoListEntryRep,
32                       []
33                     );
34
35DeclareRepresentation( "IsToDoListEntryWithListOfSourcesRep",
36                       IsToDoListEntryRep,
37                       []
38                     );
39
40DeclareRepresentation( "IsToDoListEntryWhichLaunchesAFunctionRep",
41                       IsToDoListEntryWithListOfSourcesRep,
42                       []
43                     );
44
45DeclareRepresentation( "IsToDoListEntryWithDefinedTargetRep",
46                       IsToDoListEntryWithListOfSourcesRep,
47                       []
48                     );
49
50DeclareRepresentation( "IsToDoListEntryWithSingleSourceRep",
51                       IsToDoListEntryWithDefinedTargetRep,
52                       []
53                      );
54
55DeclareRepresentation( "IsToDoListEntryWithWeakPointersRep",
56                       IsToDoListEntryWithSingleSourceRep,
57                       []
58                     );
59
60DeclareRepresentation( "IsToDoListEntryWithPointersRep",
61                       IsToDoListEntryWithSingleSourceRep,
62                       []
63                     );
64
65DeclareRepresentation( "IsToDoListEntryWithContrapositionRep",
66                       IsToDoListEntryRep,
67                       []
68                     );
69
70DeclareRepresentation( "IsToDoListEntryMadeFromOtherToDoListEntriesRep",
71                       IsToDoListEntryRep,
72                       []
73                     );
74
75BindGlobal( "TheFamilyOfToDoListEntries",
76        NewFamily( "TheFamilyOfToDoListEntries" ) );
77
78BindGlobal( "TheTypeToDoListEntryWithWeakPointers",
79        NewType( TheFamilyOfToDoListEntries,
80                IsToDoListEntryWithWeakPointersRep ) );
81
82BindGlobal( "TheTypeToDoListEntryWithPointers",
83        NewType( TheFamilyOfToDoListEntries,
84                IsToDoListEntryWithPointersRep ) );
85
86BindGlobal( "TheTypeToDoListEntryForEquivalentProperties",
87        NewType( TheFamilyOfToDoListEntries,
88                IsToDoListEntryForEquivalentPropertiesRep ) );
89
90BindGlobal( "TheTypeToDoListEntryForEqualProperties",
91        NewType( TheFamilyOfToDoListEntries,
92                IsToDoListEntryForEqualPropertiesRep ) );
93
94BindGlobal( "TheTypeToDoListEntryMadeFromOtherToDoListEntries",
95        NewType( TheFamilyOfToDoListEntries,
96                IsToDoListEntryMadeFromOtherToDoListEntriesRep ) );
97
98BindGlobal( "TheTypeToDoListEntryWithListOfSources",
99        NewType( TheFamilyOfToDoListEntries,
100                IsToDoListEntryWithDefinedTargetRep ) );
101
102BindGlobal( "TheTypeToDoListWhichLaunchesAFunction",
103        NewType( TheFamilyOfToDoListEntries,
104                IsToDoListEntryWhichLaunchesAFunctionRep ) );
105
106BindGlobal( "TheTypeToDoListEntryWithContraposition",
107        NewType( TheFamilyOfToDoListEntries,
108                IsToDoListEntryWithContrapositionRep ) );
109
110##########################################
111##
112## Methods
113##
114##########################################
115
116##
117BindGlobal( "TODOLIST_ADD_TO_RECORD_AT_POSITION",
118
119  function( record, position, entry )
120
121    if not IsBound( record.( position ) ) then
122
123        record.( position ) := [ ];
124
125    elif ForAny( record.( position ), i -> IsIdenticalObj( i, entry ) ) then
126
127        return;
128
129   fi;
130
131   Add( record.( position ), entry );
132
133end );
134
135##
136InstallMethod( \=,
137               [ IsToDoListEntry, IsToDoListEntry ],
138
139  IsIdenticalObj
140
141);
142
143##
144InstallGlobalFunction( ToDoLists_Process_Entry_Part,
145
146  function( entry_list )
147
148    if IsFunction( entry_list ) then
149
150        return entry_list();
151
152    elif IsList( entry_list ) and Length( entry_list ) > 0 and IsFunction( entry_list[ 1 ] ) then
153
154        return CallFuncList( entry_list[ 1 ], entry_list{[ 2 .. Length( entry_list ) ]} );
155
156    fi;
157
158    return entry_list;
159
160end );
161
162##
163InstallMethod( ToDoLists_Move_To_Target_ToDo_List,
164               "for entries",
165               [ IsToDoListEntryWithDefinedTargetRep ],
166
167  function( entry )
168    local source_list, target, source;
169
170    source_list := SourcePart( entry );
171
172    if source_list = fail then
173
174        return;
175
176    fi;
177
178    for source in source_list do
179
180        if IsBound( source[ 3 ] ) then
181
182            source[ 3 ] := ToDoLists_Process_Entry_Part( source[ 3 ] );
183
184        elif IsString( source[ 2 ] ) and not IsBound( source[ 3 ] ) and Tester( ValueGlobal( source[ 2 ] ) )( source[ 1 ] ) then
185
186            Add( source, ValueGlobal( source[ 2 ] )( source[ 1 ] ) );
187
188        fi;
189
190    od;
191
192    target := TargetPart( entry );
193
194    if target = fail then
195
196        return;
197
198    fi;
199
200    SetTargetObject( entry, ToDoLists_Process_Entry_Part( target[ 1 ] ) );
201
202    SetTargetValueObject( entry, ToDoLists_Process_Entry_Part( target[ 3 ] ) );
203
204    target := target[ 1 ];
205
206    if Position( ToDoList( target )!.from_others, entry ) = fail then
207
208        Add( ToDoList( target )!.from_others, entry );
209
210    fi;
211
212end );
213
214##
215InstallMethod( ToDoLists_Move_To_Target_ToDo_List,
216               "for all entries",
217               [ IsToDoListEntry ],
218
219  function( entry )
220
221end );
222
223##
224InstallGlobalFunction( ToolsForHomalg_ProcessToDoListEquivalencesAndContrapositions,
225
226  function( entry )
227    local i;
228
229    if IsBound( entry!.contrapositions ) then
230
231        for i in entry!.contrapositions do
232
233            SetFilterObj( i, PreconditionsDefinitelyNotFulfilled );
234
235        od;
236
237    fi;
238
239    if IsBound( entry!.equivalences ) then
240
241        for i in entry!.equivalences do
242
243            SetFilterObj( i, IsProcessedEntry );
244
245        od;
246
247    fi;
248
249end );
250
251##
252InstallGlobalFunction( ToolsForHomalg_CheckASourcePart,
253
254  function( source_part )
255    local pull_attr, comparator, i;
256
257    if ( not IsList( source_part ) ) or Length( source_part ) < 2 or Length( source_part ) > 4 then
258
259        Error( "not a valid argument" );
260
261        return fail;
262
263    fi;
264
265    if not IsString( source_part[ 2 ] ) then
266
267        if ForAll( source_part[ 2 ], i -> Tester( ValueGlobal( i ) )( source_part[ 1 ] ) ) then
268
269            if not IsBound( source_part[ 3 ] ) then
270
271                return true;
272
273            elif source_part[ 3 ]() then
274
275                source_part[ 3 ] := true;
276
277                return true;
278
279            else
280
281                source_part[ 3 ] := false;
282
283                return fail;
284
285            fi;
286
287        else
288
289            return false;
290
291        fi;
292
293    fi;
294
295    pull_attr := ValueGlobal( source_part[ 2 ] );
296
297    if Length( source_part ) = 4 and IsFunction( source_part[ 4 ] ) then
298
299        comparator := source_part[ 4 ];
300
301    else
302
303        comparator := \=;
304
305    fi;
306
307    if not Tester( pull_attr )( source_part[ 1 ] ) then
308
309        return false;
310
311    elif Length( source_part ) = 3 then
312
313        if IsList( source_part[ 3 ] ) then
314
315            source_part[ 3 ] := ToDoLists_Process_Entry_Part( source_part[ 3 ] );
316
317        fi;
318
319        if not comparator( pull_attr( source_part[ 1 ] ), source_part[ 3 ] ) then
320
321            return fail;
322
323        fi;
324
325    fi;
326
327    return true;
328
329end );
330
331##########################################
332##
333## General methods
334##
335##########################################
336
337##
338InstallMethod( AddToToDoList,
339               "for lists",
340               [ IsList ],
341
342  function( entry_list )
343
344    Perform( entry_list, AddToToDoList );
345
346end );
347
348##
349InstallMethod( AddToToDoList,
350               "for a todo list entry",
351               [ IsToDoListEntryWithListOfSourcesRep ],
352
353  function( entry )
354    local result, source, source_list, source_object_list, todo_list, target;
355
356    if not ToDoList_Is_Sane_Entry( entry ) then
357
358        return;
359
360    fi;
361
362    source_list := SourcePart( entry );
363
364    if source_list = fail then
365
366        return;
367
368    fi;
369
370    entry!.source_tester_list := List( source_list, i -> false );
371
372    source_object_list := [ ];
373
374    for source in source_list do
375
376        if ForAll( source_object_list, i -> not IsIdenticalObj( i, source[ 1 ] ) ) then
377
378            Add( source_object_list, source[ 1 ] );
379
380        fi;
381
382    od;
383
384    if not TODO_LISTS.activated
385       or ForAny( source_object_list, CannotHaveAToDoList )
386       or ForAny( source_object_list, i -> not IsAttributeStoringRep( i ) ) then
387
388        return;
389
390    fi;
391
392    result := ProcessAToDoListEntry( entry );
393
394    for source in source_list do
395
396        todo_list := ToDoList( source[ 1 ] );
397
398        if IsFunction( result ) then
399
400            Add( todo_list!.already_done, entry );
401
402        elif result = false and not PreconditionsDefinitelyNotFulfilled( entry ) and ( TODO_LISTS.activated or CanHaveAToDoList( source[ 1 ] ) ) then
403
404            TODOLIST_ADD_TO_RECORD_AT_POSITION( todo_list!.todos, source[ 2 ], entry );
405
406            SetFilterObj( source[ 1 ], HasSomethingToDo );
407
408        elif result = false and PreconditionsDefinitelyNotFulfilled( entry ) then
409
410            Add( todo_list!.precondition_not_fulfilled, entry );
411
412        elif result = fail then
413
414            Add( todo_list!.garbage, entry );
415
416        fi;
417
418    od;
419
420    if IsFunction( result ) then
421
422        result();
423
424    fi;
425
426end );
427
428##########################################
429##
430## Entry with functions
431##
432##########################################
433
434##
435InstallMethod( SourcePart,
436               "for entries that launches functions",
437               [ IsToDoListEntryWhichLaunchesAFunctionRep ],
438
439  function( entry )
440
441    return RecoverWholeList( entry!.source_list );
442
443end );
444
445##
446InstallMethod( TargetPart,
447               "for entries that launches functions",
448               [ IsToDoListEntryWhichLaunchesAFunctionRep ],
449
450  function( entry )
451
452    return entry!.func;
453
454end );
455
456##
457InstallMethod( ToDoListEntry,
458               "constructor",
459               [ IsList, IsFunction ],
460
461  function( source_list, func )
462    local entry;
463
464    if not ForAll( source_list, i -> IsList( i[ 2 ] ) and ( Length( i ) = 3 or Length( i ) = 2 or Length( i ) = 4 ) ) then
465
466        Error( "wrong input format" );
467
468    fi;
469
470    entry := rec( source_list := ToDoListWeakPointer( source_list ), func := func );
471
472    ObjectifyWithAttributes( entry, TheTypeToDoListWhichLaunchesAFunction );
473
474    return entry;
475
476end );
477
478##
479InstallMethod( ToDoList_Is_Sane_Entry,
480               "function entries",
481               [ IsToDoListEntryWhichLaunchesAFunctionRep ],
482
483  function( entry )
484
485    return IsCompleteWeakPointerList( entry!.source_list );
486
487end );
488
489##
490InstallMethod( ProcessAToDoListEntry,
491               [ IsToDoListEntryWhichLaunchesAFunctionRep ],
492
493  function( entry )
494    local source_list, source, pull_attr, target, push_attr, tester_var, source_status;
495
496    source_list := SourcePart( entry );
497
498    if source_list = fail then
499
500        return fail;
501
502    fi;
503
504    target := TargetPart( entry );
505
506    if target = fail then
507
508        return fail;
509
510    fi;
511
512    for source in [ 1 .. Length( source_list ) ] do
513
514        if entry!.source_tester_list[ source ] = true then
515
516            continue;
517
518        fi;
519
520        source_status := ToolsForHomalg_CheckASourcePart( source_list[ source ] );
521
522        if source_status = fail then
523
524            SetFilterObj( entry, PreconditionsDefinitelyNotFulfilled );
525
526            return false;
527
528        elif not source_status then
529
530            return false;
531
532        else
533
534            entry!.source_tester_list[ source ] := true;
535
536        fi;
537
538    od;
539
540    SetFilterObj( entry, IsProcessedEntry );
541
542    return target;
543
544end );
545
546##########################################
547##
548## Entry with list of sources
549##
550##########################################
551
552##
553InstallMethod( ToDoListEntry,
554               "todo list entry with list of sources",
555               [ IsList, IsObject, IsString, IsObject ],
556
557  function( source_list, obj_to_push, attr_to_push, val_to_push )
558    local wpt_source_list, targetlist, entry;
559
560    if not ForAll( source_list, i -> IsList( i[ 2 ] ) and ( Length( i ) = 3 or Length( i ) = 2 or Length( i ) = 4 ) ) then
561
562        Error( "wrong input format" );
563
564    fi;
565
566    wpt_source_list := ToDoListWeakPointer( source_list );
567
568    targetlist := ToDoListWeakPointer( [ obj_to_push, attr_to_push, val_to_push ] );
569
570    entry := rec( source_list := wpt_source_list, targetlist := targetlist );
571
572    ObjectifyWithAttributes( entry, TheTypeToDoListEntryWithListOfSources );
573
574    return entry;
575
576end );
577
578##
579InstallMethod( ToDoList_Is_Sane_Entry,
580               "for list entries",
581               [ IsToDoListEntryWithListOfSourcesRep ],
582
583  function( entry )
584
585    return IsCompleteWeakPointerList( entry!.source_list ) and IsCompleteWeakPointerList( entry!.targetlist );
586
587end );
588
589##
590InstallMethod( SourcePart,
591               "for entries with lists of sources",
592               [ IsToDoListEntryWithListOfSourcesRep ],
593
594  function( entry )
595
596    return RecoverWholeList( entry!.source_list );
597
598end );
599
600##
601InstallMethod( TargetPart,
602               "for entries with lists of sources",
603               [ IsToDoListEntryWithListOfSourcesRep ],
604
605  function( entry )
606
607    return RecoverWholeList( entry!.targetlist );
608
609end );
610
611##
612InstallMethod( SetTargetValueObject,
613               "for los entries",
614               [ IsToDoListEntryWithListOfSourcesRep, IsObject ],
615
616  function( entry, value )
617
618    entry!.targetlist[ 3 ] := value;
619
620end );
621
622##
623InstallMethod( SetTargetObject,
624               "for los entries",
625               [ IsToDoListEntryWithListOfSourcesRep, IsObject ],
626
627  function( entry, value )
628
629    entry!.targetlist[ 1 ] := value;
630
631end );
632
633##
634InstallMethod( ProcessAToDoListEntry,
635               [ IsToDoListEntryWithDefinedTargetRep ],
636
637  function( entry )
638    local source_list, source, pull_attr, target, push_attr, tester_var, target_value, target_obj,
639          return_function, source_status;
640
641    source_list := SourcePart( entry );
642
643    if source_list = fail then
644
645        return fail;
646
647    fi;
648
649    target := TargetPart( entry );
650
651    if target = fail then
652
653        return fail;
654
655    fi;
656
657    tester_var := true;
658
659    for source in [ 1 .. Length( source_list ) ] do
660
661        if entry!.source_tester_list[ source ] = true then
662
663            continue;
664
665        fi;
666
667        source_status := ToolsForHomalg_CheckASourcePart( source_list[ source ] );
668
669        if source_status = fail then
670
671            SetFilterObj( entry, PreconditionsDefinitelyNotFulfilled );
672
673            return false;
674
675        elif not source_status then
676
677            return false;
678
679        else
680
681            entry!.source_tester_list[ source ] := true;
682
683        fi;
684
685    od;
686
687    if not tester_var then
688        return false;
689    fi;
690
691    ## Sanitize the source.
692
693    for source in source_list do
694
695        if Length( source ) = 2 and IsString( source[ 2 ] ) then
696
697            Add( source, ValueGlobal( source[ 2 ] )( source[ 1 ] ) );
698
699        elif Length( source ) = 4 and IsString( source[ 2 ] ) then
700
701            source[ 3 ] := ValueGlobal( source[ 2 ] )( source[ 1 ] );
702
703            Remove( source, 4 );
704
705        fi;
706
707    od;
708
709    return_function := function()
710        local push_attr, target_obj, target_value, str, out;
711
712        push_attr := ValueGlobal( target[ 2 ] );
713
714        target_obj := ToDoLists_Process_Entry_Part( target[ 1 ] );
715
716        target_value := ToDoLists_Process_Entry_Part( target[ 3 ] );
717
718        SetTargetObject( entry, target_obj );
719
720        SetTargetValueObject( entry, target_value );
721
722        if not Tester( push_attr )( target_obj ) then
723
724            SetFilterObj( entry, HasSetAttributeOfObject );
725
726            if TODO_LISTS.where_infos then
727
728                str := "";
729
730                out := OutputTextString( str, false );
731
732                PrintTo1( out, function()
733                                   Where( 100 );
734                               end );
735
736                CloseStream( out );
737
738                entry!.where_infos := str;
739
740            fi;
741
742        fi;
743
744        Setter( push_attr )( target_obj, target_value );
745
746        Add( ToDoList( target_obj )!.from_others, entry );
747
748    end;
749
750    ToolsForHomalg_ProcessToDoListEquivalencesAndContrapositions( entry );
751
752    SetFilterObj( entry, IsProcessedEntry );
753
754    return return_function;
755
756end );
757
758##########################################
759##
760## Entry with contraposition
761##
762##########################################
763
764##
765InstallMethod( ToDoListEntryWithContraposition,
766               "constructor",
767               [ IsObject, IsString, IsBool, IsObject, IsString, IsBool ],
768
769  function( source, sprop, sval, target, tprop, tval )
770    local entry;
771
772    entry := rec( );
773
774    ObjectifyWithAttributes( entry, TheTypeToDoListEntryWithContraposition );
775
776    entry!.input := ToDoListWeakPointer( [ source, sprop, sval, target, tprop, tval ] );
777
778    return entry;
779
780end );
781
782##
783InstallMethod( AddToToDoList,
784               "for ToDoListEntriesWithContraposition",
785               [ IsToDoListEntryWithContrapositionRep ],
786
787  function( entry )
788    local input, entry1, entry_contra, description, description_list_entry;
789
790    input := RecoverWholeList( entry!.input );
791
792    if input = fail then
793
794        return;
795
796    fi;
797
798    entry1 := ToDoListEntry ( [ input{[ 1 .. 3 ]} ], input[ 4 ], input[ 5 ], input[ 6 ] );
799
800    entry_contra := ToDoListEntry( [ [ input[ 4 ], input[ 5 ], not input[ 6 ] ] ], input[ 1 ], input[ 2 ], not input[ 3 ] );
801
802    entry1!.contrapositions := [ entry_contra ];
803
804    entry_contra!.contrapositions := [ entry1 ];
805#
806#     AddToToDoList( ToDoListEntry( [ [ entry, "DescriptionOfImplication" ] ], entry1, "DescriptionOfImplication", [ DescriptionOfImplication, entry ] ) );
807#
808#     AddToToDoList( ToDoListEntry( [ [ entry, "DescriptionOfImplication" ] ], entry_contra, "DescriptionOfImplication", [ DescriptionOfImplication, entry ] ) );
809#
810    AddToToDoList( entry1 );
811
812    AddToToDoList( entry_contra );
813
814end );
815
816##
817InstallMethod( ToDoList_Is_Sane_Entry,
818               "for entry with contraposition",
819               [ IsToDoListEntryWithContrapositionRep ],
820
821  function( entry )
822
823    return IsCompleteWeakPointerList( entry!.input );
824
825end );
826
827##########################################
828##
829## Equal
830##
831##########################################
832
833##
834InstallMethod( ToDoListEntryForEqualAttributes,
835               "todo-list-entry-for-equivalent-properties",
836               [ IsObject, IsString, IsObject, IsString ],
837
838  function( obj1, prop1, obj2, prop2 )
839    local entry;
840
841    entry := rec( input := ToDoListWeakPointer( [ obj1, prop1, obj2, prop2 ] ) );
842
843    ObjectifyWithAttributes( entry, TheTypeToDoListEntryForEqualProperties );
844
845    SetDescriptionOfImplication( entry, Concatenation( "propagate equal attributes ", prop1, " and ", prop2 ) );
846
847    return entry;
848
849end );
850
851##
852InstallMethod( ToDoList_Is_Sane_Entry,
853               "for entry with equal",
854               [ IsToDoListEntryForEqualPropertiesRep ],
855
856  function( entry )
857
858    return IsCompleteWeakPointerList( entry!.input );
859
860end );
861
862##
863InstallMethod( AddToToDoList,
864               "for entries for equivalent properties",
865               [ IsToDoListEntryForEqualPropertiesRep ],
866
867  function( entry )
868    local input, entry_forward, entry_backwards;
869
870    input := RecoverWholeList( entry!.input );
871
872    if input = fail then
873
874        return;
875
876    fi;
877
878    entry_forward := ToDoListEntry( [ [ input[ 1 ], input[ 2 ] ] ],
879                             [ [ Concatenation( "Forward implication from ", input[2], " to ", input[4] ), [ input[ 3 ], input[ 4 ], [ ValueGlobal( input[ 2 ] ), input[ 1 ] ] ] ] ] );
880
881    entry_backwards := ToDoListEntry( [ [ input[ 3 ], input[ 4 ] ] ],
882                               [ [ Concatenation( "Backward implication from ", input[4], " to ", input[2] ), [ input[ 1 ], input[ 2 ], [ ValueGlobal( input[ 4 ] ), input[ 3 ] ] ] ] ] );
883
884    entry_forward[1]!.equivalences := entry_backwards;
885
886    entry_backwards[1]!.equivalences := entry_forward;
887#
888#     AddToToDoList( ToDoListEntry( [ [ entry, "DescriptionOfImplication" ] ], entry_forward, "DescriptionOfImplication", [ DescriptionOfImplication, entry ] ) );
889#
890#     AddToToDoList( ToDoListEntry( [ [ entry, "DescriptionOfImplication" ] ], entry_backwards, "DescriptionOfImplication", [ DescriptionOfImplication, entry ] ) );
891
892    AddToToDoList( entry_forward );
893
894    AddToToDoList( entry_backwards );
895
896end );
897
898##########################################
899##
900## Equal
901##
902##########################################
903
904##
905InstallMethod( ToDoListEntryForEquivalentAttributes,
906               "todo-list-entry-for-equivalent-properties",
907               [ IsObject, IsString, IsObject, IsObject, IsString, IsObject ],
908
909  function( obj1, prop1, val1, obj2, prop2, val2 )
910    local entry;
911
912    entry := rec( input := ToDoListWeakPointer( [ obj1, prop1, val1, obj2, prop2, val2 ] ) );
913
914    ObjectifyWithAttributes( entry, TheTypeToDoListEntryForEquivalentProperties );
915
916    return entry;
917
918end );
919
920##
921InstallMethod( ToDoList_Is_Sane_Entry,
922               "for entry with equal",
923               [ IsToDoListEntryForEquivalentPropertiesRep ],
924
925  function( entry )
926
927    return IsCompleteWeakPointerList( entry!.input );
928
929end );
930
931##
932InstallMethod( AddToToDoList,
933               "for entries for equivalent properties",
934               [ IsToDoListEntryForEquivalentPropertiesRep ],
935
936  function( entry )
937    local input, entry_forward, entry_backwards;
938
939    input := RecoverWholeList( entry!.input );
940
941    if input = fail then
942
943        return;
944
945    fi;
946
947    entry_forward := ToDoListEntry( [ [ input[ 1 ], input[ 2 ], input[ 3 ] ] ], input[ 4 ], input[ 5 ], input[ 6 ] );
948
949    entry_backwards := ToDoListEntry( [ [ input[ 4 ], input[ 5 ], input[ 6 ] ] ], input[ 1 ], input[ 2 ], input[ 3 ] );
950
951    entry_forward!.equivalences := [ entry_backwards ];
952
953    entry_backwards!.equivalences := [ entry_forward ];
954#
955#     AddToToDoList( ToDoListEntry( [ [ entry, "DescriptionOfImplication" ] ], entry_forward, "DescriptionOfImplication", [ DescriptionOfImplication, entry ] ) );
956#
957#     AddToToDoList( ToDoListEntry( [ [ entry, "DescriptionOfImplication" ] ], entry_backwards, "DescriptionOfImplication", [ DescriptionOfImplication, entry ] ) );
958
959    AddToToDoList( entry_forward );
960
961    AddToToDoList( entry_backwards );
962
963end );
964
965############################################
966##
967## Display & View
968##
969############################################
970
971##
972##
973InstallMethod( ViewObj,
974               "for todo-list entry",
975               [ IsToDoListEntry ],
976
977  function( entry )
978
979    Print( "<A ToDo-list entry" );
980
981    if HasDescriptionOfImplication( entry ) then
982
983        Print( Concatenation( " with description: ", DescriptionOfImplication( entry ) ) );
984
985    fi;
986
987    Print( ">" );
988
989end );
990
991##
992InstallMethod( Display,
993               "for todo-list entry",
994               [ IsToDoListEntry ],
995
996  function( entry )
997
998    Print( "A ToDo-list entry" );
999
1000    if HasDescriptionOfImplication( entry ) then
1001
1002        Print( Concatenation( " with description: ", DescriptionOfImplication( entry ) ) );
1003
1004    fi;
1005
1006    Print( ".\n" );
1007
1008end );
1009