API Reference¶
Bipartite Matching¶
The following mods can be imported from gurobi_optimods.bipartite_matching:
- maximum_bipartite_matching(graph, nodes1, nodes2, *, verbose=True, logfile=None, time_limit=None, solver_params=None)¶
- Solve a maximum cardinality bipartite matching problem on the given graph. - Parameters:
- graphspmatrixorGraphorDataFrame
- A graph, specified either as a scipy.sparse adjacency matrix, networkx graph, or pandas dataframe. 
- nodes1ndarrayorstr
- Nodes in the first bipartite set. If - graphis a scipy sparse matrix,- nodes1must be a numpy array. If- graphis a pandas dataframe,- nodes1must be a column name. If- graphis a networkx graph,- nodes1must be a list.
- nodes2ndarrayorstr
- Nodes in the second bipartite set. If - graphis a scipy sparse matrix,- nodes2must be a numpy array. If- graphis a pandas dataframe,- nodes2must be a column name. If- graphis a networkx graph,- nodes2must be a list.
- verbosebool, optional
- verbose=Falsesuppresses all console output
- logfilestr, optional
- Write all mod output to the given file path 
- time_limitfloat
- Solver time limit in seconds (default no limit) 
- solver_paramsdict, optional
- Gurobi parameters to be passed to the solver 
 
- graph
- Returns:
 
Line Optimization in Public Transportation Networks¶
The following mods can be imported from gurobi_optimods.line_optimization:
- line_optimization(node_data, edge_data, line_data, linepath_data, demand_data, frequencies, shortest_paths=True, *, verbose=True, logfile=None, time_limit=None, solver_params=None)¶
- Solve the line planning problem. - Parameters:
- node_dataDataFrame
- DataFrame with information on the nodes/stations. The frame must include “source”. 
- edge_dataDataFrame
- DataFrame with edges / connections between stations and associated attributes. The frame must include “source”, “target”, and “time” 
- demand_dataDataFrame
- DataFrame with node/station demand information. It must include “source”, “target”, and “demand”. The demand value must be non-negative. 
- line_dataDataFrame
- DataFrame with general line information. It must include “linename”, “capacity”, “fix_cost”, and “operating_cost”. 
- linepath_dataDataFrame
- DataFrame with information on the line routes/paths. It must include “linename”, “edge_source”, and “edge_target”. 
- frequency: List
- List with possible frequencies: How often the line can be operated in the considered time horizon. 
- shortest_pathsbool
- Parameter to choose the strategy. Default value is true and strategy 1 is used, i.e., passengers travel along shortest paths. Set to False if all possible paths are allowed. In that case, a multi-objective approach is used to first minimize line operating cost and then minimize passengers travel time. 
- verbosebool, optional
- verbose=Falsesuppresses all console output
- logfilestr, optional
- Write all mod output to the given file path 
- time_limitfloat
- Solver time limit in seconds (default no limit) 
- solver_paramsdict, optional
- Gurobi parameters to be passed to the solver 
 
- node_data
- Returns:
- tuple
- Cost of the optimal line concept (line frequency) 
- list of line-frequency tuples (optimal line concept) 
 
 
 
Maximum Flow¶
The following mods can be imported from gurobi_optimods.max_flow:
- max_flow(graph, source, sink, **kwargs)¶
- Solve the maximum flow problem for a given graph. - Parameters:
- graphspmatrixorGraphorDataFrame
- A graph, specified either as a scipy.sparse adjacency matrix, networkx graph, or pandas dataframe. These contain the capacity for each edge. In the networkx (pandas dataframe) case, we expect the edge attribute (column name) - capacity. Please see the example in the documentation.
- sourceintorstr
- The source (or origin) node for the maximum flow. 
- sinkintorstr
- The sink (or destination) node for the maximum flow. 
 
- graph
- Returns:
 
Metro Map: Computing an Octilinear Graph Representation¶
The following mods can be imported from gurobi_optimods.metromap:
- metromap(graph, linepath_data=None, include_planarity=True, penalty_edge_directions=1, penalty_line_bends=1, penalty_distance=1, improve_lp=True, *, verbose=True, logfile=None, time_limit=None, solver_params=None)¶
- Compute a metromap drawing, i.e., an octilinear network representation
- considering the origin geographical data if available given as geographic position of the nodes 
 - Parameters:
