Skip to main content Link Menu Expand (external link) Document Search Copy Copied

Policy Customization

Table of contents

  1. What is a matching policy?
  2. Code example
  3. Defining your own policy
    1. Helpful methods and variables in openkpd.Simulation
    2. Helpful methods and variables in openkpd.SimulationAltruist
    3. Helpful methods and variables in openkpd.SimulationPair
  4. Linking OpenKPD to a custom policy

What is a matching policy?

OpenKPD allows users to write their own matching policies that are then dynamically compiled into simulation. Custom matching policies are written in Java. A matching policy takes as input the features of two adjacent vertices in a compatibility graph, and returns a numerical weight. That weight is then used by the integer program to match patients. The higher the weight for a given edge, the more the optimizer would benefit by including that weight in the cycle/chain packing that utlimately determines the final match for that round. See Equation 3.1 in John’s thesis for more details.

Code example

An example of a custom policy is given in the folder /custom/UNOSWEIGHTS.java in the release. Below is a copy of that policy, which implements the point system used by UNOS in the OPTN exchange

package custom;

import openkpd.Simulation;
import openkpd.SimulationAltruist;
import openkpd.SimulationPair;

public class UNOSWeights implements openkpd.CustomWeights {

	@Override
	public double computeWeight(SimulationAltruist donor, SimulationPair patient) {
		double UNOSweight = 100;
		UNOSweight += 0.07*patient.getIterations()*Simulation.DAYS_PER_MATCH;
		UNOSweight += (patient.HLA_A_cand.equals(donor.HLA_A_don) &&
				patient.HLA_B_cand.equals(donor.HLA_B_don) &&
				patient.HLA_DR_cand.equals(donor.HLA_DR_don)) ? 10 : 0;
		UNOSweight += patient.age_cand < 18 ? 100 : 0;
		switch (patient.getBloodTypePatient()) {
		case O:
			UNOSweight += 100;
			break;
		case B:
			UNOSweight += 50;
			break;
		case A:
			UNOSweight += 25;
			break;
		default:
			break;
		}
		switch (patient.getBloodTypeDonor()) {
		case AB:
			UNOSweight += 500;
			break;
		case A:
			UNOSweight += 250;
			break;
		case B:
			UNOSweight += 100;
			break;
		default:
			break;
		}
		if (patient.getPatientCPRA() == 100) {
			UNOSweight += 2000;
		} else if (patient.getPatientCPRA() == 99) {
			UNOSweight += 1500;
		} else if (patient.getPatientCPRA() == 98) {
			UNOSweight += 1250;
		} else if (patient.getPatientCPRA() == 97) {
			UNOSweight += 900;
		} else if (patient.getPatientCPRA() == 96) {
			UNOSweight += 700;
		} else if (patient.getPatientCPRA() == 95) {
			UNOSweight += 500;
		} else if (patient.getPatientCPRA() >= 90) {
			UNOSweight += 300;
		} else if (patient.getPatientCPRA() >= 85) {
			UNOSweight += 200;
		} else if (patient.getPatientCPRA() >= 80) {
			UNOSweight += 125;
		} else if (patient.getPatientCPRA() >= 75) {
			UNOSweight += 75;
		} else if (patient.getPatientCPRA() >= 70) {
			UNOSweight += 50;
		} else if (patient.getPatientCPRA() >= 60) {
			UNOSweight += 25;
		} else if (patient.getPatientCPRA() >= 50) {
			UNOSweight += 20;
		} else if (patient.getPatientCPRA() >= 40) {
			UNOSweight += 15;
		} else if (patient.getPatientCPRA() >= 30) {
			UNOSweight += 10;
		} else if (patient.getPatientCPRA() >= 20) {
			UNOSweight += 5;
		}
		return UNOSweight;
	}

Defining your own policy

To define your own policy, create a new .java file containing a class definition. Recall that the name of the class must match the file name, and the class must be placed in a package that shares a name with the file’s parent directory. In the code example above, we place the file in the folder /custom and name the file UNOSWeights.java.

In order to implement a valid OpenKPD policy, the class definition must begin with the lines

package <package_name>

import openkpd.Simulation;
import openkpd.SimulationAltruist;
import openkpd.SimulationPair;

public class <class_name> implements openkpd.CustomWeights {

