|
10 | 10 |
|
11 | 11 | #include <cstdlib>
|
12 | 12 | #include <cstring>
|
| 13 | +#include <limits> |
13 | 14 |
|
14 | 15 | #include <isce3/except/Error.h>
|
| 16 | +#include <isce3/unwrap/ortools/min_cost_flow.h> |
15 | 17 |
|
16 | 18 | #include "snaphu.h"
|
17 | 19 |
|
@@ -2350,7 +2352,7 @@ int InitNetwork(Array2D<short>& flows, long *ngroundarcsptr, long *ncycleptr,
|
2350 | 2352 | long i;
|
2351 | 2353 |
|
2352 | 2354 | /* get and initialize memory for nodes */
|
2353 |
| - if(ground!=NULL && nodesptr->size()){ |
| 2355 | + if(ground!=NULL && !nodesptr->size()){ |
2354 | 2356 | *nodesptr = Array2D<nodeT>(nrow-1, ncol-1);
|
2355 | 2357 | InitNodeNums(nrow-1,ncol-1,*nodesptr,ground);
|
2356 | 2358 | }
|
@@ -3673,6 +3675,173 @@ signed char ClipFlow(Array2D<signed char>& residue, Array2D<short>& flows,
|
3673 | 3675 | }
|
3674 | 3676 |
|
3675 | 3677 |
|
| 3678 | +/* function: MCFInitFlows() |
| 3679 | + * ------------------------ |
| 3680 | + * Initializes the flow on the network using a minimum cost flow |
| 3681 | + * algorithm. |
| 3682 | + */ |
| 3683 | +int MCFInitFlows(Array2D<float>& wrappedphase, Array2D<short>* flowsptr, |
| 3684 | + Array2D<short>& mstcosts, long nrow, long ncol){ |
| 3685 | + |
| 3686 | + /* number of rows & cols of nodes in the residue network */ |
| 3687 | + const auto m=nrow-1; |
| 3688 | + const auto n=ncol-1; |
| 3689 | + |
| 3690 | + /* calculate phase residues (integer numbers of cycles) */ |
| 3691 | + auto residue=Array2D<signed char>(m,n); |
| 3692 | + CycleResidue(wrappedphase,residue,nrow,ncol); |
| 3693 | + |
| 3694 | + /* total number of nodes and directed arcs in the network */ |
| 3695 | + const auto nnodes=m*n+1; |
| 3696 | + const auto narcs=2*((m+1)*n+(n+1)*m); |
| 3697 | + |
| 3698 | + /* the solver uses 32-bit integers for node & arc indices */ |
| 3699 | + /* check for possible overflow */ |
| 3700 | + using operations_research::NodeIndex; |
| 3701 | + using operations_research::ArcIndex; |
| 3702 | + if(nnodes>std::numeric_limits<NodeIndex>::max()){ |
| 3703 | + throw isce3::except::RuntimeError(ISCE_SRCINFO(), |
| 3704 | + "Number of MCF network nodes exceeds maximum representable value"); |
| 3705 | + } |
| 3706 | + if(narcs>std::numeric_limits<ArcIndex>::max()){ |
| 3707 | + throw isce3::except::RuntimeError(ISCE_SRCINFO(), |
| 3708 | + "Number of MCF network arcs exceeds maximum representable value"); |
| 3709 | + } |
| 3710 | + |
| 3711 | + /* begin building the network topology and setting up the MCF problem */ |
| 3712 | + using Network=operations_research::SimpleMinCostFlow; |
| 3713 | + auto network=Network(nnodes,narcs); |
| 3714 | + |
| 3715 | + /* assigns a positive integer label to each grid node */ |
| 3716 | + /* grid node indices begin at 1 (index 0 is used for the ground node) */ |
| 3717 | + auto GetNodeIndex=[=](long i, long j)->NodeIndex{ |
| 3718 | + return 1+i*n+j; |
| 3719 | + }; |
| 3720 | + constexpr NodeIndex ground=0; |
| 3721 | + |
| 3722 | + /* adds a pair of forward & reverse arcs to the network connecting two nodes */ |
| 3723 | + /* sister arcs have equal cost and capacity */ |
| 3724 | + using operations_research::CostValue; |
| 3725 | + using operations_research::FlowQuantity; |
| 3726 | + auto AddSisterArcs=[&](NodeIndex node1, NodeIndex node2, CostValue cost){ |
| 3727 | + constexpr static auto capacity=static_cast<FlowQuantity>(ARCUBOUND); |
| 3728 | + network.AddArcWithCapacityAndUnitCost(node2,node1,capacity,cost); |
| 3729 | + network.AddArcWithCapacityAndUnitCost(node1,node2,capacity,cost); |
| 3730 | + }; |
| 3731 | + |
| 3732 | + /* break down arc costs into row (horizontal) & col (vertical) cost arrays */ |
| 3733 | + const auto rowcosts=mstcosts.topLeftCorner(m,n+1); |
| 3734 | + const auto colcosts=mstcosts.bottomLeftCorner(m+1,n); |
| 3735 | + |
| 3736 | + /* arcs are assigned sequential indices (starting from 0) in the order that |
| 3737 | + they're added to the network */ |
| 3738 | + /* we rely on this fact later on when extracting flows from the network */ |
| 3739 | + |
| 3740 | + /* begin adding horizontal arcs to the network */ |
| 3741 | + for(long i=0;i<m;++i){ |
| 3742 | + /* add a pair of arcs between the left border node and the ground node */ |
| 3743 | + { |
| 3744 | + const auto node=GetNodeIndex(i,0); |
| 3745 | + const auto cost=static_cast<CostValue>(rowcosts(i,0)); |
| 3746 | + AddSisterArcs(ground,node,cost); |
| 3747 | + } |
| 3748 | + |
| 3749 | + /* add a pair of horizontal arcs between each adjacent grid node */ |
| 3750 | + for(long j=0;j<n-1;++j){ |
| 3751 | + const auto node1=GetNodeIndex(i,j); |
| 3752 | + const auto node2=GetNodeIndex(i,j+1); |
| 3753 | + const auto cost=static_cast<CostValue>(rowcosts(i,j+1)); |
| 3754 | + AddSisterArcs(node1,node2,cost); |
| 3755 | + } |
| 3756 | + |
| 3757 | + /* add a pair of arcs between the right border node and the ground node */ |
| 3758 | + { |
| 3759 | + const auto node=GetNodeIndex(i,n-1); |
| 3760 | + const auto cost=static_cast<CostValue>(rowcosts(i,n)); |
| 3761 | + AddSisterArcs(node,ground,cost); |
| 3762 | + } |
| 3763 | + } |
| 3764 | + |
| 3765 | + /* begin adding vertical arcs to the network */ |
| 3766 | + /* add a pair of arcs between each top border node and the ground node */ |
| 3767 | + for(long j=0;j<n;++j){ |
| 3768 | + const auto node=GetNodeIndex(0,j); |
| 3769 | + const auto cost=static_cast<CostValue>(colcosts(0,j)); |
| 3770 | + AddSisterArcs(ground,node,cost); |
| 3771 | + } |
| 3772 | + /* add a pair of vertical arcs between each adjacent grid node */ |
| 3773 | + for(long i=0;i<m-1;++i){ |
| 3774 | + for(long j=0;j<n;++j){ |
| 3775 | + const auto node1=GetNodeIndex(i,j); |
| 3776 | + const auto node2=GetNodeIndex(i+1,j); |
| 3777 | + const auto cost=static_cast<CostValue>(colcosts(i+1,j)); |
| 3778 | + AddSisterArcs(node1,node2,cost); |
| 3779 | + } |
| 3780 | + } |
| 3781 | + /* add a pair of arcs between each bottom border node and the ground node */ |
| 3782 | + for(long j=0;j<n;++j){ |
| 3783 | + const auto node=GetNodeIndex(m-1,j); |
| 3784 | + const auto cost=static_cast<CostValue>(colcosts(m,j)); |
| 3785 | + AddSisterArcs(node,ground,cost); |
| 3786 | + } |
| 3787 | + |
| 3788 | + /* add node supplies to the network */ |
| 3789 | + FlowQuantity totalsupply=0; |
| 3790 | + for(long i=0;i<m;++i){ |
| 3791 | + for(long j=0;j<n;++j){ |
| 3792 | + auto node=GetNodeIndex(i,j); |
| 3793 | + auto supply=static_cast<FlowQuantity>(residue(i,j)); |
| 3794 | + network.SetNodeSupply(node,supply); |
| 3795 | + totalsupply+=supply; |
| 3796 | + } |
| 3797 | + } |
| 3798 | + |
| 3799 | + /* add enough demand to the ground node to balance the network */ |
| 3800 | + network.SetNodeSupply(ground,-totalsupply); |
| 3801 | + |
| 3802 | + /* run the solver to produce L1-optimal flows */ |
| 3803 | + if(network.Solve() != Network::OPTIMAL){ |
| 3804 | + throw isce3::except::RuntimeError(ISCE_SRCINFO(), |
| 3805 | + "MCF initialization failed"); |
| 3806 | + } |
| 3807 | + |
| 3808 | + *flowsptr=MakeRowColArray2D<short>(nrow,ncol); |
| 3809 | + |
| 3810 | + /* break down arc flows into row (horizontal) & col (vertical) flow arrays */ |
| 3811 | + auto rowflows=flowsptr->topLeftCorner(m,n+1); |
| 3812 | + auto colflows=flowsptr->bottomLeftCorner(m+1,n); |
| 3813 | + |
| 3814 | + /* extract arc flows from the network */ |
| 3815 | + /* the easiest way to do this is in the exact order in which the arcs were |
| 3816 | + added to the network (relying implicitly on the sequential ordering of arc |
| 3817 | + indices) */ |
| 3818 | + |
| 3819 | + /* extract horizontal flows from the network */ |
| 3820 | + ArcIndex arcidx=0; |
| 3821 | + for(long i=0;i<m;++i){ |
| 3822 | + for(long j=0;j<n+1;++j){ |
| 3823 | + /* Compute eastward-minus-westward net flow */ |
| 3824 | + const auto x1=network.Flow(arcidx++); |
| 3825 | + const auto x2=network.Flow(arcidx++); |
| 3826 | + rowflows(i,j)=x2-x1; |
| 3827 | + } |
| 3828 | + } |
| 3829 | + |
| 3830 | + /* extract vertical flows from the network */ |
| 3831 | + for(long i=0;i<m+1;++i){ |
| 3832 | + for(long j=0;j<n;++j){ |
| 3833 | + /* Compute southward-minus-northward net flow */ |
| 3834 | + const auto x1=network.Flow(arcidx++); |
| 3835 | + const auto x2=network.Flow(arcidx++); |
| 3836 | + colflows(i,j)=x2-x1; |
| 3837 | + } |
| 3838 | + } |
| 3839 | + |
| 3840 | + /* done */ |
| 3841 | + return(0); |
| 3842 | +} |
| 3843 | + |
| 3844 | + |
3676 | 3845 | #define INSTANTIATE_TEMPLATES(T) \
|
3677 | 3846 | template long TreeSolve(Array2D<nodeT>&, Array2D<nodesuppT>&, nodeT*, \
|
3678 | 3847 | nodeT*, Array1D<candidateT>*, \
|
|
0 commit comments