- graphGraph
- networkx graph with node attribute ‘pos’ being a tuple of x- and y-coordinate 
- linepath_dataDataFrame
- DataFrame with information on the line routes/paths. It must include “linename”, “edge_source”, and “edge_target”. This data frame could also be empty 
- include_planaritybool
- parameter to turn off the consideration of planarity constraints 
- penalty_edge_directionsfloat
- weight for original direction part in the objective, default is 1 
- penalty_line_bendsfloat
- weight for line-bend part in the objective, default is 1 
- penalty_distancefloat
- weight for distance part in the objective, default is 1 
- verbosebool, optional
- verbose=Falsesuppresses all console output
- logfilestr, optional
- Write all mod output to the given file path 
- time_limitfloat
- Solver time limit in seconds (default no limit) 
- solver_paramsdict, optional
- Gurobi parameters to be passed to the solver 
 
- graph
- Returns:
- tuple
- networkx graph with node property pos_oct representing the x and y coordinates of the octilinear representation 
- Python dict for direction for each edge (needed for plotting) 
 
 
 
Minimum Cost Flow¶
The following mods can be imported from gurobi_optimods.min_cost_flow:
- min_cost_flow_networkx(G, *, verbose=True, logfile=None, time_limit=None, solver_params=None)¶
- Solve the minimum cost flow problem for a given graph. - Parameters:
- GDiGraph
- Graph with edge attributes - capacityand- cost, as well as node attributes- demand.
- verbosebool, optional
- verbose=Falsesuppresses all console output
- logfilestr, optional
- Write all mod output to the given file path 
- time_limitfloat
- Solver time limit in seconds (default no limit) 
- solver_paramsdict, optional
- Gurobi parameters to be passed to the solver 
 
- G
- Returns:
- tuple
- Cost of the minimum cost flow (float), a subgraph of the original graph specifying the flow 
 
 
- min_cost_flow_pandas(arc_data, demand_data, *, verbose=True, logfile=None, time_limit=None, solver_params=None)¶
- Solve the minimum cost flow problem for a given graph. - The inputs adhere to the following structure: - arc_data = pd.DataFrame( [ {"from": 0, "to": 1, "capacity": 16, "cost": 0}, {"from": 1, "to": 2, "capacity": 10, "cost": 0}, ] ).set_index(["from", "to"]) demand_data = pd.DataFrame( [{"node": 0, "demand": -1}, {"node": 2, "demand": 1}] ).set_index("node") - Parameters:
- arc_dataDataFrame
- DataFrame with graph and respective attributes. These must include - "from",- "to"nodes used as index as well as- "capacity", and- "cost"columns.
- demand_dataDataFrame
- DataFrame with node demand information. These must include indexed by - "node", and include the- "demand"column. This value can be positive (requesting flow) or negative (supplying flow).
- verbosebool, optional
- verbose=Falsesuppresses all console output
- logfilestr, optional
- Write all mod output to the given file path 
- time_limitfloat
- Solver time limit in seconds (default no limit) 
- solver_paramsdict, optional
- Gurobi parameters to be passed to the solver 
 
- arc_data
- Returns:
- tuple
- Cost of the minimum cost flow (float), dictionary indexed by edges with non-zero flow in the solution (Series) 
 
 
- min_cost_flow_scipy(G, capacities, costs, demands, *, verbose=True, logfile=None, time_limit=None, solver_params=None)¶
- Solve the minimum cost flow problem for a given graph. - Parameters:
- Gspmatrix
- Adjacency matrix of the graph. 
- capacitiesspmatrix
- Matrix containing capacities for each edge. 
- costsspmatrix
- Matrix containing costs for each edge. 
- demandsndarray
- Array containing the demand for each node. 
- verbosebool, optional
- verbose=Falsesuppresses all console output
- logfilestr, optional
- Write all mod output to the given file path 
- time_limitfloat
- Solver time limit in seconds (default no limit) 
- solver_paramsdict, optional
- Gurobi parameters to be passed to the solver 
 
