@@ -315,20 +315,15 @@ let extract_intspace (mcs : marked_constellation) =
315315 Execution
316316 --------------------------------------- *)
317317
318+ type configuration = constellation * constellation
319+
318320let unpolarized_star s = List. for_all ~f: (Fn. compose not is_polarised) s.content
319321
320322let kill : constellation -> constellation = List. filter ~f: unpolarized_star
321323
322324let clean : constellation -> constellation =
323325 List. filter ~f: (fun s -> List. is_empty s.content)
324326
325- let selections l =
326- let rec aux acc = function
327- | [] -> []
328- | h :: t -> (h, acc @ t) :: aux (acc @ [ h ]) t
329- in
330- aux [] l
331-
332327let fusion repl1 repl2 s1 s2 bans1 bans2 theta : star =
333328 let new1 = List. map s1 ~f: repl1 in
334329 let new2 = List. map s2 ~f: repl2 in
@@ -360,133 +355,165 @@ let pause () =
360355 let _ = input_line stdin in
361356 ()
362357
363- let search_partners ?(showtrace = false ) (r , other_rays , bans ) candidates :
358+ (* interaction between one selected ray and one selected action *)
359+ let rec interaction ~showtrace ~queue repl1 repl2
360+ (selected_action , other_actions ) (selected_ray , other_rays , bans ) :
364361 (star list , err_effect ) Result. t =
365- if showtrace then begin
366- output_string stdout
367- @@ Printf. sprintf " select state: >>%s<< %s" (string_of_ray r)
368- (string_of_raylist other_rays);
369- pause ()
370- end ;
371- let rec select_ray ~queue other_stars repl1 repl2 s :
372- (star list , err_effect ) Result. t =
373- match s.content with
374- | [] -> Ok []
375- | r' :: s' when not (is_polarised r') ->
376- select_ray ~queue: (r' :: queue) other_stars repl1 repl2
377- { content = s'; bans }
378- | r' :: s' -> (
379- if showtrace then begin
380- output_string stdout
381- @@ Printf. sprintf " try action: >>%s<< %s...\n " (string_of_ray r')
382- (string_of_raylist s')
362+ match selected_action.content with
363+ | [] -> Ok []
364+ | r' :: s' when not (is_polarised r') ->
365+ interaction ~showtrace ~queue: (r' :: queue) repl1 repl2
366+ ({ content = s'; bans }, other_actions)
367+ (selected_ray, other_rays, bans)
368+ | r' :: s' -> (
369+ if showtrace then begin
370+ output_string stdout
371+ @@ Printf. sprintf " try action: >>%s<< %s...\n " (string_of_ray r')
372+ (string_of_raylist s')
373+ end ;
374+ match raymatcher (repl1 selected_ray) (repl2 r') with
375+ | None ->
376+ if showtrace then output_string stdout " failed." ;
377+ interaction ~showtrace ~queue: (r' :: queue) repl1 repl2
378+ ({ content = s'; bans }, other_actions)
379+ (selected_ray, other_rays, bans)
380+ (* if there is an actual connection between rays *)
381+ | Some theta ->
382+ let * _ = apply_effect selected_ray theta in
383+ begin
384+ if showtrace then
385+ output_string stdout
386+ @@ Printf. sprintf " success with %s." (string_of_subst theta);
387+ if showtrace then pause ()
383388 end ;
389+ (* action is consumed when execution is linear *)
384390 let * next =
385- select_ray ~queue: (r' :: queue) other_stars repl1 repl2
386- { content = s'; bans }
391+ interaction ~showtrace ~queue: (r' :: queue) repl1 repl2
392+ ({ content = s'; bans }, other_actions)
393+ (selected_ray, other_rays, bans)
394+ in
395+ let other_rays' = queue @ s' in
396+ let after_fusion =
397+ fusion repl1 repl2 other_rays other_rays' bans selected_action.bans
398+ theta
399+ in
400+ let all_coherent =
401+ List. for_all ~f: (fun (b1 , b2 ) -> not @@ equal_ray b1 b2)
387402 in
388- match raymatcher (repl1 r) (repl2 r') with
389- | None ->
390- if showtrace then output_string stdout " failed." ;
391- Ok next
392- (* if there is an actual connection between rays *)
393- | Some theta ->
394- let * _ = apply_effect r theta in
395- let * _ =
403+ let * res =
404+ if all_coherent after_fusion.bans then begin
405+ let _ =
406+ if showtrace then
407+ output_string stdout
408+ @@ Printf. sprintf " add star %s." (string_of_star after_fusion)
409+ in
410+ Ok (after_fusion :: next)
411+ end
412+ else begin
396413 if showtrace then
397414 output_string stdout
398- @@ Printf. sprintf " success with %s." (string_of_subst theta);
399- Ok ()
400- in
401- let * _ =
402- if showtrace then pause () ;
403- Ok ()
404- in
405- let other_rays' = queue @ s' in
406- let after_fusion =
407- fusion repl1 repl2 other_rays other_rays' bans s.bans theta
408- in
409- let all_coherent =
410- List. for_all ~f: (fun (b1 , b2 ) -> not @@ equal_ray b1 b2)
411- in
412- let * res =
413- if all_coherent after_fusion.bans then begin
414- let _ =
415- if showtrace then
416- output_string stdout
417- @@ Printf. sprintf " add star %s." (string_of_star after_fusion)
418- in
419- Ok (after_fusion :: next)
420- end
421- else begin
422- let _ =
423- if showtrace then
424- output_string stdout
425- @@ Printf. sprintf " result filtered out by constraint."
426- in
427- Ok next
428- end
429- in
430- if showtrace then pause () ;
431- ident_counter := ! ident_counter + 2 ;
432- Ok res )
433- in
415+ @@ Printf. sprintf " result filtered out by constraint." ;
416+ Ok next
417+ end
418+ in
419+ if showtrace then pause () ;
420+ ident_counter := ! ident_counter + 2 ;
421+ Ok res )
422+
423+ (* search partner for a selected ray within a set of available actions *)
424+ let search_partners ~linear ~showtrace (selected_ray , other_rays , bans ) actions
425+ : (star list * star list, err_effect) Result.t =
426+ if showtrace then begin
427+ let str_ray = string_of_ray selected_ray in
428+ let str_rays = string_of_raylist other_rays in
429+ Printf. sprintf " select state: >>%s<< %s" str_ray str_rays
430+ |> output_string stdout;
431+ pause ()
432+ end ;
434433 let repl1 = replace_indices ! ident_counter in
435- List. map (selections candidates) ~f: (fun (s , cs ) ->
436- let repl2 = replace_indices (! ident_counter + 1 ) in
437- select_ray ~queue: [] cs repl1 repl2 s )
438- |> Result. all
439- |> function
440- | Ok l -> Ok (List. concat l)
441- | Error e -> Error e
442-
443- let interaction ?(showtrace = false ) (actions : star list ) (states : star list )
444- : (constellation option, err_effect) Result.t =
445- let rec select_ray states' ~queue s ~bans =
446- match s with
447- | [] -> Ok None
448- | r :: rs when not (is_polarised r) ->
449- select_ray states' ~queue: (r :: queue) rs ~bans
450- | r :: rs -> begin
451- match search_partners ~showtrace (r, queue @ rs, bans) actions with
452- | Ok [] -> select_ray states' ~queue: (r :: queue) rs ~bans
453- | Ok new_stars -> Ok (Some new_stars)
454- | Error e -> Error e
455- end
456- in
457- let rec select_star ~queue = function
458- | [] -> Ok None
459- | s :: states' -> begin
460- match select_ray states' ~queue: [] s.content ~bans: s.bans with
461- | Ok None -> select_star ~queue: (s :: queue) states'
462- | Ok (Some new_stars ) -> Ok (Some (List. rev queue @ states' @ new_stars))
463- | Error e -> Error e
464- end
434+ let rec try_actions acc = function
435+ | [] -> Ok ([] , acc)
436+ | selected_action :: other_actions ->
437+ let repl2 = replace_indices (! ident_counter + 1 ) in
438+ let * res =
439+ interaction ~showtrace ~queue: [] repl1 repl2
440+ (selected_action, other_actions)
441+ (selected_ray, other_rays, bans)
442+ in
443+ if (not @@ List. is_empty res) && linear then
444+ let * next, new_actions = try_actions acc other_actions in
445+ Ok (res @ next, new_actions)
446+ else
447+ let * next, new_actions =
448+ try_actions (selected_action :: acc) other_actions
449+ in
450+ Ok (res @ next, new_actions)
465451 in
466- select_star ~queue: [] states
467-
468- let string_of_configuration (actions , states ) : string =
452+ try_actions [] actions
453+
454+ let rec select_ray ~linear ~showtrace ~queue actions other_states
455+ (selected_state , bans ) : (star list option * star list, err_effect) Result.t =
456+ match selected_state with
457+ | [] -> Ok (None , actions)
458+ (* if unpolarized, no need to try, try other stars *)
459+ | r :: rs when not (is_polarised r) ->
460+ select_ray ~linear ~showtrace ~queue: (r :: queue) actions other_states
461+ (rs, bans)
462+ | selected_ray :: other_rays -> (
463+ (* look for partners for the selected rays in actions *)
464+ match
465+ search_partners ~linear ~showtrace
466+ (selected_ray, queue @ other_rays, bans)
467+ actions
468+ with
469+ (* interaction did nothing (no partner), try other rays *)
470+ | Ok ([] , new_actions ) ->
471+ select_ray ~linear ~showtrace ~queue: (selected_ray :: queue) new_actions
472+ other_states (other_rays, bans)
473+ (* interaction returns a result, keep it for the next round *)
474+ | Ok (new_stars , new_actions ) -> Ok (Some new_stars, new_actions)
475+ | Error e -> Error e )
476+
477+ let rec select_star ~linear ~showtrace ~queue actions :
478+ star list -> (star list option * star list , err_effect ) Result. t = function
479+ | [] -> Ok (None , actions)
480+ (* select a state star and try finding a partner for each ray *)
481+ | selected_state :: other_states -> (
482+ match
483+ select_ray ~linear ~showtrace ~queue: [] actions other_states
484+ (selected_state.content, selected_state.bans)
485+ with
486+ (* no success with this star, try other stars *)
487+ | Ok (None, new_actions ) ->
488+ select_star ~linear ~showtrace new_actions
489+ ~queue: (selected_state :: queue) other_states
490+ (* got new stars to add, construct the result for the next round *)
491+ | Ok (Some new_stars , new_actions ) ->
492+ Ok (Some (List. rev queue @ other_states @ new_stars), new_actions)
493+ | Error e -> Error e )
494+
495+ let string_of_cfg (actions , states ) : string =
469496 Printf. sprintf " >> actions: %s\n >> states: %s\n "
470497 (string_of_constellation actions)
471498 (string_of_constellation states)
472499
473- let exec ?(showtrace = false ) mcs : (constellation, err_effect) Result.t =
474- let rec aux (actions , states ) =
500+ let exec ?(showtrace = false ) ?(linear = false ) mcs :
501+ (constellation , err_effect ) Result. t =
502+ (* do a sequence of rounds with a single interaction on state per round *)
503+ let rec loop ((actions , states ) as cfg ) =
475504 if showtrace then begin
476- output_string stdout @@ string_of_configuration (actions, states) ;
505+ output_string stdout @@ string_of_cfg cfg ;
477506 pause ()
478507 end ;
479- begin
480- match interaction ~showtrace actions states with
481- | Ok None -> Ok states
482- | Ok (Some result' ) -> aux (actions, result')
483- | Error e -> Error e
484- end
508+ match select_star ~linear ~showtrace ~queue: [] actions states with
509+ | Ok (None, _ ) -> Ok states (* no more possible interaction *)
510+ | Ok (Some res , new_actions ) -> loop (new_actions, res)
511+ | Error e -> Error e
485512 in
486- let actions, states = extract_intspace mcs in
513+ let cfg = extract_intspace mcs in
487514 if showtrace then
488515 output_string stdout @@ Printf. sprintf " \n >> starting trace...\n " ;
489- let res = aux (actions, states) in
516+ let res = loop cfg in
490517 if showtrace then begin
491518 output_string stdout @@ Printf. sprintf " >> end trace.\n " ;
492519 pause ()
0 commit comments