	@Override
	public double computeWeight(SimulationAltruist donor, SimulationPair patient) {

The method computeWeight is the pricipal one to be filled in, and retuns a double-valued edge weight between any given set of adjacaent vertices. As the donor of the “donating” vertex and the patient of the “receiving” vertex are the only ones necessary to compute most notions of compatibility, OpenKPD automatically casts the donating vertex to be an altruistic donor, if it is not one already. This way, users do not have to worry about whether or not the donating vertex is an altruist or a patient-donor pair.

With the import statements for openkpd.Simulation, openkpd.SimulationAltruist, and openkpd.SimulationPair, users have access to all public variables and methods within those files. We outline these below:

Helpful methods and variables in openkpd.Simulation

Public Variable/MethodDescription
Simulation.DAYS_PER_MATCHCorresponds to the value DAYS_PER_MATCH set in the configuration file.
Simulation.DEATHCorresponds the value EXPIRY set in the configuration file.
Simulation.PATIENCECorresponds to the value PATIENCE in the configuration file
Simulation.RENEGECorresponds to the value RENEGE in the configuration file
Simulation.EXPECTED_PAIRSCorresponds to the value EXPECTED_PAIRS in the configuration file
Simulation.EXPECTED_ALTRUISTSCorresponds to the value EXPECTED_ALTRUISTS in the configuration file
Simulation.CHAIN_CAPCorresponds to the value CHAIN_CAP in the configuration file
Simulation.CYCLE_CAPCorresponds to the value CYCLE_CAP in the configuration file
Simulation.LKDPI(SimulationPair p, SimulationAltruist m)Computes the quality of a transplant from SimulationALtruist m to the patient of a SimulationPair p using the Living Kidney Donor Profile Index

Helpful methods and variables in openkpd.SimulationAltruist

We consider a SimulationAltruist donor (as in the method description for computeWeight).

Public Variable/MethodDescription
donor.age_donCorresponds to AGE_MATCH in Numerical Features
donor.egfrCorresponds to EGFR_MATCH in Numerical Features
donor.bmi_donCorresponds to BMI_MATCH in Numerical Features
donor.bp_sytolicCorresponds to BP_SYSTOLIC_MATCH in Numerical Features
donor.weight_donCorresponds to WEIGHT_MATCH in Numerical Features
donor.isAfricanAmericanCorresponds to AFRICAN_AMERICAN_MATCH in Categorical and Boolean Features
donor.isCigaretteUserCorresponds to HCU_MATCH in Categorical and Boolean Features
donor.isAfricanAmericanCorresponds to AFRICAN_AMERICAN_MATCH in Categorical and Boolean Features
donor.isDonorMaleCorresponds to SEX_MATCH in Categorical and Boolean Features
donor.HLA_A_donCorresponds to MA1 and MA2 in Categorical and Boolean Features
donor.HLA_B_donCorresponds to MB1 and MB2 in Categorical and Boolean Features
donor.HLA_DR_donCorresponds to MDR1 and MDR2 in Categorical and Boolean Features
donor.bloodTypeDonorCorresponds to ABO_MATCH in Categorical and Boolean Features. This is an enum – see BloodType.java for its definition

Helpful methods and variables in openkpd.SimulationPair

We consider a SimulationPair patient (as in the method description for computeWeight).

Public Variable/MethodDescription
patient.age_candCorresponds to AGE_CAND in Numerical Features
patient.weight_candCorresponds to WEIGHT_CAND in Numerical Features
patient.patientCPRACorresponds to CPRA_AT_MATCH_RUN in Numerical Features
patient.getIterations()Returns the number of match iterations the patient has been in the pool
patient.getPairs()Returns the number of patient-donor pairs in the pool when this patient entered the exchange
patient.getAlts()Returns the number of altruists in the pool when this patient entered the exchange
patient.HLA_A_candCorresponds to CA1 and CA2 in Categorical and Boolean Features
patient.HLA_B_candCorresponds to CB1 and CB2 in Categorical and Boolean Features
patient.HLA_DR_candCorresponds to CDR1 and CDR2 in Categorical and Boolean Features
patient.bloodTypePatientCorresponds to ABO_CAND in Categorical and Boolean Features. This is an enum – see BloodType.java for its definition

Linking OpenKPD to a custom policy

Once a custom policy has been written, it can be linked to OpenKPD by means of the configuration file. This is done through the variables CUSTOM_WEIGHTS_PATH and CUSTOM_WEIGHTS_CLASSNAME. Given a <package_name> and <class_name>, we should set CUSTOM_WEIGHTS_CLASSNAME to be <package_name>.<class_name> and CUSTOM_WEIGHTS_PATH to be the path /.../<package_name>/<class_name>.java to the custom weight file.