- G
- Returns:
- tuple
- Cost of the minimum cost flow (float), dictionary indexed by edges with non-zero flow in the solution (spmatrix) 
 
 
Minimum Cut¶
The following mods can be imported from gurobi_optimods.min_cut:
- class MinCutResult(cut_value, partition, cutset)¶
- Solution to a Minimum-cut problem. - Attributes:
- cut: float
- Cut value of the minimum cut. 
- partition: tuple with sets
- Partition of size 2 with cut sets. 
- cutset: set of tuple
- Cutset with edges. 
 
 
- min_cut(graph, source, sink, *, verbose=True, logfile=None, time_limit=None, solver_params=None)¶
- Solve the minimum cut problem for a given graph. - Parameters:
- graphspmatrixorGraphorDataFrame
- A graph, specified either as a scipy.sparse adjacency matrix, networkx graph, or pandas dataframe. These contain the capacity for each edge. In the networkx (pandas dataframe) case, we expect the edge attribute (column name) - capacity. Please see the example in the documentation.
- sourceintorstr
- The source (or origin) node for the cutset. 
- sinkintorstr
- The sink (or destination) node for the cutset. 
- verbosebool, optional
- verbose=Falsesuppresses all console output
- logfilestr, optional
- Write all mod output to the given file path 
- time_limitfloat
- Solver time limit in seconds (default no limit) 
- solver_paramsdict, optional
- Gurobi parameters to be passed to the solver 
 
- graph
- Returns:
- min_cut_result: MinCutResult
- A dataclass containing the cut value, and set of nodes and edges in the minimum cut. 
 
- min_cut_result: 
 
Maximum Weighted Independent Set/Clique¶
The following mods can be imported from gurobi_optimods.mwis:
- class MWISResult(x, f)¶
- Data class representing the maximum weighted independent set (clique) and its weight 
- maximum_weighted_clique(graph, weights, *, verbose=True, logfile=None, time_limit=None, solver_params=None)¶
- Find a set of fully connected vertices with maximum weighted sum. - Parameters:
- graphspmatrixorGraphorDataFrame
- A graph, specified as a scipy.sparse upper triangular adjacency matrix with zero diagonals, a networkx graph, or a pandas dataframe. The pandas dataframe must include edge information in two columns named as - "node1"and- "node2".
- weightsndarrayofDataFrame
- Vertex weights. If - graphis a scipy.sparse matrix or a networkx graph,- weightsmust be a numpy array. If- graphis a pandas dataframe graph,- weightsmust be a dataframe too. The weights dataframe must include the weight information in a column named- "weights"and must be indexed by vertex number.
- verbosebool, optional
- verbose=Falsesuppresses all console output
- logfilestr, optional
- Write all mod output to the given file path 
- time_limitfloat
- Solver time limit in seconds (default no limit) 
- solver_paramsdict, optional
- Gurobi parameters to be passed to the solver 
 
- graph
- Returns:
- MWISResult
- A data class representing the maximum weighted clique array and its weight. 
 
 
- maximum_weighted_independent_set(graph, weights, *, verbose=True, logfile=None, time_limit=None, solver_params=None)¶
- Find a set of mutually non-adjacent vertices with maximum weighted sum. - Parameters:
- graphspmatrixorGraphorDataFrame
- A graph, specified as a scipy.sparse upper triangular adjacency matrix with zero diagonals, a networkx graph, or a pandas dataframe. The pandas dataframe must include edge information in two columns named as - "node1"and- "node2".
- weightsndarrayorDataFrame
- Vertex weights. If - graphis a scipy.sparse matrix or a networkx graph,- weightsmust be a numpy array. If- graphis a pandas dataframe graph,- weightsmust be a dataframe too. The weights dataframe must include the weight information in a column named- "weights"and must be indexed by vertex number.
- verbosebool, optional
- verbose=Falsesuppresses all console output
- logfilestr, optional
- Write all mod output to the given file path 
- time_limitfloat
- Solver time limit in seconds (default no limit) 
- solver_paramsdict, optional
- Gurobi parameters to be passed to the solver 
 
