package Sim::OPTcue;
# Copyright (C) 2025 by Gian Luca Brunetti, gianluca.brunetti@gmail.com. All rights reserved.
# OPclue is a program adding functionalities to the Sim::OPT program, by the same author.

use Exporter;
use parent 'Exporter';

use vars qw( $VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS );
use Math::Trig;
use Math::Round;
use List::Util qw[ min max reduce shuffle];
use List::MoreUtils qw(uniq);
use List::AllUtils qw(sum);
use Sim::OPT::Stats qw(:all);
use Storable qw(store retrieve lock_store lock_nstore lock_retrieve dclone);
use IO::Tee;
use File::Copy qw( move copy );
use Set::Intersection;
use List::Compare;
use Data::Dumper;
use POSIX;
use Data::Dump qw(dump);
use feature 'say';
use Switch::Back;

#use Sub::Signatures;
#no warnings qw(Sub::Signatures);
no strict;
no warnings;
use warnings::unused;
use Sim::OPT::Morph;
use Sim::OPT::Sim;
use Sim::OPT::Report;
use Sim::OPT::Descend;
use Sim::OPT::Takechance;
use Sim::OPT::Parcoord3d;
use Sim::OPT::Interlinear;

our @ISA = qw( Exporter );
#%EXPORT_TAGS = ( DEFAULT => [qw( &opt &prepare )]); # our %EXPORT_TAGS = ( 'all' => [ qw( ) ] );
#@EXPORT   = qw(); # our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );

our @EXPORT = qw(
relax checkstep genmodnew expand
);

$VERSION = '0.005';
$ABSTRACT = 'OPclue contains procedures that define the OPclue design optimization application. Copyright: Gian Luca Brunetti, gianluca.brunetti@gmail.com, 2025.';



if ( $tofile eq "" )
{
  $tofile = "./report.txt";
}

$tee = new IO::Tee( \*STDOUT, ">>$tofile" ); # GLOBAL ZZZ

sub relax
{ 
    my ( $countvar, $countstep ) = @_;
    if( $countvar =~ /-/ )
    {
        @countvars = split( "-", $countvar );
        @countsteps = split( "-", $countstep );
        $laxmode = "y";
    }
    else 
    {
        push( @countvars, $countvar );
        push( @countsteps, $countstep );
        $laxmode = "n";
    }
    return ( \@countvars, \@countstep );
}


sub checkstep
{
  my ( $laxmode, $countstep, $cntv ) = @_;

  if ( $laxmode = "y" )
  {
    $countstep = $countsteps[$cntv]; say $tee "IN MORPH FOREACH \$countstep: " . dump( $countstep); 
  }
  return( $countstep );
}





