tweak cgi html form with TODOs

This commit is contained in:
Thomas (Tom) C. Gorordo 2025-04-25 17:31:03 -07:00
parent 5da4a21a3f
commit 6d9d8978cf
Signed by: tgorordo
GPG key ID: 0CBED22BB0D94490
4 changed files with 65 additions and 50 deletions

View file

@ -144,56 +144,8 @@ def check_stable(*args, **kwargs):
return not check_unstable(*args, **kwargs) return not check_unstable(*args, **kwargs)
def deferred_acceptance(applicant_rankings, reviewer_rankings): from .brute import *
"""Find the Gale-Shapley deferred-acceptance stable matching for preferences A, R.""" from .def_acc import *
reviewer_rankings = reviewer_rankings.rename(
{reviewer_rankings.columns[0]: "applicant"}
)
app_prefs = rank_to_pref(applicant_rankings)
offers = app_prefs.transpose(
include_header=True,
header_name="applicant",
column_names=["pref" + str(i + 1) for i in range(app_prefs.width)],
).with_columns(pl.coalesce(pl.all().exclude("applicant")).alias("offer"))
# offers = pl.concat(pl.align_frames(offers, reviewer_rankings, on="applicant"), how="horizontal")
offers = pl.concat([offers, reviewer_rankings], how="align_left")
match = pl.DataFrame(
{
r: offers.select(pl.col("applicant", "offer").sort_by(r))
.select(
pl.when(pl.col("offer").eq(r)).then(pl.col("applicant")).otherwise(None)
)
.select(pl.all().fill_null(strategy="backward").first())
.to_series()
for r in reviewer_rankings.columns[1:]
}
) # .select(pl.all().fill_null(strategy="backward").first())
# while check_unstable(match, applicant_rankings, reviewer_rankings):
while match.select(pl.any_horizontal(pl.all().has_nulls())).item():
# TODO null applicant preferences that rejected
rejected_applicants = offers.select(
pl.col("applicant").is_in(match.row(0)).alias("matched")
)
return match
offers = offers.with_columns(pl.col("pref"))
offers = offers.with_columns(
pl.coalesce(
# TODO: select prefn columns using a regex
).alias("offer")
)
# TODO update match
# else if stable
return match
def main() -> None: def main() -> None:

3
src/carousel/brute.py Normal file
View file

@ -0,0 +1,3 @@
def brute(applicant_rankings, reviewer_rankings):
"""Brute force search for stable matches."""
pass

50
src/carousel/def_acc.py Normal file
View file

@ -0,0 +1,50 @@
def deferred_acceptance(applicant_rankings, reviewer_rankings):
"""Find Gale-Shapley deferred-acceptance stable matchings for preferences A, R."""
reviewer_rankings = reviewer_rankings.rename(
{reviewer_rankings.columns[0]: "applicant"}
)
app_prefs = rank_to_pref(applicant_rankings)
offers = app_prefs.transpose(
include_header=True,
header_name="applicant",
column_names=["pref" + str(i + 1) for i in range(app_prefs.width)],
).with_columns(pl.coalesce(pl.all().exclude("applicant")).alias("offer"))
# offers = pl.concat(pl.align_frames(offers, reviewer_rankings, on="applicant"), how="horizontal")
offers = pl.concat([offers, reviewer_rankings], how="align_left")
match = pl.DataFrame(
{
r: offers.select(pl.col("applicant", "offer").sort_by(r))
.select(
pl.when(pl.col("offer").eq(r)).then(pl.col("applicant")).otherwise(None)
)
.select(pl.all().fill_null(strategy="backward").first())
.to_series()
for r in reviewer_rankings.columns[1:]
}
) # .select(pl.all().fill_null(strategy="backward").first())
# while check_unstable(match, applicant_rankings, reviewer_rankings):
while match.select(pl.any_horizontal(pl.all().has_nulls())).item():
# TODO null applicant preferences that rejected
rejected_applicants = offers.select(
pl.col("applicant").is_in(match.row(0)).alias("matched")
)
return match
offers = offers.with_columns(pl.col("pref"))
offers = offers.with_columns(
pl.coalesce(
# TODO: select prefn columns using a regex
).alias("offer")
)
# TODO update match
# else if stable
return match

View file

@ -400,7 +400,13 @@
<h3>Tabular Input</h3> <h3>Tabular Input</h3>
You can enter tables of preferences directly in the first tab of the form above. You can enter tables of preferences directly in the first tab of the form above.
TODO
<h4>Example:</h4> <h4>Example:</h4>
Suppose we want to figure out a Grad TA-to-Class assignment. Graduate students will be our "Applicants"
- each one will be assigned a class to TA -, and classes will be our "Reviewers" - taking a quota of needed TAs.
TODO
<h3>File Upload</h3> <h3>File Upload</h3>
@ -411,8 +417,12 @@
<h4>Excel</h4> <h4>Excel</h4>
TODO
<h4>CSV</h4> <h4>CSV</h4>
TODO
</details> </details>
</div> </div>
</form> </form>