@@ -478,25 +478,8 @@ function default_copy_to(dest::MOI.ModelLike, src::MOI.ModelLike)
478
478
error (" Model $(typeof (dest)) does not support copy_to." )
479
479
end
480
480
MOI. empty! (dest)
481
- vis_src = MOI. get (src, MOI. ListOfVariableIndices ())
482
- index_map = IndexMap ()
483
- # The `NLPBlock` assumes that the order of variables does not change (#849)
484
- # Therefore, all VariableIndex and VectorOfVariable constraints are added
485
- # seprately, and no variables constrained-on-creation are added.
486
- has_nlp = MOI. NLPBlock () in MOI. get (src, MOI. ListOfModelAttributesSet ())
487
- constraints_not_added = if has_nlp
488
- Any[
489
- MOI. get (src, MOI. ListOfConstraintIndices {F,S} ()) for
490
- (F, S) in MOI. get (src, MOI. ListOfConstraintTypesPresent ()) if
491
- _is_variable_function (F)
492
- ]
493
- else
494
- Any[
495
- _try_constrain_variables_on_creation (dest, src, index_map, S)
496
- for S in sorted_variable_sets_by_cost (dest, src)
497
- ]
498
- end
499
- _copy_free_variables (dest, index_map, vis_src)
481
+ index_map, vis_src, constraints_not_added =
482
+ _copy_variables_with_set (dest, src)
500
483
# Copy variable attributes
501
484
pass_attributes (dest, src, index_map, vis_src)
502
485
# Copy model attributes
@@ -507,6 +490,119 @@ function default_copy_to(dest::MOI.ModelLike, src::MOI.ModelLike)
507
490
return index_map
508
491
end
509
492
493
+ struct _CopyVariablesWithSetCache
494
+ variable_to_column:: Dict{MOI.VariableIndex,Int}
495
+ constraints_not_added:: Vector{Any}
496
+ variables_with_domain:: Set{MOI.VariableIndex}
497
+ variable_cones:: Vector{Tuple{Vector{MOI.VariableIndex},Any}}
498
+ function _CopyVariablesWithSetCache ()
499
+ return new (
500
+ Dict {MOI.VariableIndex,Int} (),
501
+ Any[],
502
+ Set {MOI.VariableIndex} (),
503
+ Tuple{Vector{MOI. VariableIndex},Any}[]
504
+ )
505
+ end
506
+ end
507
+
508
+ function _build_copy_variables_with_set_cache (
509
+ src:: MOI.ModelLike ,
510
+ cache:: _CopyVariablesWithSetCache ,
511
+ :: Type{S} ,
512
+ ) where {S<: MOI.AbstractScalarSet }
513
+ F = MOI. VariableIndex
514
+ for ci in MOI. get (src, MOI. ListOfConstraintIndices {F,S} ())
515
+ f = MOI. get (src, MOI. ConstraintFunction (), ci)
516
+ if f in cache. variables_with_domain
517
+ push! (cache. constraints_not_added, ci)
518
+ else
519
+ push! (cache. variables_with_domain, f)
520
+ push! (cache. variable_cones, ([f], ci))
521
+ end
522
+ end
523
+ return
524
+ end
525
+
526
+ function _is_variable_cone (cache, f:: MOI.VectorOfVariables )
527
+ if isempty (f. variables)
528
+ return false
529
+ end
530
+ offset = cache. variable_to_column[f. variables[1 ]] - 1
531
+ for (i, xi) in enumerate (f. variables)
532
+ if xi in cache. variables_with_domain
533
+ return false
534
+ elseif cache. variable_to_column[xi] != offset + i
535
+ return false
536
+ end
537
+ end
538
+ return true
539
+ end
540
+
541
+ function _build_copy_variables_with_set_cache (
542
+ src:: MOI.ModelLike ,
543
+ cache:: _CopyVariablesWithSetCache ,
544
+ :: Type{S} ,
545
+ ) where {S<: MOI.AbstractVectorSet }
546
+ F = MOI. VectorOfVariables
547
+ for ci in MOI. get (src, MOI. ListOfConstraintIndices {F,S} ())
548
+ f = MOI. get (src, MOI. ConstraintFunction ())
549
+ if _is_variable_cone (cache, f)
550
+ for fi in f. variables
551
+ push! (cache. variables_with_domain, fi)
552
+ end
553
+ push! (cache. variable_cones, (f. variables, ci))
554
+ else
555
+ push! (cache. constraints_not_added, ci)
556
+ end
557
+ end
558
+ return
559
+ end
560
+
561
+ function _copy_variables_with_set (dest, src)
562
+ vis_src = MOI. get (src, MOI. ListOfVariableIndices ())
563
+ index_map = IndexMap ()
564
+ cache = _CopyVariablesWithSetCache ()
565
+ for (i, v) in enumerate (vis_src)
566
+ cache. variable_to_column[v] = i
567
+ end
568
+ for S in sorted_variable_sets_by_cost (dest, src)
569
+ _build_copy_variables_with_set_cache (src, cache, S)
570
+ end
571
+ column (x:: MOI.VariableIndex ) = cache. variable_to_column[x]
572
+ start_column (x) = column (first (x[1 ]))
573
+ current_column = 0
574
+ for (f, ci) in sort! (cache. variable_cones; by = start_column)
575
+ offset = column (first (f)) - current_column - 1
576
+ if offset > 0
577
+ dest_x = MOI. add_variables (dest, offset)
578
+ for i in 1 : offset
579
+ index_map[vis_src[current_column + i]] = dest_x[i]
580
+ end
581
+ end
582
+ set = MOI. get (src, MOI. ConstraintSet (), ci)
583
+ if set isa MOI. AbstractScalarSet
584
+ dest_x, dest_ci = MOI. add_constrained_variable (dest, set)
585
+ index_map[only (f)] = dest_x
586
+ index_map[ci] = dest_ci
587
+ else
588
+ dest_x, dest_ci = MOI. add_constrained_variables (dest, set)
589
+ for (fi, xi) in zip (f, dest_x)
590
+ index_map[fi] = xi
591
+ end
592
+ index_map[ci] = dest_ci
593
+ end
594
+ current_column = column (last (f))
595
+ end
596
+ offset = length (cache. variable_to_column) - current_column
597
+ if offset > 0
598
+ dest_x = MOI. add_variables (dest, offset)
599
+ for i in 1 : offset
600
+ index_map[vis_src[current_column + i]] = dest_x[i]
601
+ end
602
+ end
603
+ return index_map, vis_src, cache. constraints_not_added
604
+ end
605
+
510
606
"""
511
607
ModelFilter(filter::Function, model::MOI.ModelLike)
512
608
0 commit comments