-- import Debug.Trace (trace)

perStateSweep ::
  (Node.C node, Show node,RealFloat a,
   Ord a, Show a, UV.Unbox a, Arith.ZeroTestable (sweep vec a),
   Arith.Product (sweep vec a), Arith.Constant a,
   Sweep.SweepVector vec a, Sweep.SweepMap sweep vec a a,
   Sweep.SweepClass sweep vec a,
   Monoid (sweep vec Bool),
   Sweep.SweepMap sweep vec a Bool,
   Sweep.SweepClass sweep vec Bool) =>
  Params.System node a ->
  Params.Optimisation node list sweep vec a ->
  StateQty.Graph node (Result (sweep vec a)) (Result (sweep vec a)) ->
  Map Idx.State (Map (list a) (Type.SweepPerReq node sweep vec a))
perStateSweep sysParams optParams stateFlowGraph  =
  Map.mapWithKey f states
  where states = StateQty.states stateFlowGraph
        reqsAndDofs = map TopoIdx.Power
                      $ ReqsAndDofs.unReqs (Params.reqsPos optParams)
                        ++ ReqsAndDofs.unDofs (Params.dofsPos optParams)

        f state _ = DoubleSweep.doubleSweep solveFunc (Params.points optParams)
          where solveFunc =
                  Optimisation.solve
                    optParams
                    reqsAndDofs
                    (AppOpt.eraseXAndEtaFromState state stateFlowGraph)
                    (Params.etaAssignMap sysParams)
                    (Params.etaMap sysParams)
                    state
perStateSweep ::
  (Node.C node, Show node,RealFloat a,
   Ord a, Show a, UV.Unbox a, Arith.ZeroTestable (sweep vec a),
   Arith.Product (sweep vec a), Arith.Constant a,
   Sweep.SweepVector vec a, Sweep.SweepMap sweep vec a a,
   Sweep.SweepClass sweep vec a,
   Monoid (sweep vec Bool),
   Sweep.SweepMap sweep vec a Bool,
   Sweep.SweepClass sweep vec Bool) =>
  Params.System node a ->
  Params.Optimisation node list sweep vec a ->
  StateQty.Graph node (Result (sweep vec a)) (Result (sweep vec a)) ->
  Map Idx.State (Map (list a) (Type.SweepPerReq node sweep vec a))
perStateSweep sysParams optParams stateFlowGraph  =
  Map.mapWithKey f states
  where states = StateQty.states stateFlowGraph
        reqsAndDofs = map TopoIdx.Power
                      $ ReqsAndDofs.unReqs (Params.reqsPos optParams)
                        ++ ReqsAndDofs.unDofs (Params.dofsPos optParams)

        f state _ = DoubleSweep.doubleSweep solveFunc (Params.points optParams)
          where solveFunc =
                  Optimisation.solve
                    optParams
                    reqsAndDofs
                    (AppOpt.eraseXAndEtaFromState state stateFlowGraph)
                    (Params.etaAssignMap sysParams)
                    (Params.etaMap sysParams)
                    state
perStateSweep sysParams optParams stateFlowGraph  =
  Map.mapWithKey f states
  where states = StateQty.states stateFlowGraph
        reqsAndDofs = map TopoIdx.Power
                      $ ReqsAndDofs.unReqs (Params.reqsPos optParams)
                        ++ ReqsAndDofs.unDofs (Params.dofsPos optParams)

        f state _ = DoubleSweep.doubleSweep solveFunc (Params.points optParams)
          where solveFunc =
                  Optimisation.solve
                    optParams
                    reqsAndDofs
                    (AppOpt.eraseXAndEtaFromState state stateFlowGraph)
                    (Params.etaAssignMap sysParams)
                    (Params.etaMap sysParams)
                    state