- graph
- Returns:
- MWISResult
- A data class representing the maximum weighted independent set array and its weight. 
 
 
Optimal Power Flow¶
The following mods can be imported from gurobi_optimods.opf:
- compute_violations(case, voltages, polar=False, *, verbose=True, logfile=None, time_limit=None, solver_params=None)¶
- Constructs an OPF model from given case data and computes a violation dictionary out of given voltage values. - If a voltage solution is present, e.g., from an external computation, this function can be used to check whether the given voltage solution is indeed feasible for the AC optimization model. Usually, if the violations are not too big, one can use the voltage solution for further calculations. - Returns a violation dictionary following MATPOWER notation which holds all case data and additional violation fields. The additional fields are - violation["bus"][i]["Vmviol"]for voltage magnitude violation at bus i
- violation["bus"][i]["Pviol"]for real injection violation at bus i
- violation["bus"][i]["Qviol"]for reactive injection violation at bus i
- violation["branch"][i]["limitviol"]for limit violation at branch i
 - The violation dictionary can be used to generate a violations figure with the - generate_opf_violations_figurefunction- Parameters:
- casedict
- Dictionary holding case data 
- voltagesdict
- Dictionary holding bus input voltage data 
- polar: bool, optional
- If True, use polar formulation when checking violations, defaults to False 
- verbosebool, optional
- verbose=Falsesuppresses all console output
- logfilestr, optional
- Write all mod output to the given file path 
- time_limitfloat
- Solver time limit in seconds (default no limit) 
- solver_paramsdict, optional
- Gurobi parameters to be passed to the solver 
 
- case
- Returns:
- dict
- Case dictionary following MATPOWER notation with additional violations fields 
 
 
- read_case_matpower(file_path)¶
- Read in a MATPOWER case file. - The file must contain a MATPOWER version 2 ‘mpc’ struct. 
- solution_plot(case, coords, solution)¶
- Reads the given case and returns a plotly figure object. Ideally the solution has been computed by the - solve_opffunction- Parameters:
- Returns:
- plotly.graph_objects.Figure
- A plotly figure object displaying the solution. The plot can be displaged by calling - figure.show().
 
 
- solve_opf(case, opftype='AC', branch_switching=False, min_active_branches=0.9, use_mip_start=False, *, verbose=True, logfile=None, time_limit=None, solver_params=None)¶
- Constructs an OPF model from given data and solves it with Gurobi. Returns a result dictionary following MATPOWER notation. The additional and possibly altered fields are - result["success"]1 if at least one feasible solution has been found, 0 otherwise
- result["et"]time spent for optimization
- result["f"]solution objective value
- result["bus"][i]["Vm"]for voltage magnitude value at bus i
- result["bus"][i]["Va"]for voltage angle value at bus i
- result["bus"][i]["mu"]for shadow prices of balance constraints at bus i (only available for DC without branchswitching)
- result["gen"][i]["Pg"]for real power injection at generator i
- result["gen"][i]["Qg"]for reactive power injection at generator i
- result["branch"][i]["Pf"]for real power injected into “from” end of branch at branch i
- result["branch"][i]["Pt"]for real power injected into “to” end of branch at branch i
- result["branch"][i]["Qf"]for reactive power injected into “from” end of branch at branch i (AC only)
- result["branch"][i]["Qt"]for reactive power injected into “from” end of branch at branch i (AC only)
- result["branch"][i]["switching"]states whether a branch i is turned on or off in the final solution
 - Parameters:
- casedict
- Dictionary holding case data 
- opftypestr
- Desired OPF model type. One of - AC,- AClocal,- ACrelax, or- DC
- branch_switchingbool, optional
- If set to True, enables branch switching. 
- min_active_branchesfloat, optional
- Defines the minimum number of branches that must be turned on when branch switching is active, i.e. the minimum number of turned on branches is equal to - numbranches * min_active_branches. Has no effect if- branchswitchingis set to False.
- use_mip_startbool, optional
- (Advanced) If set to True, try various MIP starts for branch switching models. Has no effect if - branchswitchingis set to False. For DC models, this setting is ignored, and the mip start is always used.
- verbosebool, optional
- verbose=Falsesuppresses all console output
- logfilestr, optional
- Write all mod output to the given file path 
- time_limitfloat
- Solver time limit in seconds (default no limit) 
- solver_paramsdict, optional
- Gurobi parameters to be passed to the solver 
 