sub expand
{
  my ($ctx) = @_;
  my $tee       = $ctx->{tee}       || $Sim::OPT::tee;
  my $configfile= $ctx->{configfile};
  my $precious  = $ctx->{precious};

  my @instances = @{ $ctx->{instances} };
  my %dirfiles  = %{ $ctx->{dirfiles} };
  my %inst      = %{ $ctx->{inst} };
  my @precedents= @{ $ctx->{precedents} || [] };

  my %dowhat    = %{ $ctx->{dowhat} };
  my %vehicles  = %{ $ctx->{vehicles} };
  my %mids      = %{ $ctx->{mids} };
  my %varnums   = %{ $ctx->{varnums} };
  my %carrier   = %{ $ctx->{carrier} || {} };

  my @blockelts = @{ $ctx->{blockelts} };
  my $from      = $ctx->{from};

  my $mypath    = $ctx->{mypath};
  my $file      = $ctx->{file};
  my $countcase = $ctx->{countcase};
  my $countblock= $ctx->{countblock};
  my @packet;
  my @fulls;


  if ( $dirfiles{randompick} eq "y" )
  {
    my $randompicknum = $dirfiles{randompicknum}; #say $tee "\$randompicknum: $randompicknum"; say $tee "\$from: $from";
    my ( @sack, @collect, @dish, @newb );
    my @firstinstance = @instances[ 0..0 ];

    $instn = $dirfiles{countinst};
      
    my %carrier = Sim::OPT::reconstruct( $origin );
    #my $starttarget = giveback( \%mids ); ##say "STARTTARGET $starttarget";
    
    if ( ( $randompicknum == 0 ) or ( $randompicknum eq "" ) )
    { say $tee "\$randompicknum is 0, but it cannot. Stopping" and die; }
    
    while ( scalar( @sack ) < $randompicknum ) 
    { 
      my ( $newstring, $pairs_r ) = Sim::OPT::genstring( \%varnums, \@blockelts, $from ); say $tee "\$newstring: $newstring";
      
      if ( $newstring ~~ @{ $dirfiles{dones} } )
      {
        next;
      }
      else 
      {
        push( @{ $dirfiles{dones} }, $newstring ); 
        push( @sack, $newstring ); #say $tee "\@sack: " . dump (@sack);
      } 
      
      #say $tee "\@blockelts: " . dump (@blockelts);
      #say $tee "\$newstring: " . dump ($newstring);
      #say $tee "\%mids: " . dump (\%mids);
      #say $tee "\$countcase: " . dump ($countcase);
      #say $tee "%dowhat: " . dump (\%dowhat);
      #say $tee "NOW!!! \$instances[0]: " . dump ( $instances[0], );
      #say $tee "NOW!!! \%carrier: " . dump (\%carrier);
      #say $tee " \%inst: " . dump (\%inst);

      #( $instance_r, $counter ) = setpickinst( $newstring, \%mids, $countcase, \@firstinstance, \%dowhat, "no", $counter ); #NO IS $fire. For blocks, "no". For singletons, "yes".
      ( $instance_r ) = Sim::OPT::define_random_file( $newstring, \%mids, $countcase, \@firstinstance, \%dowhat, "no", $instn, $pairs_r ); #NO IS $fire. For blocks, "no". For singletons, "yes".
      
      $instn++;
      $dirfiles{countinst} = $instn;
      my @newinstance = @{ $instance_r }; say $tee "\@newinstance " . dump ( @newinstance );
      
      my %i = %{ $newinstance[0] };
      my %to = %{ $i{to} }; #say $tee " \%to " .dump ( \%to );
      my %orig = %{ $i{orig} }; #say $tee " \%orig " .dump ( \%orig );
      my $is = $i{is}; #say $tee " \$is " .dump ( $is );
      my $origin = $i{origin}; #say $tee " \$origin " .dump ( $origin );
      my $from = $i{from}; #say $tee " \$from " .dump ( $from );
      my $instn;


      $to{to} = "$mypath/$file" . "_" . "$is";  #say $tee "A out of setpickinst \$to{to} " .dump ( $to{to} );
      $to{cleanto} = "$is"; #say $tee "B out of setpickinst \$to{cleanto} " .dump ( $to{cleanto} );
      $orig{to} = "$mypath/$file" . "_" . "$origin"; #say $tee "C out of setpickinst \$orig{to} " .dump ( $orig{to} );
      $orig{cleanto} = "$origin"; #say $tee "D out of setpickinst \$orig{cleanto} " .dump ( $orig{cleanto} );

      if ( $dowhat{names} eq "short" )
      {
        my $crypto = Sim::OPT::encrypt1( $is ); #say $tee "out of setpickinst \$crypto " .dump ( \$crypto );
        my $cryptor = Sim::OPT::encrypt1( $origin ); #say $tee "out of setpickinst \$cryptor " .dump ( \$cryptor );
        $to{crypto} = "$mypath/$file" . "_" . "$crypto";  ###DDD!!! FINISH THIS.
        $to{cleancrypto} = $crypto;  ###DDD!!! FINISH THIS.
        $orig{crypto} = "$mypath/$file" . "_" . "$cryptor";  ###DDD!!! FINISH THIS.
        $orig{cleancrypto} = $cryptor; ###DDD!!! FINISH THIS.
      }
      elsif ( $dowhat{names} eq "medium" )
      {
        my $crypto = Sim::OPT::encrypt0( $is ); #say $tee "out of setpickinst \$crypto " .dump ( \$crypto );
        my $cryptor = Sim::OPT::encrypt0( $origin ); #say $tee "out of setpickinst \$cryptor " .dump ( \$cryptor );
        $to{crypto} = "$mypath/$file" . "_" . "$crypto";  ###DDD!!! FINISH THIS.
        $to{cleancrypto} = $crypto;  ###DDD!!! FINISH THIS.
        $orig{crypto} = "$mypath/$file" . "_" . "$cryptor";  ###DDD!!! FINISH THIS.
        $orig{cleancrypto} = $cryptor; ###DDD!!! FINISH THIS.
      }
      else
      {
        $to{crypto} = $to{to};  ### TAKE CARE!!! REASSIGNIMENT!!!
        $to{cleancrypto} = $to{cleanto}; ### TAKE CARE!!! REASSIGNIMENT!!!
        $orig{crypto} = $orig{to}; ### TAKE CARE!!! REASSIGNIMENT!!!
        $orig{cleancrypto} = $orig{cleanto}; ### TAKE CARE!!! REASSIGNIMENT!!!
      }

      $inst{$to{cleanto}} = $to{cleancrypto};
      $inst{$to{crypto}} = $to{to};
      $inst{$to{cleancrypto}} = $to{cleanto};
      $inst{$to{to}} = $to{crypto};
      $inst{$orig{cleanto}} = $orig{cleancrypto};
      $inst{$orig{crypto}} = $orig{to};
      $inst{$orig{cleancrypto}} = $orig{cleanto};
      $inst{$orig{to}} = $orig{crypto};
      %inst = Sim::OPT::cleaninst( %inst );

      #say $tee "FINALLY, \%inst" . dump( \%inst );

      say $tee "IN RANDOMPICK \@newinstance " . dump( @newinstance );

      push( @dish, @newinstance );
    }


    if ( $dowhat{morph} eq "y" )
    {
      #say $tee "16ARRIVED 3,LAUNCHING MORPHING WITH \$configfile $configfile, \@shortinstances, " . dump( @shortinstances ) . ", ...0000000000000000000000
      #\$fire $fire, \%dirfiles,  " . dump( %dirfiles ) . ", \%dowhat, "  . dump( %dowhat ) . ", \%vehicles, " . dump( %vehicles ) . " \%inst " . dump( %inst ), ;
      my ( $dirfiles_r ) = Sim::OPT::Morph::morph( $configfile, \@dish, \%dirfiles, \%dowhat, \%vehicles, \%inst );
      %dirfiles = %$dirfiles_r;
    }

    #my @lastinstance = ();
    #my $c = 0;
    #foreach my $inst ( @shortinstances )
    #{
    # if ( $c == $#shortinstances )
    # {
    #   push ( @lastinstance, $inst );
    # }
    # $c++;
    #}
    
    if ( ( $dowhat{simulate} eq "y" ) or ( $dowhat{newreport} eq "y" ) )
    {
      #say $tee "ARRIVED 4, WITH $precious";
      #say $tee "LAUNCHING SIM WITH  \@lastinstance, " . dump( @lastinstance ) . ", \$fire $fire, \%dirfiles,  " . dump( %dirfiles ) .
      #     ", \%vehicles, " . dump( %vehicles ) . ", \%dowhat, "  . dump( %dowhat ) . " \%inst " . dump( %inst ), ;
      ( my $packet_r, my $dirfiles_r, $csim ) = Sim::OPT::Sim::sim( { instances => \@dish, dowhat => \%dowhat, 
        dirfiles => \%dirfiles, vehicles => \%vehicles, precious => $precious, inst => \%inst, fire => "y", packet => \@packet } );
    } say $tee "RECEIVED PACKET " . dump( @packet );
    @packet = uniq( @$packet_r );
    %dirfiles = %$dirfiles_r;

    if ( $dowhat{descend} eq "y" )
    {
      say $tee "DESCEND_INPUT is=" . $lastinstance[0]{is} . " to=" . $lastinstance[0]{to}{to} . " cleanto=" . $lastinstance[0]{to}{cleanto};
      say $tee "#Descending to catch performance " . ($countcase + 1) . ", block " . ($countblock + 1) . ".";
      Sim::OPT::Descend::descend( { instances => \@dish, dowhat => \%dowhat, dirfiles => \%dirfiles, vehicles => \%vehicles, inst => \%inst, precedents => \@precedents, precious => "$precious" } );
      say $tee "#Moving on " . ($countcase + 1) . ", block " . ($countblock + 1) . ".";
    }

    my $cryptolinks = "$mypath/$file" . "_" . "$countcase" . "_cryptolinks.pl";
    open ( CRYPTOLINKS, ">$cryptolinks" ) or die;
    say CRYPTOLINKS "" . dump( \%inst );
    close CRYPTOLINKS;

    if ( $dowhat{metamodel} eq "y" )
    {
      my $tmpblankfile = "$mypath/$file" . "_tmp_gen_blank.csv"; say $tee "IN LATINHYPERCUBE \$tmpblankfile: " . dump( $tmpblankfile );
      my $bit = $file . "_";
      my @bag =( $bit );
      my @fills = @{ Sim::OPT::Descend::prepareblank( \%varnums, $tmpblankfile, \@blockelts, \@bag, $file, \%carrier ) };
      @fulls = uniq( map { $_->[0] } @fills );
    }
    return( \@fulls );
  }


  ##########################################################
  elsif ( $dirfiles{newrandompick} eq "y" )
  {
    my $randompicknum = $dirfiles{randompicknum}; #say $tee "\$randompicknum: $randompicknum"; say $tee "\$from: $from";
    my ( @sack, @collect, @dish, @newb );
    my @firstinstance = @instances[ 0..0 ];

    $instn = $dirfiles{countinst};
      
    my %carrier = reconstruct( $origin );
    #my $starttarget = giveback( \%mids ); ##say "STARTTARGET $starttarget";
    
    if ( ( $randompicknum == 0 ) or ( $randompicknum eq "" ) )
    { say $tee "\$randompicknum is 0, but it cannot. Stopping" and die; }
    
    while ( scalar( @sack ) < $randompicknum ) 
    { 
      my ( $newstring, $pairs_r ) = Sim::OPT::genstring( \%varnums, \@blockelts, $from ); say $tee "\$newstring: $newstring";
      
      if ( $newstring ~~ @{ $dirfiles{dones} } )
      {
        next;
      }
      else 
      {
        push( @{ $dirfiles{dones} }, $newstring ); 
        push( @sack, $newstring ); #say $tee "\@sack: " . dump (@sack);
      } 
      
      #say $tee "\@blockelts: " . dump (@blockelts);
      #say $tee "\$newstring: " . dump ($newstring);
      #say $tee "\%mids: " . dump (\%mids);
      #say $tee "\$countcase: " . dump ($countcase);
      #say $tee "%dowhat: " . dump (\%dowhat);
      #say $tee "NOW!!! \$instances[0]: " . dump ( $instances[0], );
      #say $tee "NOW!!! \%carrier: " . dump (\%carrier);
      #say $tee " \%inst: " . dump (\%inst);

      #( $instance_r, $counter ) = setpickinst( $newstring, \%mids, $countcase, \@firstinstance, \%dowhat, "no", $counter ); #NO IS $fire. For blocks, "no". For singletons, "yes".
      ( $instance_r ) = Sim::OPT::define_random_file( $newstring, \%mids, $countcase, \@firstinstance, \%dowhat, "no", $instn, $pairs_r ); #NO IS $fire. For blocks, "no". For singletons, "yes".
      
      $instn++;
      $dirfiles{countinst} = $instn;
      my @newinstance = @{ $instance_r }; say $tee "\@newinstance " . dump ( @newinstance );
      
      my %i = %{ $newinstance[0] };
      my %to = %{ $i{to} }; #say $tee " \%to " .dump ( \%to );
      my %orig = %{ $i{orig} }; #say $tee " \%orig " .dump ( \%orig );
      my $is = $i{is}; #say $tee " \$is " .dump ( $is );
      my $origin = $i{origin}; #say $tee " \$origin " .dump ( $origin );
      my $from = $i{from}; #say $tee " \$from " .dump ( $from );
      my $instn;


      $to{to} = "$mypath/$file" . "_" . "$is";  #say $tee "A out of setpickinst \$to{to} " .dump ( $to{to} );
      $to{cleanto} = "$is"; #say $tee "B out of setpickinst \$to{cleanto} " .dump ( $to{cleanto} );
      $orig{to} = "$mypath/$file" . "_" . "$origin"; #say $tee "C out of setpickinst \$orig{to} " .dump ( $orig{to} );
      $orig{cleanto} = "$origin"; #say $tee "D out of setpickinst \$orig{cleanto} " .dump ( $orig{cleanto} );

      if ( $dowhat{names} eq "short" )
      {
        my $crypto = Sim::OPT::encrypt1( $is ); #say $tee "out of setpickinst \$crypto " .dump ( \$crypto );
        my $cryptor = Sim::OPT::encrypt1( $origin ); #say $tee "out of setpickinst \$cryptor " .dump ( \$cryptor );
        $to{crypto} = "$mypath/$file" . "_" . "$crypto";  ###DDD!!! FINISH THIS.
        $to{cleancrypto} = $crypto;  ###DDD!!! FINISH THIS.
        $orig{crypto} = "$mypath/$file" . "_" . "$cryptor";  ###DDD!!! FINISH THIS.
        $orig{cleancrypto} = $cryptor; ###DDD!!! FINISH THIS.
      }
      elsif ( $dowhat{names} eq "medium" )
      {
        my $crypto = Sim::OPT::encrypt0( $is ); #say $tee "out of setpickinst \$crypto " .dump ( \$crypto );
        my $cryptor = Sim::OPT::encrypt0( $origin ); #say $tee "out of setpickinst \$cryptor " .dump ( \$cryptor );
        $to{crypto} = "$mypath/$file" . "_" . "$crypto";  ###DDD!!! FINISH THIS.
        $to{cleancrypto} = $crypto;  ###DDD!!! FINISH THIS.
        $orig{crypto} = "$mypath/$file" . "_" . "$cryptor";  ###DDD!!! FINISH THIS.
        $orig{cleancrypto} = $cryptor; ###DDD!!! FINISH THIS.
      }
      else
      {
        $to{crypto} = $to{to};  ### TAKE CARE!!! REASSIGNIMENT!!!
        $to{cleancrypto} = $to{cleanto}; ### TAKE CARE!!! REASSIGNIMENT!!!
        $orig{crypto} = $orig{to}; ### TAKE CARE!!! REASSIGNIMENT!!!
        $orig{cleancrypto} = $orig{cleanto}; ### TAKE CARE!!! REASSIGNIMENT!!!
      }

      $inst{$to{cleanto}} = $to{cleancrypto};
      $inst{$to{crypto}} = $to{to};
      $inst{$to{cleancrypto}} = $to{cleanto};
      $inst{$to{to}} = $to{crypto};
      $inst{$orig{cleanto}} = $orig{cleancrypto};
      $inst{$orig{crypto}} = $orig{to};
      $inst{$orig{cleancrypto}} = $orig{cleanto};
      $inst{$orig{to}} = $orig{crypto};
      %inst = Sim::OPT::cleaninst( %inst );

      #say $tee "FINALLY, \%inst" . dump( \%inst );

      say $tee "IN RANDOMPICK \@newinstance " . dump( @newinstance );

      push( @dish, @newinstance );
    }


    if ( $dowhat{morph} eq "y" )
    {
      #say $tee "16ARRIVED 3,LAUNCHING MORPHING WITH \$configfile $configfile, \@shortinstances, " . dump( @shortinstances ) . ", ...0000000000000000000000
      #\$fire $fire, \%dirfiles,  " . dump( %dirfiles ) . ", \%dowhat, "  . dump( %dowhat ) . ", \%vehicles, " . dump( %vehicles ) . " \%inst " . dump( %inst ), ;
      my ( $dirfiles_r ) = Sim::OPT::Morph::morph( $configfile, \@dish, \%dirfiles, \%dowhat, \%vehicles, \%inst );
      %dirfiles = %$dirfiles_r;
    }

    #my @lastinstance = ();
    #my $c = 0;
    #foreach my $inst ( @shortinstances )
    #{
    # if ( $c == $#shortinstances )
    # {
    #   push ( @lastinstance, $inst );
    # }
    # $c++;
    #}
    
    if ( ( $dowhat{simulate} eq "y" ) or ( $dowhat{newreport} eq "y" ) )
    {
      #say $tee "ARRIVED 4, WITH $precious";
      #say $tee "LAUNCHING SIM WITH  \@lastinstance, " . dump( @lastinstance ) . ", \$fire $fire, \%dirfiles,  " . dump( %dirfiles ) .
      #     ", \%vehicles, " . dump( %vehicles ) . ", \%dowhat, "  . dump( %dowhat ) . " \%inst " . dump( %inst ), ;
      ( my $packet_r, my $dirfiles_r, $csim ) = Sim::OPT::Sim::sim( { instances => \@dish, dowhat => \%dowhat, 
        dirfiles => \%dirfiles, vehicles => \%vehicles, precious => $precious, inst => \%inst, fire => "y", packet => \@packet } );
    } say $tee "RECEIVED PACKET " . dump( @packet );
    @packet = uniq( @$packet_r );
    %dirfiles = %$dirfiles_r;

    if ( $dowhat{descend} eq "y" )
    {
      say $tee "DESCEND_INPUT is=" . $lastinstance[0]{is} . " to=" . $lastinstance[0]{to}{to} . " cleanto=" . $lastinstance[0]{to}{cleanto};
      say $tee "#Descending to catch performance " . ($countcase + 1) . ", block " . ($countblock + 1) . ".";
      Sim::OPT::Descend::descend( { instances => \@dish, dowhat => \%dowhat, dirfiles => \%dirfiles, vehicles => \%vehicles, inst => \%inst, precedents => \@precedents, precious => "$precious" } );
      say $tee "#Moving on " . ($countcase + 1) . ", block " . ($countblock + 1) . ".";
    }

    my $cryptolinks = "$mypath/$file" . "_" . "$countcase" . "_cryptolinks.pl";
    open ( CRYPTOLINKS, ">$cryptolinks" ) or die;
    say CRYPTOLINKS "" . dump( \%inst );
    close CRYPTOLINKS;

    if ( $dowhat{metamodel} eq "y" )
    {
      my $tmpblankfile = "$mypath/$file" . "_tmp_gen_blank.csv"; say $tee "IN LATINHYPERCUBE \$tmpblankfile: " . dump( $tmpblankfile );
      my $bit = $file . "_";
      my @bag =( $bit );
      my @fills = @{ Sim::OPT::Descend::prepareblank( \%varnums, $tmpblankfile, \@blockelts, \@bag, $file, \%carrier ) };
      @fulls = uniq( map { $_->[0] } @fills );
    }
    return( \@fulls );
  }


#################################################################
  if ( $dirfiles{ga} eq "y" )
  {
    #say $tee "SHOW \@instances: " . dump ( @instances ); # use Storable;
    say $tee "#Calling GAs on morphing operations for case " . ($countcase +1) . ", block " . ($countblock + 1) . ".";

    my $basestore = "./basestore-$countcase-$countblock";
    my $dowhatstore = "./dowhat-$countcase-$countblock";
    my $dirfilesstore = "./dirfiles-$countcase-$countblock";

    my %carrier = Sim::OPT::reconstruct( $origin );
    my $starttarget = Sim::OPT::giveback( \%mids ); ##say "STARTTARGET $starttarget";
    
    my ( $startcrypt, $crypto, $cryptor );

    if ( $dowhat{names} eq "short" )
    {
      $startcrypt = Sim::OPT::encrypt1( $starttarget );
      $crypto = Sim::OPT::encrypt1( $starttarget );
      $cryptor = Sim::OPT::encrypt1( $starttarget );
    }
    elsif ( $dowhat{names} eq "medium" )
    {
      $startcrypt = Sim::OPT::encrypt0( $starttarget );
      $crypto = Sim::OPT::encrypt0( $starttarget );
      $cryptor = Sim::OPT::encrypt0( $starttarget );
    }

    #%obtained = map { $_{is} = $starttarget } %{ $instances[$#instances] };
    #%obtained = map { $_{origin} = $starttarget } %{ $instances[$#instances] };
    #%obtained = map { $_{from} = $starttarget } %{ $instances[$#instances] };
    #%obtained = map { $_{to}{cleanto} = $starttarget } %{ $instances[$#instances] };
    #%obtained = map { $_{orig} = $starttarget } %{ $instances[$#instances] };
    #%obtained = map { $_{orig}{cleanto} = $starttarget } %{ $instances[$#instances] };
    #%obtained = map { $_{to}{to} = $starttarget } %{ $instances[$#instances] };
    #%obtained = map { $_{orig}{to} = $starttarget } %{ $instances[$#instances] };


    my $count = 0;
    foreach $i ( @instances )
    {
      my %in = %{ $i };
      if ( $count == 0 )
      {
        $in{is} = $starttarget;
        $in{origin} = $starttarget;
        $in{from} = $starttarget;
        $to{cleanto} = $starttarget;
        $orig{cleanto} = $starttarget;
        $to{to} = "$mypath/$file" . "_" . "$starttarget";
        $orig{to} = "$mypath/$file" . "_" . "$starttarget";

        if ( $dowhat{names} eq "short" )
        {
          $to{crypto} = "$mypath/$file" . "_" . "$crypto";  ###DDD!!! FINISH THIS.
          $to{cleancrypto} = $crypto;  ###DDD!!! FINISH THIS.
          $orig{crypto} = "$mypath/$file" . "_" . "$cryptor";  ###DDD!!! FINISH THIS.
          $orig{cleancrypto} = $cryptor; ###DDD!!! FINISH THIS.
        }
        elsif ( $dowhat{names} eq "medium" )
        {
          $to{crypto} = "$mypath/$file" . "_" . "$crypto";  ###DDD!!! FINISH THIS.
          $to{cleancrypto} = $crypto;  ###DDD!!! FINISH THIS.
          $orig{crypto} = "$mypath/$file" . "_" . "$cryptor";  ###DDD!!! FINISH THIS.
          $orig{cleancrypto} = $cryptor; ###DDD!!! FINISH THIS.
        }
        else
        {
          $to{crypto} = "$mypath/$file" . "_" . "$starttarget";  ### TAKE CARE!!! REASSIGNIMENT!!!
          $to{cleancrypto} = $starttarget; ### TAKE CARE!!! REASSIGNIMENT!!!
          $orig{crypto} = "$mypath/$file" . "_" . "$starttarget"; ### TAKE CARE!!! REASSIGNIMENT!!!
          $orig{cleancrypto} = $starttarget; ### TAKE CARE!!! REASSIGNIMENT!!!
        }

        $inst{$to{cleanto}} = $to{cleancrypto};
        $inst{$to{crypto}} = $to{to};
        $inst{$to{cleancrypto}} = $to{cleanto};
        $inst{$to{to}} = $to{crypto};
        $inst{$orig{cleanto}} = $orig{cleancrypto};
        $inst{$orig{crypto}} = $orig{to};
        $inst{$orig{cleancrypto}} = $orig{cleanto};
        $inst{$orig{to}} = $orig{crypto};
        %inst = Sim::OPT::cleaninst( %inst );
      }
      $count++;
    }

    my @juggle;
    my @prov = @instances; #say $tee "BEFORE, INSTANCES: " . dump ( @instances );
    my $pop = pop( @prov );
    my %instance = %{ $pop };

    say $tee `rm -f $basestore`;
    say $tee `rm -f $dowhatstore`;
    say $tee `rm -f $dirfilesstore`;
    say $tee `rm -f $basestore-return`;
    say $tee `rm -f ./$relate.txt`;
    say $tee `rm -f ./$report.txt`;


    store \%instance, "$basestore";
    store \%dowhat, "$dowhatstore"; # ATTENTION. use Storable;
    store \%dirfiles, "$dirfilesstore"; # ATTENTION. use Storable;


    #say $tee "python $dowhat{ga} $configfile $starttarget $countcase $basestore $dowhatstore $dirfilesstore $dirfiles{ganum}";
    my @returns = `python $dowhat{ga} $configfile $starttarget $countcase $basestore $dowhatstore $dirfilesstore $dirfiles{ganum}`; #HERE FLOWS THE ACTION
    #say  "RETURNED!: " . dump ( @returns );


    my @selecteds;


    #say  "\%mids!: " . dump ( \%mids ); say  "\$countcase!: " . dump ( $countcase );
    #say  "\@juggle!: " . dump ( @juggle ); say  "\%dowhat!: " . dump ( \%dowhat );
    foreach my $name ( @returns )
    {
      chomp $name; #say  "\$name!: " . dump ( $name );
      my $inss_r = Sim::OPT::setpickinst( $name, \%mids, $countcase, \@juggle, \%dowhat );
      my @inss = @{ $inss_r }; chomp $name; #say  "\@inss!: " . dump ( @inss );
      my $pickedins = $inss[$#inss];
      push ( @selecteds, $pickedins );
    }
    #say  "SELECTEDS!: " . dump ( @selecteds );

    my @instances = @selecteds;

    foreach my $inst_r ( @instances )
    {
      my %i = %{ $inst_r };
      my %inst = %{ $i{inst} };
      my %to = %{ $i{to} }; #say RELATE "out of setpickinst \%to " .dump ( %to );
      my %orig = %{ $i{orig} }; #say RELATE "out of \%orig \$crypto " .dump ( %orig );
      my $is = $i{is}; #say RELATE "out of setpickinst \$is " .dump ( $is );
      my $origin = $i{origin}; #say RELATE "out of setpickinst \$origin " .dump ( $origin );

      #my $crypto = int( ( scalar( keys %inst ) ) / 5 * 6 );
      #my $cryptor = $crypto + 1;
      my ( $crypto, $cryptor );
      if ( $dowhat{names} eq "short" )
      {
        $crypto = Sim::OPT::encrypt1( $is ); #say RELATE "out of setpickinst \$crypto " .dump ( $crypto );
        $cryptor = Sim::OPT::encrypt1( $origin ); #say RELATE "out of setpickinst \$cryptor " .dump ( $cryptor );
      }
      elsif ( $dowhat{names} eq "medium" )
      {
        $crypto = Sim::OPT::encrypt0( $is ); #say RELATE "out of setpickinst \$crypto " .dump ( $crypto );
        $cryptor = Sim::OPT::encrypt0( $origin ); #say RELATE "out of setpickinst \$cryptor " .dump ( $cryptor );
      }

      $to{to} = "$mypath/$file" . "_" . "$is";  ### TAKE CARE!!! REASSIGNIMENT!!!
      $to{cleanto} = "$is"; ### TAKE CARE!!! REASSIGNIMENT!!!
      $orig{to} = "$mypath/$file" . "_" . "$origin"; ### TAKE CARE!!! REASSIGNIMENT!!!
      $orig{cleanto} = "$origin"; ### TAKE CARE!!! REASSIGNIMENT!!!

      if ( ( $dowhat{names} eq "short" ) or ( $dowhat{names} eq "medium" ) )
      {
        $to{crypto} = "$mypath/$file" . "_" . "$crypto";  ###DDD!!! FINISH THIS.
        $to{cleancrypto} = $crypto;  ###DDD!!! FINISH THIS.
        $orig{crypto} = "$mypath/$file" . "_" . "$cryptor";  ###DDD!!! FINISH THIS.
        $orig{cleancrypto} = $cryptor; ###DDD!!! FINISH THIS.
      }
      else
      {
        $to{crypto} = $to{to};  ### TAKE CARE!!! REASSIGNIMENT!!!
        $to{cleancrypto} = $to{cleanto}; ### TAKE CARE!!! REASSIGNIMENT!!!
        $orig{crypto} = $orig{to}; ### TAKE CARE!!! REASSIGNIMENT!!!
        $orig{cleancrypto} = $orig{cleanto}; ### TAKE CARE!!! REASSIGNIMENT!!!
      }

      $inst{$to{cleanto}} = $to{cleancrypto};
      $inst{$to{crypto}} = $to{to};
      $inst{$to{cleancrypto}} = $to{cleanto};
      $inst{$to{to}} = $to{crypto};
      $inst{$orig{cleanto}} = $orig{cleancrypto};
      $inst{$orig{crypto}} = $orig{to};
      $inst{$orig{cleancrypto}} = $orig{cleanto};
      $inst{$orig{to}} = $orig{crypto};
      %inst = Sim::OPT::cleaninst( %inst );
    }

    my $cryptolinks = "$mypath/$file" . "_" . "$countcase" . "_cryptolinks.pl";
    open ( CRYPTOLINKS, ">$cryptolinks" ) or die;
    say CRYPTOLINKS "" . dump( \%inst );
    close CRYPTOLINKS;

    if ( ( $dowhat{simulate} eq "y" ) or ( $dowhat{newreport} eq "y" ) )
    {
      say $tee "#Calling simulations, reporting and retrieving for instance $instance{is} in case " . ($countcase +1) . ", block " . ($countblock + 1) . ".";
       ( my $packet_r, my $dirfiles_r, $csim ) = Sim::OPT::Sim::sim(
          { instances => \@instances, dirfiles => \%dirfiles, dowhat => \%dowhat, vehicles => \%vehicles,
            inst => \%inst, precedents => \@precedents, postproc => "y", packet => \@packet } ); # CHECK IF: fire => "y is needed" 
          @packet = uniq( @$packet_r ); say $tee "RECEIVED PACKET " . dump( @packet );
          %dirfiles, %$dirfiles_r;
    }

    if ( $dowhat{metamodel} eq "y" )
    {
      $tmpblankfile = "$mypath/$file" . "_tmp_gen_blank.csv"; #say $tee "IN LATINHYPERCUBE \$tmpblankfile: " . dump( $tmpblankfile );
      $bit = $file . "_";
      @bag =( $bit );
      @fills = @{ Sim::OPT::Descend::prepareblank( \%varnums, $tmpblankfile, \@blockelts, \@bag, $file, \%carrier ) };
      @fulls = uniq( map { $_->[0] } @fills );
    }
    return ( \@fulls )
  }


#################################################################
  elsif ( $dirfiles{OLDrandompick} eq "y" ) #DDD
  {
    say $tee "#Calling randomly picked morphing operations for case " . ($countcase +1) . ", block " . ($countblock + 1) . ".";

    my @pool = @instances ;
    say $tee "\pool: " . dump( @pool );
    @reds = shuffle( @pool );
    say $tee "REDS1: " . dump( @reds );
    @reds = @reds[0..($dirfiles{randompicknum}-1)];
    say $tee "REDS2: " . dump( @reds );

    @instances = @reds;


    if ( $dowhat{morph} eq "y" )
    {
      say $tee "#Calling morphing operations for instance $instance{is} in case " . ($countcase +1) . ", block " . ($countblock + 1) . ".";
      my ( $dirfiles_r ) = Sim::OPT::Morph::morph( $configfile, \@instances, \%dirfiles, \%dowhat, \%vehicles, \%inst, \@precedents );
      %dirfiles = %$dirfiles_r;
    }

    if ( ( $dowhat{simulate} eq "y" ) or ( $dowhat{newreport} eq "y" ) )
    {

      say $tee "#Calling simulations, reporting and retrieving for instance $instance{is} in case " . ($countcase +1) . ", block " . ($countblock + 1) . ".";
       ( my $packet_r, my $dirfiles_r, $csim ) = Sim::OPT::Sim::sim(
          { instances => \@instances, dirfiles => \%dirfiles, dowhat => \%dowhat, vehicles => \%vehicles,
            inst => \%inst, precedents => \@precedents, , packet => \@packet } );
           @packet = uniq( @$packet_r ); say $tee "RECEIVED PACKET " . dump( @packet );
          %dirfiles = %$dirfiles_r;
    }
    if ( $dowhat{metamodel} eq "y" )
    {
      $tmpblankfile = "$mypath/$file" . "_tmp_gen_blank.csv"; #say $tee "IN LATINHYPERCUBE \$tmpblankfile: " . dump( $tmpblankfile );
      $bit = $file . "_";
      @bag =( $bit );
      @fills = @{ Sim::OPT::Descend::prepareblank( \%varnums, $tmpblankfile, \@blockelts, \@bag, $file, \%carrier ) };
      @fulls = uniq( map { $_->[0] } @fills );
    }
    return ( \@fulls );
  }
} # END SUB EXPAND



sub genmodnew
{
  my ( $to, $stepsvar, $countop, $countstep, $applytype_ref, $genmodnew_ref, $countvar, $fileconfig , $mypath, $file, $countmorphing, $launchline, $menus_ref, $countinstance, $tee ) = @_;
  say $tee "I AM IN NENMODNEW!!!!!!!!!!!!!!";

  my @applytype = @$applytype_ref;
  my @genmodnew = @ {$genmodnew_ref };
  my $cntinst = ( $countinstance + 1 );
  say $tee "Applying constraints for case " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $cntinst.";

  my @sourcefiles = @{ $genmodnew[$countop][0] }; say $tee "OUTER \@sourcefiles: " . dump ( @sourcefiles );
  my @numberfiles = @{ $genmodnew[$countop][1] }; say $tee "OUTER \@numberfiles: " . dump ( @numberfiles );
  my @configfiles = @{ $genmodnew[$countop][2] }; say $tee "OUTER \@configfiles: " . dump ( @configfiles );
  my @incrs = @{ $genmodnew[$countop][3] };  say $tee "OUTER \@incrs: " . dump ( @incrs );
  my @subtypes = @{ $genmodnew[$countop][4] }; say $tee "OUTER \@subtypes: " . dump ( @subtypes );
  my @vertpairs = @{ $genmodnew[$countop][5] }; say $tee "OUTER \@vertpairs: " . dump ( @vertpairs );
  my @vertstomoves = @{ $genmodnew[$countop][6] }; say $tee "OUTER \@vertstomoves: " . dump ( @vertstomoves );
  
  my ( %ver, %obs, %oldver, %oldobs, %eds );
    
  my $countfile = 0;
    foreach my $sourcefile ( @sourcefiles )
  {

    my $sourceaddress = "$to$sourcefile";  say $tee "INSIDE FIRST \$sourceaddress: " . dump( $sourceaddress );

    open( SOURCEFILE, $sourceaddress ) or die "Can't open $sourceaddress: $!\n";
    my @lines = <SOURCEFILE>;
    close SOURCEFILE;
    my $num = $numberfiles[$countfile]; say $tee "INSIDE FIRST \$num: " . dump( $num );
        
    my $vertnum = 0;
        my $obsnum = 0;
    foreach my $line ( @lines )
    {
      $line =~ s/^\s+//;
      my @rowelts = split(/\s+|,/, $line);
      {

        if   ($rowelts[0] eq "*vertex" )
        { 
          $vertnum++;
          #say "foundvert $vertnum";
          @{ $ver{$num}{$vertnum} } = ( $rowelts[1], $rowelts[2], $rowelts[3] );
        }
            if   ($rowelts[0] eq "*obs" )
        { 
          $obsnum++;
          #say "foundobs $obsnum";
          @{ $obs{$num}{$obsnum} } = ( $rowelts[0], $rowelts[1], $rowelts[2], $rowelts[3],
                $rowelts[4], $rowelts[5], $rowelts[6], $rowelts[7], $rowelts[8], $rowelts[9], $rowelts[10], $rowelts[13] ) ;
        }
      }
        }

        %oldver = %{ dclone(\%ver) };
        %oldobs = %{ dclone(\%obs) };


        my $cn = 0;
        foreach my $line ( @lines )
        {
            chomp $line;
            if ( $line =~ /#&&/ )
            {
                $line =~ s/^\s+//;
                $line =~ s/\s+/ /;
                my @transitional = split(/#&&/, $line);
                my $leftpart = $transitional[0]; #say $tee "AAAPPLY_CONSTRAINTS \$leftpart: " . dump( $leftpart );
                my @elts = split(/\s+|,/, $leftpart); #say $tee "AAAPPLY_CONSTRAINTS \@elts: " . dump( @elts );

                my $rightpart = $transitional[1]; #say $tee "AAAPPLY_CONSTRAINTS \$rightpartA: " . dump( $rightpart );
                $rightpart =~ s/^\s+//; #say $tee "AAAPPLY_CONSTRAINTS \$rightpartB: " . dump( $rightpart );
                $rightpart =~ s/\s+$//; #say $tee "AAAPPLY_CONSTRAINTS \$rightpartC: " . dump( $rightpart );
                $rightpart =~ s/\s+/ /; #say $tee "AAAPPLY_CONSTRAINTS \$rightpartD: " . dump( $rightpart );
                my @ins = split(/\s+|,/, $rightpart); #say $tee "AAAPPLY_CONSTRAINTS \@ins: " . dump( @ins );

                foreach my $in ( @ins )
                {
                    unless ( ( $in eq undef ) or ( $leftpart eq undef ) or ( $rightpart eq undef ) )
                    {
                        my @elements = split(/-/, $in); #say $tee "AAAPPLY_CONSTRAINTS \@elements: " . dump( @elements );
                        my $name = $elements[0];
                        my $position = $elements[1];
                        $eds{$name}{file} = $sourcefile; #say $tee "AAAPPLY_CONSTRAINTS \$eds{\$name}{file}: " . dump( $eds{$name}{file} );
                        $eds{$name}{line} = $cn; #say $tee "AAAPPLY_CONSTRAINTS \$eds{\$name}{line}: " . dump( $eds{$name}{line} );
                        $eds{$name}{position} = $position; #say $tee "AAAPPLY_CONSTRAINTS \$eds{\$name}{position}: " . dump( $eds{$name}{position} );
                        $eds{$name}{value} = $elts[$position];  #say $tee "AAAPPLY_CONSTRAINTS \$eds{\$name}{value}: " . dump( $eds{$name}{value} );
                        my $length = length($in); #say $tee "AAAPPLY_CONSTRAINTS \$length: " . dump( $length );
                        $eds{$name}{length} = $length; #say $tee "AAAPPLY_CONSTRAINTS \$eds{\$name}{length}: " . dump( $eds{$name}{length} );
                        my $beginning = index($line, $in);
                        $eds{$name}{beginning} = $beginning; #say $tee "AAAPPLY_CONSTRAINTS \$eds{\$name}{beginning}: " . dump( $eds{$name}{beginning} );
                        my $end = $beginning + $length;
                        $eds{$name}{end} = $end; #say $tee "AAAPPLY_CONSTRAINTS \$eds{\$name}{end}: " . dump( $eds{$name}{end} );
                        $eds{$name}{rightpart} = $rightpart; #say $tee "AAAPPLY_CONSTRAINTS \$eds{\$name}{rightpart}: " . dump( $eds{$name}{rightpart} );
                    }
                }
            }
            $cn++;
        }
       
        my $countype = 0;
        foreach my $subtype ( @subtypes )
        {
          my $incr = $incrs[$countype]; say $tee "INSIDE FIRST IN FIRST \$incr: " . dump( $incr );
          my @vertpair = @{ $vertpairs[$countype] }; say $tee "INSIDE FIRST IN FIRST \@vertpair: " . dump( @vertpair );
          my ( $firstvert, $secondvert ) = @vertpair; say $tee "INSIDE FIRST IN FIRST \$firstvert, \$secondvert: " . dump( $firstvert, $secondvert );
          my @vertstomove = @{ $vertstomoves[$countype] }; say $tee "INSIDE FIRST IN FIRST \@vertstomove: " . dump( @vertstomove );

          if ( "all" ~~ @vertstomove )
          {
            @vertstomove = ( 1 .. $vertnum );
          } say $tee "AFTER all PROCESSING \@vertstomove: " . dump( @vertstomove );

          my ( $swing, $base, $pace, $val, $myval );
        my $count = 0;
          
        if ( ref ( $incr ) )
        {
          my $min = $incr->[0];
          my $max = $incr->[1];
          $swing->[$countype] = ( $max - $min );
          $base->[$countype] = ( 0 - $min );
        }
        else
        {
          $swing->[$countype] = ( 2 * $incr ); 
          $base->[$countype] = ( 0 - $incr );
        }

        $pace->[$countype] = ( $swing->[$countype] / ( $stepsvar - 1 ) );
        $val->[$countype] = ( $base->[$countype] + ( $pace->[$countype] * ( $countstep - 1 ) ) ); # THIS IS WHAT YOU WANT TO USE IN THE INSTRUCTIONS FOR PROPAGATING CONSTRAINTS
            $myval = $val->[$countype]; say $tee "INSIDE FIRST IN FIRST \$myval: " . dump( $myval );
          
          
          if ( ( $subtype eq "pairedmove" ) or ( $subtype eq "pairedobsmove" ) or ( $subtype eq "rotation" ) or ( $subtype eq "obsrotation" ) )
          {   #say $tee "\%ver: " . dump ( \%ver );
              #say $tee "\%obs: " . dump ( \%obs );
              my ( $vert1, $vert2 );
              unless ( ref( $firstvert ) )
              {
                $vert1 = $ver{$num}{$firstvert}; say $tee "INSIDE SECOND \$num: $num, \$firstvert: " . dump ($firstvert) ;
              }
              else
              {
                  $vert1 = $firstvert; say $tee "INSIDE SECOND ISREF \$num: $num, \$firstvert: " . dump ($firstvert) ;
              }

              unless ( ref( $secondvert ) )
              {
                $vert2 = $ver{$num}{$secondvert}; say $tee "INSIDE SECOND \$num: $num, \$secondvert: " . dump($secondvert);
              }
              else
              {
                   $vert2 = $secondvert; say $tee "INSIDE SECOND ISREF \$num: $num, \$secondvert: " . dump($secondvert);
              }
        

            my $xdiff = - ( $vert1->[0] - $vert2->[0] ); say $tee "INSIDE SECOND \$xdiff: " . dump( $xdiff );
            my $ydiff = - ( $vert1->[1] - $vert2->[1] ); say $tee "INSIDE SECOND \$ydiff: " . dump( $ydiff );
            my $zdiff = - ( $vert1->[2] - $vert2->[2] ); say $tee "INSIDE SECOND \$zdiff: " . dump( $zdiff );

            my $dist = sqrt ( ( $xdiff ** 2 ) + ( $ydiff ** 2 ) + ( $zdiff ** 2 ) ); say $tee "INSIDE SECOND \$dist: " . dump( $dist );

            my ($demult, $xdemult, $ydemult, $zdemult, $xadd, $yadd, $zadd );

            if ( $dist != 0 )
            {
               $demult = ( 1 / $dist ); say $tee "INSIDE SECOND \$demult: " . dump( $demult );
               $xdemult = ( $xdiff * $demult ); say $tee "INSIDE SECOND \$xdemult: " . dump( $xdemult );
               $ydemult = ( $ydiff * $demult ); say $tee "INSIDE SECOND \$ydemult: " . dump( $ydemult );
               $zdemult = ( $zdiff * $demult ); say $tee "INSIDE SECOND \$zdemult: " . dump( $zdemult );
            }
            else 
            {
               $xdemult = 0; say $tee "INSIDE SECOND \$xdemult: " . dump( $xdemult );
               $ydemult = 0; say $tee "INSIDE SECOND \$ydemult: " . dump( $ydemult );
               $zdemult = 0; say $tee "INSIDE SECOND \$zdemult: " . dump( $zdemult );
            }

            $xadd = ( $xdemult * $myval ); say $tee "INSIDE SECOND \$xadd: " . dump( $xadd );
            $yadd = ( $ydemult * $myval ); say $tee "INSIDE SECOND \$yadd: " . dump( $yadd );
            $zadd = ( $zdemult * $myval ); say $tee "INSIDE SECOND \$zadd: " . dump( $zadd );
        
        
                if ( $subtype eq "pairedmove" ) 
                {
                  foreach my $v ( @vertstomove )
                  {
                    $ver{$num}{$v}->[0] = ( $ver{$num}{$v}->[0] + $xadd );
                    $ver{$num}{$v}->[1] = ( $ver{$num}{$v}->[1] + $yadd );
                    $ver{$num}{$v}->[2] = ( $ver{$num}{$v}->[2] + $zadd );
                  }
                }
        

                if ( $subtype eq "pairedobsmove" ) 
                {
                  foreach my $v ( @vertstomove )
                  {
                    $obs{$num}{$v}->[1] = ( $obs{$num}{$v}->[1] + $xadd );
                    $obs{$num}{$v}->[2] = ( $obs{$num}{$v}->[2] + $yadd );
                    $obs{$num}{$v}->[3] = ( $obs{$num}{$v}->[3] + $zadd );
                  }
                }


                if ( ( $subtype eq "rotation" ) or ( $subtype eq "obsrotation" ) )
                {
                  if ( $vert2->[0] eq "" )
                  {
                    $vert2->[0] = $vert1->[0];
                    $vert2->[1] = $vert1->[1];
                    $vert2->[2] = ( $vert1->[2] + 1 );
                  }
                } say $tee "\$vert1: " . dump( $vert1 ); say $tee "\$vert2: " . dump( $vert2 );

                if ( $subtype eq "rotation" ) 
                {
                  foreach my $v ( @vertstomove )
                  {
                    ( $ver{$num}{$v}->[0], $ver{$num}{$v}->[1], $ver{$num}{$v}->[2] ) = 
                    Sim::OPT::Morph::rotateabout( $ver{$num}{$v}->[0], $ver{$num}{$v}->[1], $ver{$num}{$v}->[2],       # point to rotate (P)
                      $vert1->[0], $vert1->[1], $vert1->[2],     # point D on axis
                      $vert2->[0], $vert2->[1], $vert2->[2],     # point E on axis
                      $myval 
                    );
                  }
                }

                if ( $subtype eq "obsrotation" ) 
                {
                  foreach my $v ( @vertstomove )
                  {
                    ( $obs{$num}{$v}->[1], $obs{$num}{$v}->[2], $obs{$num}{$v}->[3] ) = 
                      Sim::OPT::Morph::rotateabout( $obs{$num}{$v}->[1], $obs{$num}{$v}->[2], $obs{$num}{$v}->[3],       # point to rotate (P)
                          $vert1->[0], $vert1->[1], $vert1->[2],     # point D on axis
                          $vert2->[0], $vert2->[1], $vert2->[2],     # point E on axis
                          $myval 
                        );
                    $obs{$num}{$v}->[7] = ( $obs{$num}{$v}->[7] + $myval );
                    if ( $obs{$num}{$v}->[7] > 360 )
                    {
                      $obs{$num}{$v}->[7] = ( $obs{$num}{$v}->[7] - 360 );
                    }
                    elsif ( $obs{$num}{$v}->[7] < 0 )
                    {
                      $obs{$num}{$v}->[7] = ( $obs{$num}{$v}->[7] + 360 );
                    }
                  }
                }
          }
        $countype++;
      }
      $countfile++;
    }


    my ( $swing, $base, $pace, $val );
    my $count = 0;
    foreach $incr ( @incrs )
    {
      if ( ref ( $incr ) )
      {
        my $min = $incr->[0];
        my $max = $incr->[1];
        $swing->[$count] = ( $max - $min );
        $base->[$count] = ( 0 - $min );
      }
      else
      {
        $swing->[$count] = ( 2 * $incr );
        $base->[$count] = ( 0 - $incr );
      }

      $pace->[$count] = ( $swing->[$count] / ( $stepsvar - 1 ) );
      $val->[$count] = ( $base->[$count] + ( $pace->[$count] * ( $countstep - 1 ) ) ); # THIS IS WHAT YOU WANT TO USE IN THE INSTRUCTIONS FOR PROPAGATING CONSTRAINTS
      $count++;
    }


    #say $tee "BEFORE EVAL, \%ver: " . dump(\%ver) . "\%obs: " . dump(\%obs) . " \%oldver" . dump(\%oldver) . " \%oldobs" . dump(\%oldobs);
    foreach my $configfile ( @configfiles )
    {
      my $configaddress = "$to$configfile";
      if ( defined ( $configaddress ) )
      {
        if ( -e $configaddress )
        {
          #do $configaddress;
          eval `cat $configaddress`; # HERE AN EXTERNAL FILE FOR PROPAGATION OF CONSTRAINTS IS EVALUATED.
          if ($@) { print $tee "ERROR in $configaddress:\n$@"; die; }
        }
        else
        {
          say $tee "$configaddress does not exist. Exiting." and die;
        }
      }
    }

    my $countfile = 0;
    foreach my $sourcefile ( @sourcefiles )
    {
        my $sourceaddress = "$to$sourcefile";  #say $tee "\$sourceaddress: " . dump( $sourceaddress );

        open( SOURCEFILE, $sourceaddress ) or die "Can't open $sourceaddress: $!\n";
        my @lines = <SOURCEFILE>;
        close SOURCEFILE;
        my $old = $sourceaddress . ".old" ;
            print $tee `mv $sourceaddress $old `;

        my $num = $numberfiles[$countfile];

        open( SOURCEFILE, ">$sourceaddress" ) or die "Can't open $sourceaddress: $!\n";
    
        my $countline = 0;
        my $countv = 0;
        my $countob = 0;
        foreach my $lin ( @lines )
        {
          chomp $lin;
          if ( $lin =~ /^\*vertex/ )
          {
             $countv++;
             my $ve = $ver{$num}{$countv};
             $ve->[0] = sprintf("%.5f", $ve->[0]);
             $ve->[1] = sprintf("%.5f", $ve->[1]);
             $ve->[2] = sprintf("%.5f", $ve->[2]);
             print SOURCEFILE "*vertex  $ve->[0]  $ve->[1]  $ve->[2]   #   $countv\n";
          }
          elsif ( $lin =~ /^\*obs/ )
          {
            $countob++;
            my $ob = $obs{$num}{$countob};
            print SOURCEFILE "*obs,$ob->[1],$ob->[2],$ob->[3],$ob->[4],$ob->[5],$ob->[6],$ob->[7],$ob->[8],$ob->[9] $ob->[10]  #   block  $countob\n";
          }
          else
          {
             print SOURCEFILE "$lin\n";
          }
          $countline++;
        }
        $countfile++;
        close SOURCEFILE;
    }
    
    unless ( !%eds )
    {
        foreach my $sourcefile ( @sourcefiles )
        {
            my $sourceaddress = "$to$sourcefile";  #say $tee "\$sourceaddress: " . dump( $sourceaddress );

            open( SOURCEFILE, $sourceaddress ) or die "Can't open $sourceaddress: $!\n";
            my @lines = <SOURCEFILE>;
            close SOURCEFILE;
            my $old = $sourceaddress . ".oldnew" ;
            print $tee `mv $sourceaddress $oldnew `;

            my $cnt = 0;
            foreach my $lin ( @lines )
            {
                if ( $lin =~ /#&&/ )
                {   #say $tee "APPLY_CONSTRAINTS \$lin: " . dump( $lin );
                    $lin =~ s/ +/ /;
                    my @splits = split( "$separator", $lin ); say $tee "APPLY_CONSTRAINTS \@splits: " . dump( @splits );

                    my @transitional = split( /#&&/, $lin );
                    my $rightpart = $transitional[1];
                    $rightpart =~ s/^ +//;
                    $rightpart =~ s/ +/ /; say $tee "APPLY_CONSTRAINTS \$rightpart: " . dump( $rightpart );
                    my @elms = split( / /, $rightpart ); say $tee "APPLY_CONSTRAINTS \@elms: " . dump( @elms );

                    foreach my $elm ( @elms )
                    {
                        chomp $elm;
                        my ( $name, $number ) = split( "-", $elm );

                        say $tee "APPLY_CONSTRAINTS \$name: " . dump( $name );
                        if ( $eds{$name}{file} eq $sourcefile )
                        {
                            #if ( $eds{$name}{line} eq $cnt )
                            #{
                                $splits[$eds{$name}{position}] = $eds{$name}{newvalue};

                                #$line = ( substr( $line, 0, $eds{$name}{beginning} ) ) . ( substr( $line, $eds{$name}{end} ) ); say $tee "APPPLY_CONSTRAINTS \$line!: " . dump( $line );
                                #substr( $line, $eds{$name}{beginning}, 0) = $eds{$name}{newvalue}; say $tee "APPPLY_CONSTRAINTS \$line!: " . dump( $line );

                                #unless ( $line =~ /#&&/ )
                                #{
                                # $line . " $rightpart";
                                #}
                            #}
                        }
                    }

                    my $novelline;
                    foreach my $split ( @splits )
                    {
                        $split = $split . "$separator";
                        $novelline = $novelline . $split;
                    }
                    $line = $novelline . "\n";
                }
                $line =~ s/\\00//g ;
                print SOURCEFILE $line;
                $cnt++;
            }
            close SOURCEFILE;
        }
    }
    say $tee "#Tranlating vertices while applying constraints " . ($countcase + 1) . ", block " . ($countblock + 1) . ", parameter $countvar at iteration $countstep. Instance $countinstance.\n";
}   # END SUB genmodnew



#############################################################################

1;

__END__

=head1 NAME

OPTcue. Additional function for Sim::OPT.

=head1 SYNOPSIS



=head1 DESCRIPTION

OPclue is a program adding functionalities to the Sim::OPT program, an optimization and parametric exploration program favouring problem decomposition.

OPT works under Linux.

=head2 EXPORT


=head1 SEE ALSO


=head1 AUTHOR

Gian Luca Brunetti, E<lt>gianluca.brunetti@gmail.comE<gt>

=head1 COPYRIGHT AND LICENSE

Copyright (C) 2025 by Gian Luca Brunetti, gianluca.brunetti@gmail.com. All rights reserved.

=cut
