Skip to content

Commit 01d63ad

Browse files
authored
Add case classes to enforce matching problem budget data assumptions (#42)
1 parent 51d3b88 commit 01d63ad

File tree

5 files changed

+29
-9
lines changed

5 files changed

+29
-9
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package com.linkedin.dualip.data
2+
3+
/**
4+
* Representation of the budget vector/budget per item id for Matching Problem.
5+
*
6+
* @param itemId - id of the item (i.e. product id)
7+
* @param budget - the budget for itemId/the b(itemId) value in the budget (b) vector
8+
*/
9+
case class BudgetData(itemId: Int, budget: Double)
10+
11+
/**
12+
* Representation of the budget for a specific entity, given a constraint matrix.
13+
* This is used to represent the budget of an entity that may have several constraints, as in the
14+
* Multiple Matching Problem.
15+
*
16+
* @param entityIndex - index for the entity
17+
* @param constraintIndex - index of the constraint
18+
* @param budgetValue - budget for this entity-constraint combo, or b(entityIndex)(constraintIndex)
19+
*/
20+
case class MultipleMatchingBudgetData(entityIndex: Int, constraintIndex: Int, budgetValue: Double)

dualip/src/main/scala/com/linkedin/dualip/driver/LPSolverDriver.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ object LPSolverDriver {
345345
val driverParams = LPSolverDriverParamsParser.parseArgs(args)
346346

347347
println("-----------------------------------------------------------------------")
348-
println(" DuaLip v2.0 2022")
348+
println(" DuaLip v4.0 2023")
349349
println(" Dual Decomposition based Linear Program Solver")
350350
println("-----------------------------------------------------------------------")
351351
println("Settings:")

dualip/src/main/scala/com/linkedin/dualip/problem/MatchingSlateSolver.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.linkedin.dualip.problem
22

33
import breeze.linalg.{SparseVector => BSV}
4-
import com.linkedin.dualip.data.MatchingData
4+
import com.linkedin.dualip.data.{BudgetData, MatchingData}
55
import com.linkedin.dualip.objective.distributedobjective.DistributedRegularizedObjective
66
import com.linkedin.dualip.objective.{DualPrimalObjective, DualPrimalObjectiveLoader, PartialPrimalStats}
77
import com.linkedin.dualip.projection.{BoxCutProjection, GreedyProjection, SimplexProjection, UnitBoxProjection}
@@ -12,7 +12,7 @@ import com.linkedin.optimization.util.VectorOperations.toBSV
1212
import com.twitter.algebird.{Max, Tuple5Semigroup}
1313
import org.apache.spark.broadcast.Broadcast
1414
import org.apache.spark.sql.functions.{col, lit}
15-
import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession}
15+
import org.apache.spark.sql.{DataFrame, Dataset, SparkSession}
1616
import org.apache.spark.storage.StorageLevel
1717

1818
import scala.util.Try
@@ -160,8 +160,8 @@ object MatchingSolverDualObjectiveFunction extends DualPrimalObjectiveLoader {
160160
*/
161161
def loadData(inputPaths: InputPaths)(implicit spark: SparkSession): (Dataset[MatchingData], BSV[Double]) = {
162162
import spark.implicits._
163-
val budget = IOUtility.readDataFrame(inputPaths.vectorBPath, inputPaths.format)
164-
.map { case Row(_c0: Number, _c1: Number) => (_c0.intValue(), _c1.doubleValue()) }
163+
val budget = IOUtility.readDataFrame(inputPaths.vectorBPath, inputPaths.format).as[BudgetData]
164+
.map { budgetRecord => (budgetRecord.itemId, budgetRecord.budget) }
165165
.collect
166166

167167
val itemIds = budget.toMap.keySet

dualip/src/main/scala/com/linkedin/dualip/problem/MultipleMatchingSolver.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.linkedin.dualip.problem
22

33
import breeze.linalg.{SparseVector => BSV}
4-
import com.linkedin.dualip.data.MultipleMatchingData
4+
import com.linkedin.dualip.data.{MultipleMatchingBudgetData, MultipleMatchingData}
55
import com.linkedin.dualip.objective.distributedobjective.DistributedRegularizedObjective
66
import com.linkedin.dualip.objective.{DualPrimalObjective, DualPrimalObjectiveLoader, PartialPrimalStats}
77
import com.linkedin.dualip.projection.{BoxCutProjection, GreedyProjection, SimplexProjection, UnitBoxProjection}
@@ -146,8 +146,8 @@ object MultipleMatchingSolverDualObjectiveFunction extends DualPrimalObjectiveLo
146146
// constraintIndex: index for the constraint; for a multiple-matching problem with three matching constraints per
147147
// entity, this column may assume values 0, 1 and 2
148148
// budgetValue: value of the budget
149-
val budgetDF = IOUtility.readDataFrame(inputPaths.vectorBPath, inputPaths.format)
150-
.toDF("entityIndex", "constraintIndex", "budgetValue")
149+
val budgetDF = IOUtility.readDataFrame(inputPaths.vectorBPath, inputPaths.format).as[MultipleMatchingBudgetData]
150+
.toDF()
151151

152152
val matchingConstraintsPerIndex = budgetDF.select("constraintIndex").distinct().count().toInt
153153
val reindexBudgetDF = budgetDF

version.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
version=3.0.*
1+
version=4.0.*
22

0 commit comments

Comments
 (0)