- case
- Returns:
- dict
- Case dictionary following MATPOWER notation with additional result fields 
 
 
- violation_plot(case, coords, violations)¶
- Reads the given case and returns a plotly figure object of provided violations. Ideally the violations have been computed by the - compute_violationsfunction- Parameters:
- Returns:
- plotly.graph_objects.Figure
- A plotly figure object highlighting violations in the solution. The plot can be displaged by calling - figure.show().
 
 
Mean-Variance Portfolio¶
The following mods can be imported from gurobi_optimods.portfolio:
- class MeanVariancePortfolio(mu, cov_matrix=None, cov_factors=None)¶
- Optimal mean-variance portfolio solver. - Instantiate an object of - MeanVariancePortfoliofor given covariance matrix and return vector. Use- MeanVariancePortfolio.efficient_portfolio()to solve for efficient portfolios with given parameters.- Parameters:
- mu1-d ndarray
- Vector of expected returns for each asset 
- cov_matrix2-d ndarray
- Covariance matrix \(\Sigma\) 
- cov_factorstupleofndarray
- Covariance factors that constitute \(\Sigma = B K B^T + diag(d)\). - cov_factors[0]: (n, k) ndarray \(B\)
- cov_factors[1]: (k, k) ndarray \(K\), SPD
- cov_factors[2]: (n,) ndarray \(d\), nonnegative
 
 
- mu1-d 
- Raises:
- LinAlgError
- If the matrix K is not positive definite 
 
 - efficient_portfolio(gamma, max_trades=None, max_positions=None, fees_buy=None, fees_sell=None, costs_buy=None, costs_sell=None, min_long=None, min_short=None, max_total_short=0.0, initial_holdings=None, rf_return=None, *, verbose=True, logfile=None, time_limit=None, solver_params=None)¶
- Compute efficient portfolio for given parameters - Parameters:
- gammafloat>= 0
- Risk aversion cofficient for balancing risk and return; the resulting objective functions is \(\mu^T x - 0.5 \gamma x^T \Sigma x\) 
- max_tradesint>= 0, optional
- Upper limit on the number of trades 
- max_positionsint>= 0, optional
- Upper limit on the number of open positions 
- fees_buyfloatorndarray>= 0, optional
- Fixed-charge fee for each buy transaction, relative to total portfolio value 
- fees_sellfloatorndarray>= 0, optional
- Fixed-charge fee for each sell transaction, relative to total portfolio value 
- costs_buyfloatorndarray>= 0, optional
- Variable transaction costs for each buy transaction, relative to trade value 
- costs_sellfloatorndarray>= 0, optional
- Variable transaction costs for each sell transaction, relative to trade value 
- min_longfloat>= 0, optional
- Lower bound on the volume on a traded long position, relative to total portfolio value 
- min_shortfloat>= 0, optional
- Lower bound on the volume on a traded short position, relative to total portfolio value 
- max_total_shortfloat>= 0, optional
- Maximum total short positions, relative to total investment. 
- initial_holdings1-d ndarray, optional
- Initial portfolio holdings (sum needs to be <= 1) 
- rf_returnfloat, optional
- Include a risk-free asset having return rate - rf_return.
- verbosebool, optional
- verbose=Falsesuppresses all console output
- logfilestr, optional
- Write all mod output to the given file path 
- time_limitfloat
- Solver time limit in seconds (default no limit) 
- solver_paramsdict, optional
- Gurobi parameters to be passed to the solver 
 
- gamma
- Returns:
- mvp_resultPortfolioResult
- A dataclass containing the efficient portfolio, along with auxiliary information: - mvp_result.x: The portfolio vector \(x\)
- mvp_result.risk: The estimated risk \(x^T \Sigma x\) of the portfolio
- mvp_result.return: The estimated return \(\mu^T x\) of the portfolio
- mvp.x_rfrelative investment in the risk-free asset. Present only if- rf_returnwas non-None on input
 - Some combinations of requested portfolio features may rule out all possible portfolios. In this corner case the value - Noneis returned.
 
- mvp_result
 - Notes - Refer to Enforcing more portfolio features for a detailed discussion of all parameters. 
 
- class PortfolioResult(x, ret, risk, x_rf=None)¶
- Data class representing computed portfolios. - Attributes:
 
