From ea6cf3cab975e1e0423a20e5dad34e3db0b14c1f Mon Sep 17 00:00:00 2001 From: Sam Al-Sapti Date: Mon, 1 May 2023 13:36:56 +0200 Subject: [PATCH] Refactor Matchmaker to take p_cases and t_exps (OMatrix) --- src/gale_shapley.mpc | 115 +++++++++++++++++++++---------------------- 1 file changed, 56 insertions(+), 59 deletions(-) diff --git a/src/gale_shapley.mpc b/src/gale_shapley.mpc index 31613f8..45682a2 100644 --- a/src/gale_shapley.mpc +++ b/src/gale_shapley.mpc @@ -12,60 +12,36 @@ from Compiler.gs import OMatrix, OMatrixRow, OStack class Matchmaker: """ - Makes self.f_ranks and self.m_prefs as instances of OMatrix - We can call them p_cases (patient cases) and t_exps (therapist experience) + Based on Matchmaker from Compiler/gs.py in MP-SPDZ, copyright (c) 2023, + Commonwealth Scientific and Industrial Research Organisation (CSIRO) + ABN 41 687 119 230, published under the BSD 3-Clause Licence """ - def init_easy(self): - self.m_prefs = OMatrix(self.N, self.M, oram_type=self.oram_type, - int_type=self.int_type) + def engage(self, patient, therapist, for_real): + self.wives.access(patient, therapist, for_real) + self.husbands.access(therapist, patient, for_real) - @for_range(self.N) - def f(i): - time() - types.cint(i).print_reg('mpre') + def dump(self, patient, therapist, for_real): + self.wives.delete(patient, for_real) + self.husbands.delete(therapist, for_real) + self.unengaged.append(patient, for_real) - @for_range(self.M) - def f(j): - self.m_prefs[i][j] = (i + j) % self.N - - self.f_ranks = OMatrix(self.N, oram_type=self.oram_type, - int_type=self.int_type) - - @for_range(self.N) - def f(i): - time() - types.cint(i).print_reg('fran') - - @for_range(self.M) - def f(j): - self.f_ranks[i][(j - i + self.N) % self.N] = j - - def engage(self, man, woman, for_real): - self.wives.access(man, woman, for_real) - self.husbands.access(woman, man, for_real) - - def dump(self, man, woman, for_real): - self.wives.delete(man, for_real) - self.husbands.delete(woman, for_real) - self.unengaged.append(man, for_real) - - def propose(self, man, woman, for_real): - (fiance,), free = self.husbands.read(woman) + def propose(self, patient, therapist, for_real): + (fiance,), free = self.husbands.read(therapist) engaged = 1 - free - rank_man = self.f_ranks[woman][man] - (rank_fiance,), worst_fiance = self.f_ranks[woman].read(engaged*fiance) + rank_man = self.t_exps[therapist][patient] + (rank_fiance,), worst_fiance = self.t_exps[therapist].read(engaged*fiance) leaving = self.int_type(rank_man) < self.int_type(rank_fiance) if self.M < self.N: leaving = 1 - (1 - leaving) * (1 - worst_fiance) print_str('woman: %s, man: %s, fiance: %s, worst fiance: %s, ', - *(x.reveal() for x in (woman, man, fiance, worst_fiance))) + *(x.reveal() for x in (therapist, patient, fiance, worst_fiance))) print_ln('rank man: %s, rank fiance: %s, engaged: %s, leaving: %s', *(x.reveal() for x in (rank_man, rank_fiance, engaged, leaving))) - self.dump(fiance, woman, engaged * leaving * for_real) - self.engage(man, woman, (1 - (engaged * (1 - leaving))) * for_real) - self.unengaged.append(man, engaged * (1 - leaving) * for_real) + self.dump(fiance, therapist, engaged * leaving * for_real) + self.engage(patient, therapist, (1 - (engaged * (1 - leaving))) * for_real) + self.unengaged.append(patient, engaged * (1 - leaving) * for_real) def match(self, n_loops=None): if n_loops is None or n_loops > self.N * self.M: @@ -95,17 +71,17 @@ class Matchmaker: def f(i=None): rounds.iadd(1) time() - man = self.unengaged.pop() - pref = self.int_type(propose[man]) + patient = self.unengaged.pop() + pref = self.int_type(propose[patient]) if self.M < self.N and n_loops is None: @if_((pref == self.M).reveal()) def f(): print_ln('run out of acceptable women') crash() - propose[man] = pref + 1 - self.propose(man, self.m_prefs[man][pref], True) + propose[patient] = pref + 1 + self.propose(patient, self.p_cases[patient][pref], True) print_ln('man: %s, pref: %s, left: %s', - *(x.reveal() for x in (man, pref, self.unengaged.size))) + *(x.reveal() for x in (patient, pref, self.unengaged.size))) return types.regint((self.unengaged.size > 0).reveal()) print_ln('%s rounds', rounds) @@ -114,15 +90,17 @@ class Matchmaker: types.cint(i).print_reg('wife') self.husbands[i].reveal().print_reg('husb') - def __init__(self, N, M=None, reverse=False, oram_type=OptimalORAM, - int_type=types.sint): + def __init__(self, N, p_cases, t_exps, M=1, reverse=False, + oram_type=OptimalORAM, int_type=types.sint): self.N = N - self.M = N if M is None else M - self.oram_type = oram_type + self.M = M + self.p_cases = p_cases + self.t_exps = t_exps self.reverse = reverse + self.oram_type = oram_type self.int_type = int_type self.basic_type = int_type.basic_type - print('match', self.oram_type) + print('match', N, M) """ CONSTANTS """ @@ -134,8 +112,9 @@ MATCHING_SIZE = 2 """ Assembling lists """ p_shares = Matrix(rows=PLAYERS, columns=MATCHING_SIZE, value_type=sint) +t_shares = Matrix(rows=PLAYERS, columns=MATCHING_SIZE, value_type=sint) -# Fill data from players into the matrix +# Fill data from players into the patient matrix # The matrix is ordered as m[row:player][col:share] @for_range(PLAYERS) def _(i): @@ -143,20 +122,38 @@ def _(i): def _(j): p_shares[i][j] = sint.get_input_from(i) +# Fill data from players into the therapist matrix +# The matrix is ordered as m[row:player][col:share] +@for_range(PLAYERS) +def _(i): + @for_range(MATCHING_SIZE) + def _(j): + t_shares[i][j] = sint.get_input_from(i) + @for_range(PLAYERS) def _(i): @for_range(MATCHING_SIZE) def _(j): print_ln('input from player %s: %s', i, p_shares[i][j].reveal()) +@for_range(PLAYERS) +def _(i): + @for_range(MATCHING_SIZE) + def _(j): + print_ln('input from player %s: %s', i, t_shares[i][j].reveal()) + # Add entire column together to reveal secret-shared input +p_cases = OMatrix(N=MATCHING_SIZE, M=1, oram_type=OptimalORAM, int_type=types.sint) +t_exps = OMatrix(N=MATCHING_SIZE, M=1, oram_type=OptimalORAM, int_type=types.sint) @for_range(MATCHING_SIZE) def _(i): - col = p_shares.get_column(i) - print_ln('res: %s', sum(col).reveal()) + p_val = sum(p_shares.get_column(i)) + p_cases[i][0] = p_val + t_val = sum(t_shares.get_column(i)) + t_exps[i][0] = t_val + print_ln('p_res: %s', p_val.reveal()) + print_ln('t_res: %s', t_val.reveal()) - -# mm = Matchmaker(50, oram_type=OptimalORAM) -# mm.init_easy() -# mm.match() +mm = Matchmaker(MATCHING_SIZE, p_cases, t_exps) +mm.match()