Quadratic Unconstrained Binary Optimization (QUBO)¶
The following mods can be imported from gurobi_optimods.qubo:
- class QuboResult(solution, objective_value)¶
- Solution to a QUBO problem. 
- solve_qubo(coeff_matrix, *, verbose=True, logfile=None, time_limit=None, solver_params=None)¶
- Solve a quadratic unconstrained binary optimization (QUBO) problem, i.e., minimize quadratic function \(x'Qx\) defined by coefficient matrix \(Q\) over a binary decision variable vector \(x\) - Parameters:
- coeff_matrixspmatrix
- Quadratic coefficient matrix 
- verbosebool, optional
- verbose=Falsesuppresses all console output
- logfilestr, optional
- Write all mod output to the given file path 
- time_limitfloat
- Solver time limit in seconds (default no limit) 
- solver_paramsdict, optional
- Gurobi parameters to be passed to the solver 
 
- coeff_matrix
- Returns:
- QuboResult
- A dataclass containing a 0/1 solution array and its objective value 
 
 
Regression¶
The following mods can be imported from gurobi_optimods.regression:
- class LADRegression¶
- Least absolute deviations (L1-norm) regressor - fit(X_train, y_train, *, verbose=True, logfile=None, time_limit=None, solver_params=None)¶
- Fit the model to training data. - Parameters:
- X_trainndarray
- Training set feature values 
- y_trainndarray
- Training set output values 
- verbosebool, optional
- verbose=Falsesuppresses all console output
- logfilestr, optional
- Write all mod output to the given file path 
- time_limitfloat
- Solver time limit in seconds (default no limit) 
- solver_paramsdict, optional
- Gurobi parameters to be passed to the solver 
 
- X_train
 
 
- class SharpeRatioResult(x, sharpe_ratio, ret, risk)¶
- Data class representing the portfolio that maximizes the Sharpe ratio. 
- max_sharpe_ratio(cov_matrix, mu, rf_rate=0, *, verbose=True, logfile=None, time_limit=None, solver_params=None)¶
- Solve the problem of finding a portfolio that maximizes the Sharpe ratio. - Parameters:
- cov_matrixndarrayorDataFrame
- 2D positive-semidefinite variance-covariance matrix \(\Sigma\) 
- mundarrayorSeries
- Expected return rates \(\mu\) 
- rf_ratefloat>= 0, optional
- Non-negative risk-free rate of return (defaults to - 0)
- verbosebool, optional
- verbose=Falsesuppresses all console output
- logfilestr, optional
- Write all mod output to the given file path 
- time_limitfloat
- Solver time limit in seconds (default no limit) 
- solver_paramsdict, optional
- Gurobi parameters to be passed to the solver 
 
- cov_matrix
- Returns:
- resultSharpeRatioResult
- A data class representing the portfolio that maximizes the Sharpe ratio: - result.x: The relative portfolio allocations \(x\)
- result.sharpe_ratio: The Sharpe ratio of the portfolio
- result.ret: The estimated return \(\mu^T x\) of the portfolio
- result.risk: The estimated risk \(x^T \Sigma x\) of the portfolio
 
 
- result
 
Workforce Scheduling¶
The following mods can be imported from gurobi_optimods.workforce:
- solve_workforce_scheduling(availability, shift_requirements, worker_limits, preferences=None, rolling_limits=False, *, verbose=True, logfile=None, time_limit=None, solver_params=None)¶
- Solve a workforce scheduling model. - Parameters:
- availabilityDataFrame
- Dataframe with columns ‘Worker’ and ‘Shift’ defining all allowable worker-shift combinations. The ‘Preference’ column optionally assigns a preference value to the given combination. 
- shift_requirementsDataFrame
- Dataframe with columns ‘Shift’ and ‘Required’ specifying the number of staff required for every shift. 
- worker_limitsDataFrame
- Dataframe with columns ‘Worker’, ‘MinShifts’, and ‘MaxShifts’ specifying the maximum and minimum number of shifts each worker may be assigned in the schedule. 
- preferencesstr, optional
- The name of a column in the availability dataframe containing preference values. If provided, the mod returns a schedule which maximises the sum of preference values of assigned shifts. 
- rolling_limitsbool
- Whether to enforce worker shift limits on a rolling window basis. If True, worker_limits must contain an additional ‘Window’ column specifying the rolling window for each worker. 
- verbosebool, optional
- verbose=Falsesuppresses all console output
- logfilestr, optional
- Write all mod output to the given file path 
- time_limitfloat
- Solver time limit in seconds (default no limit) 
- solver_paramsdict, optional
- Gurobi parameters to be passed to the solver 
 
- availability
- Returns:
- DataFrame
- Shift assignments as a subset of the availability dataframe 
 
- Raises:
- ValueError
- If a feasible set of shift assignments cannot be constructed from the input data