**Federal Motor Carrier Safety Administration (FMCSA)**

**MatchWare Applications for**

**The New Motor Carrier Management**

**Information System**

**(New MCMIS)**

Design Document

**POR-02-7385 V1.0**

December 2002

Baseline Version

*Prepared for:*

![](media/image1.png){width="1.45625in" height="0.7284722222222222in"}

*US Department of Transportation*

*Federal Motor Carrier Safety Administration*

*400 Seventh Street, SW*

*Washington, DC 20590*

*Prepared by:*

![](media/image2.wmf){width="0.5833333333333334in"
height="0.7555555555555555in"}

*The Johns Hopkins University*

*Applied Physics Laboratory*

*11100 Johns Hopkins Road*

*Laurel, MD 20723-6099*

> ***Note***
>
> *The Motor Carrier Safety Improvement Act was signed into law on
> December 9, 1999. This act established a new Federal Motor Carrier
> Safety Administration (FMCSA) within the US Department of
> Transportation (DOT), effective January 1, 2000. Prior to that, the
> motor carrier and highway safety program was administered under the
> Federal Highway Administration (FHWA).*
>
> The mission of the FMCSA is to improve truck and commercial passenger
> carrier safety on our nation's highways through information
> technology, targeted enforcement, research and technology, outreach,
> and partnerships. The FMCSA manages the ITS/CVO Program, a voluntary
> effort involving public and private partnerships that uses information
> systems, innovative technologies, and business practice reengineering
> to improve safety, simplify government administrative systems, and
> provide savings to states and motor carriers. The FMCSA works closely
> with the FHWA's ITS Joint Program Office (JPO) to ensure the
> integration and interoperability of ITS/CVO systems with the national
> ITS program.

Baseline Issue

This is a final baseline document describing an as-built, as-delivered
system. There are no updates planned for this document. Documentation
describing future versions of the system will be assigned different
titles/version numbers as required.

This document is disseminated in the interest of information exchange.
The Johns Hopkins University Applied Physics Laboratory (JHU/APL)
assumes no liability for its contents or use thereof. This report does
not constitute a standard, specification, or regulation. JHU/APL does
not endorse products or manufacturers. Trade and manufacturer's names
appear in this report only because they are considered essential to the
object of this document.

Note: This document and other CVISN-related documentation are available
for review and downloading by the ITS/CVO community from the CVISN site
on the World Wide Web. All updates to this document will be maintained
and published on that site; hardcopies of future versions will not
normally be distributed. The URL for the site is
<http://www.jhuapl.edu/cvisn/>.

Review and comments to this document are welcome. Please send comments
to:

> Pankaj R. Karnik
>
> The Johns Hopkins University Applied Physics Laboratory
>
> 11100 Johns Hopkins Road
>
> Laurel, MD 20723
>
> Phone: 240-228-7815
>
> Fax: 240-228-5928
>
> E-Mail: <Pankaj.Karnik@jhuapl.edu>

**MatchWare Applications for New MCMIS**

**Table of Contents**

Page

[1. Introduction 1--1](#introduction)

[2. MatchWare Applications for New MCMIS
2--1](#matchware-applications-for-new-mcmis)

[2.1 Match Handler Program 2--2](#match-handler-program)

[2.1.1 Search and Match Services for New MCMIS
2--2](#search-and-match-services-for-new-mcmis)

[2.1.2 Standardization Services for New MCMIS
2--3](#standardization-services-for-new-mcmis)

[2.2 Match Handler PL/SQL 2--3](#match-handler-plsql)

[2.3 MatchWare Services API 2--4](#matchware-services-api)

[3. Strategy for Using MatchWare 3--1](#strategy-for-using-matchware)

[3.1 Standardization Services 3--1](#standardization-services)

[3.2 Matching Services 3--2](#matching-services)

[3.3 MatchWare Services API Reference Tables
3--3](#matchware-services-api-reference-tables)

[3.4 Searching Strategy 3--3](#searching-strategy)

[3.5 Matching after Searching 3--6](#matching-after-searching)

[3.6 Scores and Results 3--7](#scores-and-results)

[4. Carrier Search and Match Algorithm
4--1](#carrier-search-and-match-algorithm)

[4.1 FMCSA Business Rules 4--1](#fmcsa-business-rules)

[4.1.1 Partial Information Used for Establishing Identity
4--1](#partial-information-used-for-establishing-identity)

[4.1.2 Intrastate Carriers 4--2](#intrastate-carriers)

[4.1.3 Inactive Carriers 4--2](#inactive-carriers)

[4.1.4 Queries with USDOT or ICC Number
4--2](#queries-with-usdot-or-icc-number)

[4.2 Impact on the Carrier Search and Match Algorithm
4--3](#impact-on-the-carrier-search-and-match-algorithm)

[5. MatchWare / Integrity Configuration Files
5--1](#matchware-integrity-configuration-files)

[Appendix A. MatchWare Services API Reference Tables
A--1](#matchware-services-api-reference-tables-1)

[Appendix B. MatchWare Configurations and Settings
B--1](#matchware-configurations-and-settings)

[Appendix C. FMCSA Rules for Declaring Matches
C--1](#fmcsa-rules-for-declaring-matches)

[Appendix D. Carrier Search and Match Algorithm
D--1](#carrier-search-and-match-algorithm-1)

[Appendix E. Match Handler for New MCMIS
E--1](#match-handler-for-new-mcmis)

[E.1 Match Handler E--3](#match-handler)

[E.2 Match Handler Architecture E--3](#match-handler-architecture)

[E.3 Match Handler Program Design E--5](#match-handler-program-design)

[E.4 Match Handler Database Setup E--5](#match-handler-database-setup)

[E.5 Match Handler Program Operation and Administration
E--6](#match-handler-program-operation-and-administration)

[Appendix F. MatchWare Applications Distribution CD
F--1](#matchware-applications-distribution-cd)

[F.1 MatchWare Applications for New MCMIS CD
F--3](#matchware-applications-for-new-mcmis-cd)

[F.2 Call Hierarchy and Cross Reference
F--3](#call-hierarchy-and-cross-reference)

[Appendix G. Source Code Description G--1](#source-code-description)

[G.1 Introduction G--3](#introduction-1)

[G.2 Directory Structure G--3](#directory-structure)

[G.3 Module Function Descriptions G--4](#module-function-descriptions)

[Appendix H. MatchWare Services API H--1](#matchware-services-api-1)

[H.1 MatchWare H--3](#matchware)

[H.2 MatchWare Services API Class Descriptions
H--4](#matchware-services-api-class-descriptions)

[Appendix I. Carrier Search and Match Algorithm Adaptation
I--1](#carrier-search-and-match-algorithm-adaptation)

[Appendix J. Evaluation of Integrity Real Time for C
J--1](#evaluation-of-integrity-real-time-for-c)

[J.1 Introduction J--1](#introduction-2)

[J.2 The Evaluation Criteria: J--1](#the-evaluation-criteria)

[J.3 The Evaluation J--1](#the-evaluation)

[J.4 Conclusions J--1](#conclusions)

[Appendix K. References K--1](#references)

# Introduction

The Johns Hopkins University Applied Physics Laboratory (JHU/APL) has
developed software applications to be used by the New Motor Carrier
Management Information System (New MCMIS) being developed for the
Federal Motor Carrier Safety Administration (FMCSA). The New MCMIS is
the next generation carrier safety information system, which was derived
from the mainframe-based legacy MCMIS. Those software applications used
for carrier identification make use of the standardization and
probabilistic string comparison capabilities of the commercial software
product MatchWare™ developed by MatchWare Technologies Incorporated.

Carrier Identification is the process of determining or confirming the
USDOT number of a record, (carrier, shipper or other entity) provided to
the New MCMIS application depending on how well information on the
record agrees with the information stored in the New MCMIS database. The
New MCMIS system uses MatchWare-based applications as part of
Registration, Crash Report and Inspection Report processing. Proper
carrier identification helps prevent duplicate records from being
created in the New MCMIS database when used in the Carrier Registration
process. For Crash and Inspection report processing, proper carrier
identification ensures that these reports are assigned to the correct
USDOT number and helps maintain the accuracy of safety data in the New
MCMIS database.

The benefits of using applications based on MatchWare for carrier
identification are improved accuracy resulting in higher quality
matching results and better overall data quality in the New MCMIS
database.

MatchWare-based applications for New MCMIS were developed using
Microsoft Visual C++ V6.0 with MatchWare Callable Libraries Version 4.1.
Vality Technologies Inc. acquired MatchWare Technologies Inc. in July
1999, and replaced MatchWare with a new product referred to as
*Integrity*. JHU/APL tested these applications using the replacement
libraries, Integrity Real Time for C Version 3.11.in December 2001.
Extensive tests confirmed that all carrier-matching applications
developed by JHU/APL, produced identical results when built with the new
*Integrity* libraries. All carrier matching software delivered to FMCSA
for the New MCMIS system was built with the Integrity Real Time for C
Version 3.11 libraries; Oracle Pro\*C provides embedded SQL capability.
The Match Handler interface to New MCMIS is written in Oracle PL/SQL.

This document provides information and details about the design of the
MatchWare-based applications developed by JHU/APL for the New MCMIS
system. In this document, the term MatchWare also refers to the new
Integrity products. Appendix J provides details of the method used by
JHU/APL for evaluating Integrity Real Time for C as the replacement for
the MatchWare Callable Libraries.

This Page Intentionally Blank

# MatchWare Applications for New MCMIS

![](media/image3.wmf)The block diagram in Figure 2--1 shows the
relationships of the applications that use and provide MatchWare-based
services for the New MCMIS System.

Figure 2--1. Block Diagram of MatchWare\
Applications for New MCMIS

## Match Handler Program

The Match Handler Program shown in Figure 2--1 is a C++ program and is
the core application that provides MatchWare-based capability to the New
MCMIS System. The Match Handler Program provides Search and Match
services and Standardization services to the New MCMIS system. The
program is built using Microsoft Visual C/C+ Version 6.0, Oracle Pro\*C
version 8.1.6 and Integrity Real Time for C Version 3.11. Appendix E
contains details about the Match Handler program.

### Search and Match Services for New MCMIS

One service that the Match Handler Program provides the New MCMIS system
is to process a query related to the identity of a carrier to determine
or help an operator determine which of the following three conditions is
true:

1.  The information in the query matches exactly one carrier in the New
    MCMIS database. This is defined as a Confirmed Definite Match.

2.  The information in the query may or may not match one or more than
    one carrier in the New MCMIS database. This is defined as a
    Potential Match. A Potential Match is resolved either as a Confirmed
    Definite Match or a Definite Non Match by an operator.

3.  The information in the query does not match any carrier in the New
    MCMIS database. This is defined as a Definite Non Match.

Four data elements are used to establish the identity of a carrier.
These elements are USDOT Number, ICC Docket Number, full name and full
address. Each of these elements provides a way of defining a unique
component of the identity of a carrier and when used together, these
four elements provide a composite means of establishing the identity of
a carrier.

While the basic carrier identification query contains one name and one
address to find a match in the New MCMIS database, the Match Handler
program can process queries containing up to two names and two
addresses. The ability to process a query with one name and one address
forms the core capability of the MatchWare-based search and match engine
for New MCMIS. JHU/APL developed a technique to determine the identity
of a carrier when up to two names and two addresses are provided in the
query by performing just two search operations instead of four searches,
thereby reducing in half, the time that would normally be required to
process such queries.

The Match Handler Program requires complete name and address information
in the query to provide the best matching results. Higher matching speed
and accuracy are achieved if the correct USDOT number and/or ICC Docket
Number are provided in the query in addition to the required name and
address information.

When the Match Handler Program processes a query containing one name and
one address, it compares this information with up to two names (Legal
and Doing Business As-DBA) and two addresses (Street and Mailing) in the
New MCMIS database. The Match Handler program declares a confirmed
definite or potential match when the query name and address successfully
match any combination of name and address in the New MCMIS database. The
difference between a confirmed definite and a potential match is that a
confirmed definite match is declared when information in the query
matches the information from exactly one USDOT number in the New MCMIS
database. A definite non match is declared when no match is found in the
New MCMIS database, i.e., confirmed definite match or potential match is
not declared.

When a query contains more than one name and/or address, the Match
Handler Program processes the query as two distinct name and address
pairs; Legal Name with Street Address and DBA Name with Mailing Address.
If just one name and two addresses or one address and two names are
provided in a query, the Match Handler Program repeats the available
name or address to complete the missing data element. The aggregate
result for the query is declared by combining the individual results
obtained from the two distinct pairs. Appendix I provide details about
the method used to combine information and declare results.

New MCMIS PL/SQL applications invoke the Match Handler Program for
search and match services through the two functions fnc_search_and match
and fnc_carrier_match in the pkg_match_handler package, respectively.

### Standardization Services for New MCMIS

The Match Handler Program also provides standardization services to the
New MCMIS system. This service allows the New MCMIS system to convert
the name and address information for carriers in the New MCMIS database
into their corresponding MatchWare keys. These keys are used as indexes
for searching or comparing carrier records and are stored in the
MatchWare Services Reference Tables in the New MCMIS database.

New MCMIS PL/SQL applications invoke the Match Handler Program for
standardization services through the function fnc_standardize in the
pkg_match_handler package.

## Match Handler PL/SQL

The interface for New MCMIS PL/SQL programs to the Match Handler Program
is through the Match Handler PL/SQL. Match Handler PL/SQL provides a way
for the C++ MatchWare programs and the New MCMIS PL/SQL programs to
interact with each other. Appendix F provides details about the Match
Handler PL/SQL.

## MatchWare Services API

The MatchWare Services API provides the building blocks used by the
Match Handler Program for providing MatchWare-based capability to the
New MCMIS System. The MatchWare services API was developed using an
Object Oriented paradigm. A software developer using the MatchWare
Services API is not required to know how to use low level MatchWare
library function calls and can design applications based on high level
objects and classes suitable for carrier identification applications.
Appendix E provides details of the Match Handler Program and the
MatchWare Services API.

# Strategy for Using MatchWare

MatchWare provides two services: *Standardization* and *Matching* that
are useful for carrier identification applications. These services are
available via a set of C function calls through MatchWare Callable
Libraries. The strategy used by the MatchWare Services API for utilizing
MatchWare for a carrier identification query involves performing a
search for likely candidates based on information in the query followed
by a matching operation for all candidates found, to determine if any of
those candidates match the information in the query. MatchWare provides
the means for performing targeted searches and intelligent probabilistic
matching through its Standardization and Matching Services. Details of
capabilities of MatchWare discussed in this section are available in
Reference 3. Specific details of the MatchWare configurations used by
the MatchWare Services API are provided in later sections of this
document.

## Standardization Services

Searching a database for records based on names or addresses is very
difficult for a variety of reasons. The formats of the information in
the database and query may be different and the form of words or their
spelling may not be the same. Further, a name or address search using a
character string is very slow and commonly involves looking up every
record in the database before selecting only those records that meet the
desired criteria. MatchWare provides standardization services by which
names and addresses are broken into distinct components. These
standardized components provide an efficient means of searching the
database by using names and address information.

In the case of Name Standardization, MatchWare removes commonly used
words in business names like "The", "Of", "Inc", "Company", etc., that
do not provide any additional information to establish the identity by
name. MatchWare then converts the first five significant words of the
remaining words of the name to their root form to eliminate variations
in spelling or usage. Words like Robert, Robbie, Bob, Rob would all be
converted to the same root word by this process. Finally, MatchWare
provides the capability of converting these tokens to SOUNDEX, REVERSE
SOUNDEX and NYSIIS forms, which are based on the way a word sounds.
These can compensate for spelling errors in a query when searching.

The SOUNDEX algorithm codes tokens phonetically by reducing them to the
first letter and up to three digits, where each digit is one of six
consonant sounds. This reduces matching problems from different forms of
spellings for the same word. The REVERSE SOUNDEX algorithm codes tokens
phonetically by reducing them to the last letter and up to three digits,
where each digit is one of six consonant sounds. This reduces matching
problems from spelling errors where the first few letters spelt
incorrectly could result in a matching error. The NYSIIS algorithm
converts a name to a phonetic coding of up to six characters. This
reduces matching problems from different spellings using a completely
phonetic version of the word using letters. The NYSIIS form is better
for matching names than just a SOUNDEX or REVERSE SOUNDEX form of the
same word.

For Address Standardization, MatchWare provides very well defined
components for U.S. and Canadian addresses. These components include
details such as "Unit Value" (Number) and "Unit Type" (P.O. Box), "House
Number" and "Street Name", "City" and "Zip Code". Words in all addresses
are converted to standard forms to eliminate differences due to
abbreviation and usage (P.O. Box / PO BOX, ST PAUL / SAINT PAUL, Street
/ St etc) and then if necessary SOUNDEX or REVERSE SOUNDEX conversions
are also available to eliminate matching problems due to spelling errors
or variations in the spelling.

Standardization Services from MatchWare also provide the means of
converting name and address information to distinct fields or MatchWare
Keys. The Match Handler Program uses these keys in two ways: some keys
are used to index records in the New MCMIS database and are useful for
searching, while others keys are used to compare records when matching.
Commonly searched name and address component columns in the database are
indexed, greatly reducing the time required to locate records based on
names and address.

Details of standardization capabilities of MatchWare are available in
Reference 3. Specific details of the MatchWare standardization used by
the MatchWare Services API are provided in later sections of this
document.

## Matching Services

MatchWare provides probabilistic string comparison or more simply
"Matching" services, which form the basis for the results provided by
the Match Handler Program's search and match functionality. MatchWare
provides a high performance matching engine which can quickly compare a
given character string representing a query, with a large number of
candidate strings representing possible solutions very quickly. Once
matching is completed, the Match Handler Program provides a list of all
candidate strings ranked from best to worst, and assigns a score to each
candidate that tells how well the candidate matches the query. MatchWare
provides means of customizing the rules for comparing character strings.

A common problem when comparing names is that the order of words is
frequently changed. When this happens, name comparisons fail or get
complicated because of the changed word order. MatchWare solves this
problem by tokenizing the words of the carrier name in the query as well
as in each candidate and then comparing the tokens in the order that
results in the highest name match score.

Another feature of MatchWare is the capability to use different criteria
for matching different parts of the character string. Using the
capabilities of MatchWare, all four components of the query, the USDOT
Number, ICC Docket Number, name and address are compared with the
components of all candidate records in a single operation. This results
in a very quick and accurate matching operation.

## MatchWare Services API Reference Tables

In order to use the Match Handler Program to process carrier
identification queries against the New MCMIS database, standardized
components known as keys must be created for all records in the New
MCMIS database. These keys must be stored in the MatchWare Services API
Reference Tables so that they can be used for searching and matching
operations.

The MatchWare Services API Reference Tables must be updated and
maintained correctly in order to ensure that the results declared by the
Match Handler Program are correct and synchronized with the New MCMIS
Carrier Table. Incorrect, duplicate or missing entries in the MatchWare
Services API Reference Tables will cause the results declared by the
Match Handler Program to be wrong, misleading or confusing. For best
results, these reference tables should not contain records that are
marked as "Known Duplicates" or "Secondary" in the New MCMIS Carrier
Table nor records that contain blank name or address fields.

## Searching Strategy 

MatchWare Standardization Services parse carrier names and addresses
into MatchWare keys, some of which become indexed keys in the reference
database for performing searches. These keys provide the capability to
select a wide range of those records from the reference tables that are
most likely to yield the best match for a given query. Keys like NYSIIS1
and NYSIIS2 for the carrier name and REVERSE STREET SOUNDEX and CITY
SOUNDEX for carrier addresses help compensate for spelling errors and
variations since they are based on the way a word *sounds* instead of
its spelling.

The MatchWare Services API employs an additional searching strategy,
which is to perform the searches in stages using different keys at each
stage. Using different keys and multiple stages prevents an incorrect
piece of information in the query or reference database from skewing the
results as long as there is enough correct information to provide a
correct result. Keys used for a stage define just a small but critical
part of the full record and all records in the reference database that
match the key are selected during that search stage.

The idea is that if **all** records satisfying a critical search
criteria are selected from the reference tables during a search stage,
then the following statements are true:

1.  There is no record left in the database that satisfies the search
    criteria, and

```{=html}
<!-- -->
```
4.  It is possible that one or more of the records selected will meet
    all matching criteria for the given query.

Based on this concept, selection keys and search stages were selected
that would quickly and most effectively provide for the selection of
records most likely to result in a confirmed match. Keys for each stage
were kept mutually exclusive of others to avoid replication of searches.
Searches are conducted in stages that are likely to provide the most
accurate results most quickly. Every search stage database query is
followed by a match operation to determine if the result is a confirmed
definite match. If a confirmed definite match is not found, each
successive stage widens the scope of the database search and takes
longer to perform.

The search stages used are as follows:

1.  **USDOT Number:** The USDOT Number in a query is defined as a key in
    the MatchWare environment, exactly as it appears in the query
    without any processing by MatchWare. When the USDOT Number is
    provided and other pieces of information (ICC Number, name and
    address) on the query are correct, this search stage produces the
    quickest and most accurate results.

```{=html}
<!-- -->
```
5.  **ICC Docket Number:** The ICC Docket Number is also defined as a
    key in the MatchWare environment. When the USDOT Number is not
    provided or is incorrect and fails to produce a positive result, the
    ICC Number, with the correct name and address in the query, produces
    positive results as quickly and accurately as the USDOT Number.

6.  **Name Search:** When both USDOT Number and ICC Number fail to
    produce a positive identification, carrier name is the next most
    likely component that could result in a match. The keys used for
    name searches are the NYSIIS values of WORD1 and WORD2 from the
    carrier name, not WORD1 or WORD2 itself. While the NYSIIS1 and
    NYSIIS2 fields provide a means for performing an indexed search by
    name, the time required for such a search depends on how often a
    NYSIIS value occurs in the reference database. Commonly used names
    could occur in the reference database 50,000 times or more, which
    results in a very long search, while uncommon names result in very
    quick searches.

> The objective of the Name Search Stage is to select all records from
> the database that meet both, (union of) the NYSIIS1 and NYSIIS2 search
> criteria. This ensures that if the search fails, there are no records
> in the database that could possibly match the name in the query.
> However, there are certain thresholds of counts of NYSIIS1 and NYSIIS2
> beyond which searching records for the union of both NYSIIS1 and
> NYSIIS2 is impractical. To overcome this problem, this search stage is
> performed using the following search variations:

a.  NYSIIS1 union NYSIIS2 search if counts for both are low.

b.  NYSIIS1 search if the count for NYSIIS2 only is very high (e.g.Word2
    is "TRUCK")

c.  NYSIIS2 search if the count for NYSIIS1 only is very high (e.g.Word1
    is "JOHN'S")

d.  (NYSIIS1 and NYSIIS2) union (NYSIIS2 and NYSIIS1) searches if counts
    for both NYSIIS1 and NYSIIS2 are very high. The union of two Boolean
    conditions is used in this case to compensate for the possible
    switch of Position of NYSIIS1 and NYSIIS2 in the query or the
    reference database.

> The values of low and high counts were determined by analyzing the
> data in the reference tables. The low counts cover over 94% of the
> records in the reference database and take less than thirty seconds to
> complete. The high counts eliminate those searches that would take
> over a minute but in many cases up to five minutes to complete.

7.  **Address Search:** If the previous stages fail to produce a
    positive identification, it means that either information in the
    previous stages was missing or provided incorrectly. In such cases,
    address information could help correct searches led astray by
    misleading information in the USDOT, ICC and Name Stages. MatchWare
    standardization produces many keys for carrier address. In order to
    ensure that key based address searches are wide enough to cover all
    relevant records yet focused towards address information in the
    query, specific combinations of keys are used. The state component
    of an address by itself is a poor choice because of the high number
    of records per state in the New MCMIS database. Zip Code information
    in the New MCMIS database has been found to be outdated and
    therefore relying entirely on that key could cause misleading
    results. The keys found to provide the best overall results for the
    MatchWare Services API are a combination of REVERSE STREET SOUNDEX,
    CITY SOUNDEX and STATE when the address contains a street address or
    a UNITVALUE, CITY SOUNDEX and STATE when the address is a Post
    Office box or other container like Post Office Bag or Mail Box.
    REVERSE STREET SOUNDEX is selected because it picks up all streets
    ending in the same sound, to allow for variation in spellings for
    street names. Even though the MatchWare keys UNITVALUE and UNITTYPE
    are normally paired, UNITTYPE is not included in the second type of
    search because often, values that are used in the query and New
    MCMIS database for that component of the address are inconsistent
    with each other.

> Though address searches can be expensive in terms of processing time,
> they can provide excellent results because they ensure that all
> carrier records with a particular address defined by street, city and
> state or P.O. Box Number in a given state have been considered to
> establish the identity of a carrier.

8.  **Combined Name and Address search:** When all the previous four
    stages failed to produce a confirmed match, a combination of name
    and address is used as a last resort to obtain a result. The
    combination used is NYSIIS and STATE, using either 1) the NYSIIS key
    that was not used in the Name search stage or 2) the NYSIIS key from
    the name search stage with lowest count. This is the most expensive
    stage in terms of processing time; however, it ensures that all
    reasonable steps are taken to establish the identity of the carrier.

## Matching after Searching

As stated before, each search stage described above is followed by a
match operation to determine whether the records resulting from the
search result in a definite confirmed match. During each search stage
candidate records are selected from the MatchWare Services API Reference
Tables based on one component of the query. However, all four components
\--USDOT Number, ICC DOCKET Number, name and address -- are retrieved
for the candidate records from the reference tables.

The match operation for each stage compares all four components of each
candidate record with information in the query. For example, in the
USDOT stage, although records are selected from the reference database
based on just one component the USDOT number, the match operations
compare all four components -- USDOT Number, ICC DOCKET Number, name and
address. This process, known as blocking in MatchWare terminology,
provides a "degree of freedom" in selecting candidates during the search
stage but ensures full comparison while deciding which records from
among all the candidates match the information in the query.

Except for the USDOT Number and the ICC Docket Number, the keys used to
search for candidates are different from the keys used to match or
compare candidates with the information contained in the query. By their
definition, the USDOT Number and the ICC Docket Number are keys for
searching as well as critical information to confirm the identity of a
carrier.

For name searches, the NYSIIS values of WORD1 and WORD2 are ideal search
keys because they result in a larger number of carrier records with a
wide variation of forms of the same names to be retrieved by the search.
To compare the candidates found by the search with the name information
in the query, however, the standard form of WORD1, WORD2 ... WORD5 must
be used. This is because using NYSIIS1 and NYSIIS2 for matching will
produce the same results as the search. Using the actual WORD1 .. WORD5
keys will ensure that matching candidate name strings are close to the
original name string in the query. This is also the reason why the full
name must be provided in the query to ensure the best results from
MatchWare.

Keys used for address searches, REVERSE STREET SOUNDEX, CITY SOUNDEX and
STATE or UNIT VALUE, CITY SOUNDEX and STATE are ideal for retrieving the
most likely records based on address. However, to ensure that the
address on the records compare closely with the address on the query,
the keys used for matching are HOUSENUM, STREETNAME, UNIT TYPE, UNIT
VALUE, CITY, STATE and ZIPCODE. This ensures a closer match of the
candidate records with the query when the addresses are compared.

When using MatchWare, any search must be followed by a match operation
in order to utilize the capabilities of MatchWare in a meaningful way.
Without the match operation, a search using MatchWare keys alone would
be no better than and could be replaced by a database search using the
equivalent SOUNDEX function.

## Scores and Results

Upon completion of the search and match operation, MatchWare returns an
ordered list of all candidates ranked from best to worst with a score
assigned to each candidate. The score is based on rules and settings
specified in the MatchWare configuration files. MatchWare does not make
a determination as to whether or not a candidate is a definite match: it
just provides a score that is based on a comparison of the information
in the candidate record with the information in the query.

Each component of the candidate record, USDOT Number, ICC DOCKET Number,
name and address contributes to the combined score that MatchWare
assigns any candidate. Better matching between each component and the
equivalent information in the query results in a higher score for that
component; a mismatch results in a negative score. When a component is
missing in either the query or the candidate record, MatchWare assigns
no score to that component, thus reducing the maximum score assigned to
that candidate record. For output reporting, MatchWare only generates
the overall score for each candidate record, not the score associated
with each record component. Based on analysis conducted by JHU/APL, the
breakdown of maximum possible MatchWare scores for the current
configuration are as follows:

Table 3--1.\
MatchWare Scores by Component

  ----------------------------- ------------------ ----------------------
  Element                       Maximum\           Maximum\
                                Possible\          Deduction for\
                                Score              Disagreement

  USDOT Number                  2.00               -0.58

  ICC Docket Number             2.00               -0.58

  Name                          13.28              -13.28

  Address                       17.50              -10.04

  Total                         34.78              -24.48
  ----------------------------- ------------------ ----------------------

Based on the score assigned to a candidate record, the MatchWare
Services API interprets the result to determine whether the result of a
query is a confirmed definite match, potential match or definite non
match.

Table 3--2.\
Match Result Based on Score

  ------------------------- ---------------------------------------------
  Match Result              MatchWare Score Threshold

  Definite Match            23.00 -- Max Score

  Potential Match           11.00 -- 23.00

  No Match                  \<11.00
  ------------------------- ---------------------------------------------

This Page Intentionally Blank

# Carrier Search and Match Algorithm

Applications that use MatchWare depend on the total MatchWare score of a
candidate to declare a result. The total MatchWare score is based on the
degree to which all pieces of information in a candidate record agree
with corresponding pieces of information in the query. If the total
MatchWare score for any candidate is below the definite match threshold,
then normally, the result is not a definite match.

The FMCSA has provided a set of business rules that define how the Match
Handler Program should declare carrier identification results. Some of
these rules dictate that a candidate be declared a definite match based
on partial agreement of information, when the total MatchWare score for
that candidate could be below the definite match threshold. Other rules
require that candidates whose total MatchWare Score is above the
definite match threshold not be declared a definite match but a
potential match instead.

The Carrier Search and Match Algorithm used in the MatchWare Services
API has been developed with the objectives of using features of
MatchWare to provide accurate carrier identification capabilities to New
MCMIS and other FMCSA applications. The algorithm blends the MatchWare
approach of staged blocking and searching to establish the identity of
carriers with the FMCSA's business rules for declaring results. Search
stages used by the algorithm have been selected to provide an optimized
matching outcome while maintaining high speed query processing. In order
to comply with FMCSA requirements of using their business rules for
declaring results, JHU/APL has developed techniques for using the
capabilities of MatchWare while implementing those rules

This section provides details of the business rules defined by the FMCSA
for declaring matching results and their impact on Carrier Search and
Match Algorithm. Appendix D provides details of the Carrier Search and
Match Algorithm used by the Match Handler Program.

## FMCSA Business Rules

### Partial Information Used for Establishing Identity

For Crash and Inspection report processing, the FMCSA requires that a
candidate must be declared a definite match even when the total
MatchWare score is below the definite match threshold. FMCSA has defined
rules by which these declarations are to be made. According to these
rules, if two distinct elements in a candidate record agree with
information in the query, the candidate record can be declared a
confirmed definite match. The reason behind these rules is to address
the case when information in a query and in the New MCMIS database does
not completely agree for operational reasons. For example, the address
for a carrier may have changed and be reflected in the paperwork and the
side of the truck but not updated in the MCMIS database or vice versa.
In such cases, application of FMCSA business rules would allow for the
automated processing of Crash and Inspection reports instead of
requiring potential match resolution by a human operator.

A summary of the rules defined by the FMCSA for declaring definite
matches and their order of priority is provided in Table 4--1 below.
Appendix C contains the document provided by FMCSA defining these rules.

Table 4--3.\
FMCSA Rules for Confirming Matches\
Using Partial Information

  ------------ --------- --------- --------- -------------- ---------------
  Priority\    USDOT     ICC       Name      Address        Maximum\
  (Rule)                                                    Contribution
                                                            to\
                                                            Score

  1            Match     Match                              4.0

  2            Match               Match                    15.28

  3                      Match     Match                    19.50

  4            Match                         Match          15.28

  5                      Match               Match          19.50

  6                                Match     Match          30.78
  ------------ --------- --------- --------- -------------- ---------------

### Intrastate Carriers

When processing INTRASTATE Inspection reports, the directive provided by
the FMCSA is that an Intrastate Inspection report is never to be
classified a Potential Match. Rather, it must be declared a Confirmed
Definite Match or a Definite Non Match based on a successful match or
lack thereof to USDOT Number or ICC Docket Number, respectively.

### Inactive Carriers

Prior to December 2001, the FMCSA required MatchWare-based applications
developed by JHU/APL to change all Confirmed Definite Matches of
INACTIVE carrier records evaluated during Crash and Inspection Report
processing to Potential Matches. This was done to ensure those records
would be manually reviewed by an operator for final match resolution.

In December 2001, the FMCSA changed the requirement to support automated
declaration of INACTIVE carriers as Confirmed Definite Matches. This
automated declaration was permitted only when a given INACTIVE carrier
was the only candidate confirmed as a definite match and had the same
USDOT Number of ICC Docket Number specified in the query.

### Queries with USDOT or ICC Number

The FMCSA requires records containing a USDOT Number or ICC Docket
Number, which are evaluated during Crash or Inspection report
processing, be declared a Potential Match if a Confirmed Definite Match
can not be established, even when a MatchWare score would normally
indicate Definite Non Match status.

## Impact on the Carrier Search and Match Algorithm

Application of the business rules defined by the FMCSA could lead to
several problems:

1.  In all cases where either the Name or Address component is present
    yet excluded from consideration for the matching operation, the
    maximum MatchWare score for that report cannot reach the Definite
    Match Threshold. In addition, the MatchWare score will be further
    reduced if mismatches in other elements are encountered.

```{=html}
<!-- -->
```
9.  Applying these rules often results in conflicting confirmed matches
    due to the nature of the information provided on some types of
    queries. For example, in a particular query, the ICC Docket Number
    and name information could identify as a match, a record that is
    different when compared with the record that the USDOT Number and
    address information have identified as a match in New MCMIS
    database.

To solve the first problem, MatchWare applications for New MCMIS were
designed to integrate the FMCSA rules with MatchWare processing. When
the FMCSA rules are applied to declare a Confirmed Definite Match based
on partial information, the candidate that is declared as the Definite
Match does not typically get a high enough MatchWare score to use the
normal thresholds for declaring the result. JHU/APL has developed a
method by which the low scores that a candidate gets when the FMCSA
rules are applied can be mapped to normal MatchWare thresholds. This
Mapping of scores allows a single uniform scale by which results can be
declared regardless of whether the rules provided by the FMCSA are
applied.

To mediate the second problem, JHU/APL asked the FMCSA to provide
priority rules for breaking the tie and deadlock when the same query
resulted in a Confirmed Definite Match with two different records in the
New MCMIS database. See Table 4--1 above for the priority rules defined
by the FMCSA for declaring results based on partial information.
Appendix D provides details of the algorithm developed by JHU/APL.

Once the individual MatchWare component scores are determined, FMCSA
rules can be applied in terms of MatchWare scores. When rules are
applied, an inherently low score can be mapped to a normalized MatchWare
score. This provides a method by which a common threshold is used to
declare results when either standard MatchWare processing or FMCSA
business rules are used as a basis for processing a query. This is
critical because very often, a query could yield *several different*
results depending upon which method is applied. The algorithm used by
the MatchWare Services API derives the best possible results and then
decides the final outcome based on priorities defined by the FMCSA
rules. This method ensures that a complete search is conducted before
declaring a match instead of stopping at the first match, which might
not result in the correct carrier. FMCSA rules are applied whenever
applicable, when normal MatchWare processing does not result in a
confirmed match for a query.

This Page Intentionally Blank

# MatchWare / Integrity Configuration Files

MatchWare uses a set of configuration files for establishing the
MatchWare Standardization and Matching environment. In 1998, MatchWare
Technologies Inc., created customized configuration files for the FMCSA
MatchWare applications SAFETYNET10 and SAFETYNET 2000. Enhanced versions
of these files form the basis for the MatchWare configuration files used
for New MCMIS. JHU/APL has enhanced these files based on information
obtained from MatchWare Technologies Inc to correct problems with the
original files and to make them suitable for use with the larger name
and address fields required by the New MCMIS system.

Integrity, the replacement product for MatchWare, also uses a similar
but different set of configuration files for establishing its
Standardization and Matching environment. However, configuration files
originally created for MatchWare can also be used with Integrity.

During the development of the Match Handler Program for New MCMIS,
extensive testing was conducted to ensure that the enhanced
configuration files produce correct results when compared with the
results from the MatchWare applications for Legacy MCMIS. This testing
has also established that these customized configuration files produce
identical results when used with either the MatchWare Callable Libraries
or the Integrity Real Time for C libraries.

For the Match Handler Program, a dictionary file CMCOMBINED41. DCT
defines keys for the MatchWare environment. Information from the query
is first formatted into a 228 Character "Standardization Record" and
parsed into the MatchWare components, "Name", "Geocode" and "Place" by
the specification in the standardization file CMATCH41.STN. The three
components of the query, "Name", "Geocode" and "Place" are then
standardized and converted to keys for the MatchWare environment by the
standardizer. The dictionary file CMCOMBINED41.DCT and individual
pattern and classification files for "Name", (CMCOMPANY.PAT,
CMCOMPANY.CLS) "Geocode", (CMGEOCODE.PAT, CMGEOCODE.CLS) and "Place"
(CMPLACE.PAT, CMPLACE.CLS) define the MatchWare keys that will be
generated.

The rule file APLMATCH41.RUL defines a 563 character "Match Record" as
well as the rules for matching candidates drawn from the reference
database with the data in the query. One Match Record is built with keys
from the reference database for every candidate record selected during
the search. The stage is set for matching the candidates from the
reference database with the information in the query by loading all
"Match Records" into the MatchWare environment. MatchWare compares all
candidates with the query by comparing keys according to the rules in
the rule file. The score that is assigned by MatchWare to a particular
Match Record depends on the match quality as defined in the rule file.

Appendix B contains the Standardization, Dictionary and Rule Files used
to establish the MatchWare environment for the New MCMIS system.

This Page Intentionally Blank

########  MatchWare Services API Reference Tables

This Page Intentionally Blank

**[MatchWare Services API Reference Tables]{.underline}**

![](media/image4.png){width="6.997222222222222in" height="5.90625in"}

This Page Intentionally Blank

########  MatchWare Configurations and Settings 

This Page Intentionally Blank

**[Standardization File CMATCH41.STN]{.underline}**

;

; STANDARDIZE file Adapted from Scientex \[A\] : SEARCH.STN

; Is cmatch41.stn

; References cmcombined41.dct

;

RECORD 228

INTERACTIVE

TYPE ASCII

;

STANDARDIZE COMPANY (21-140)

PROCESSFILE COMPANY CMCOMPANY CMCOMBINED41

STANDARDIZE GEOCODE (141-190)

PROCESSFILE GEOCODE CMGEOCODE CMCOMBINED41

STANDARDIZE PLACE (191 25) (216 2) (218-227)

PROCESSFILE PLACE CMPLACE CMCOMBINED41

;STRIPLIST \"-()&/#\<\>;:\\\".\\\' \"

STRIPLIST \"\_-()&/#\<\>;:\\\".\\\\\' \"

SEPLIST \" \"

**[Dictionary File CMCOMBINED41.DCT]{.underline}**

\\FORMAT\\ SORT=N

;

; CID file match key

;

QN C 12 S; Query Number

US N 8 S; USDOT Number

CN C 120 S; Carrier Name

CA C 50 S; Carrier Address

CC C 25 S; Carrier City

CS C 2 S; Carrier State

CZ M 6 S; Carrier Zip /\*Type is mixed for Canadian Alpha Zips\*/

;CE M 3 S- 120 Carrier Zip Extension - which is not used - space holder

CE M 4 S; ZipCode Extension

IN C 1 S; Interstate Marker - Not Used

IC N 6 S; ICC Number

AS C 1 S; Activity Status

NT C 1 S; Name Type

AT C 1 S; Address Type

NW C 1 S; NWords - Number of words

W1 C 30 S; Company1 - Word 1 \"Manitoba\"

W2 C 30 S; Company2 - Word 2 \"Council\"

W3 C 30 S; Company3 - Word 3 \"Organic\"

W4 C 30 S; Company4 - Word 4 \"Vegetable\"

W5 C 30 S; Company5 - Word 5 \"Farmers\"

DV C 15 S; Div - Division or misc info

N1 C 8 S; NYSIIS1 - NYSIIS of word 1

N2 C 8 S; NYSIIS2 - NYSIIS of word 2

BT C 4 S; BranchType - Branch or outlet type

BR M 6 S; BranchVal - Branch or outlet identification

HN N 10 S; HouseNumber - 1

HS C 6 S; HouseSuffix - 11 \"A\", \"1/2\", etc.

PD C 2 S; PreDirection - 17

PT C 4 S; PreType - 19

SN C 48 S; StreetName - 23

ST C 4 S; SuffixType - 51

SQ C 3 S; 300 SuffixQual - 55 (old, ext, byp)

SD C 2 S; SuffixDir - 58 Suffix direction

UT C 6 S; UnitType - 60 Unit designation type

UV C 6 S; UnitValue - 66 Unit designnation value

XS C 8 S; StrSoundex - 72 Soundex of Street Name

XR C 4 S; StrRsoundex - 80 Reverse Soundex of street name

CT C 25 S; CityName - 1 City name

XC C 4 S; CitySndx - 26 Soundex of City name

SA C 2 S; State - 30 State Abbreviation

ZP M 6 S; Zip - 32 Zip code

Z4 N 4 S; Zip4 - 38 Zip4 add-on code

VR C 1 S; Valid Record Marker

CY C 150 S;For array matching

**[Rule File APLMATCH41.RUL]{.underline}**

; APL Match Rule file for full Match aplmatch41.rul

; Rules file for authority file

; Matchware V4.1 changed CY to W1

VAR USDOT 1 8 S;X

VAR CarrName 9 120 S

VAR CarrAddr 129 50 S

VAR CarrCity 179 25 S

VAR CarrState 204 2 S

VAR CarrZip 206 10 S

VAR InterState 216 1 S

VAR ICC 217 6 S;X

VAR Status 223 1 S

VAR Legal_vs_DBA 224 1 S

VAR Official_vs_Address 225 1 S

VAR NWords 226 1 S

ARRAY_ADJ Company 227 30 5 S NWords

VAR Div 377 15 S

VAR NYSIIS1 392 8 S;X

VAR NYSIIS2 400 8 S;X

VAR BRType 408 4 S

VAR BRVal 412 6 S

VAR HouseNum 418 10 S

VAR HouseSuf 428 6 S

VAR Predir 434 2 S

VAR Pretype 436 4 S

VAR StreetName 440 48 S

VAR SuffixType 488 4 S

VAR SuffixQual 492 3 S

VAR SuffixDir 495 2 S

VAR UnitType 497 6 S

VAR UnitVal 503 6 S

VAR StreetSndx 509 8 S;X

VAR RevStreetSndx 517 4 S;X

VAR City 521 25 S

VAR CitySndx 546 4 S;X

VAR State 550 2 S

VAR ZipCode 552 6 S;X

VAR ZipCodeExt 558 4 S

VAR ValidRecord 562 1 S

MATCH CHAR US USDOT 0.40 0.10

MATCH NUMERIC IC ICC 0.40 0.10

; First try match on the array of company name

MATCH ARRAY UNCERT W1 5 Company 0.9999 0.0001 700.00

; Second try match on the array of company name

;MATCH ARRAY UNCERT CY 5 Company 0.9999 0.0001 700.00

; Second try match on the address

MATCH NUMERIC HN HouseNum 0.60 0.10

MATCH UNCERT SN StreetName 0.70 0.10 700.00

MATCH UNCERT UT UnitType 0.60 0.10 700.00

MATCH UNCERT UV UnitVal 0.60 0.10 700.00

MATCH UNCERT CT CarrCity 0.90 0.10 700.00

MATCH UNCERT ZP ZipCode 0.70 0.10 550.00

;Changed from 900 MATCH UNCERT ZP ZipCode 0.70 0.10 900.00

;MATCH CNT_DIFF Z4 ZipCodeExt 0.70 0.10 1

MATCH CHAR CS State 0.20 0.10

CUTOFF 2.0

;CUTOFF 0.0

########  FMCSA Rules for Declaring Matches 

This Page Intentionally Blank

**CARRIER SEARCH SYSTEM ALGORITHM**

**[MATCH SCORING ON CARRIER ID INFORMATION]{.underline}**

Name: 70 points

Address: 5 points

City: 8 points

State: 8 points

Zip Code: 8 or 9 points (depending on length of code)

USDOT #: 21 points

ICC #: 21 points

**[DEFINITE MATCHES]{.underline}**

90 points or more are generally required for a definite match of the
Census to the inspection/accident data, e.g.:

\* Same Carrier Name, Address, City & State

\* Same Carrier Name & USDOT Number

\* Same Carrier Name & ICC Number

Exceptions that are also considered matches are:

\* Same USDOT Number & full address (Address, City, State & Zip Code)

\* Same ICC Number & full address

\* Same USDOT Number & ICC Number

This Page Intentionally Blank

########  Carrier Search and Match Algorithm 

This Page Intentionally Blank

**Introduction**

The Carrier Search and Match Algorithm is designed to accept a carrier
query and to declare a result along with, potentially, a list of
candidates. The Carrier Search and Match Algorithm uses a combination of
sequential, intelligent database queries, MatchWare library functions,
adjustments to the MatchWare results, and application of rules from
FMCSA to declare its result as expediently and as accurately as
possible.

The goal of the algorithm is to locate a carrier in the New MCMIS
database given a carrier "query," which consists of a name and an
address, and optionally a DOT and/or ICC number. SQL queries are used to
locate "match candidates," and MatchWare, FMCSA rules, and heuristics,
developed by JHU/APL, are used to score the candidates. The algorithm
declares one of the following three possible outcomes for every query:

1.  [Confirmed Definite Match]{.underline} where the algorithm declares
    that one carrier from the New MCMIS database definitely matches the
    carrier in the query;

2.  [Potential Match]{.underline} where the algorithm suggests one or
    more carriers from the New MCMIS database, as potential matches to
    the carrier of the query; and

3.  [Definite Non‑Match]{.underline} which guarantees that no carrier in
    the New MCMIS database matched the carrier of the query.

Since the reference tables are populated with over three-quarters of a
million carriers (and growing), it would be wholly impractical to
examine every carrier in the database for each query. The algorithm
solves this problem by iterating through a series of targeted, indexed
database queries, or "search stages".

As each search stage is executed, all returned rows are included in the
candidate pool. During the matching process, MatchWare compares all the
candidates to the carrier in the query and assigns each candidate a
score. Then, FMCSA-mandated rules and JHU/APL heuristics are applied,
which may modify the scores originally assigned by MatchWare.

The application of the rules and heuristics affect the results obtained
from a search stage in one of the following ways:

-   A candidate, considered a definite match based on the MatchWare
    score, continues to be a definite match after the application of all
    rules and heuristics. When a search stage returns a definite match
    in this manner, the algorithm has achieved its goal and can declare
    a result. In this case, none of the remaining search stages are
    performed

-   A candidate who is a definite match based on the MatchWare score is
    no longer a definite match. Instead, after applying the rules and
    heuristics the candidate becomes a potential match following a
    correction for "false positive definite match". The algorithm
    continues the search for a definite match in this case.

-   A candidate that was not considered a definite match, becomes one by
    application of the rules and heuristics. The algorithm does not
    discontinue the search for a better candidate when it "promotes" a
    candidate by the application of one of these heuristic or rules.

-   A candidate, not considered a potential match, gets promoted to that
    status after the application of the rules and heuristics.

When a search stage results in a definite match as in case (1) or after
all search stages are performed, the algorithm merges the results from
all search stages that were completed and declares a result of Confirmed
Definite Match, Potential Match or Definite Non Match based on the
collective results from those stages.

**Database Searches**

The Carrier Search and Match Algorithm uses a set of pre-defined SQL
queries to search the database for candidates. Each query performs the
same three-table join and returns the same columns: they differ in the
condition expressed by their "where" clauses. Each query's search
condition, or "where" clause, consists of one or more equality matches
on indexed columns. See the section later in this appendix for details
of the searches.

**MatchWare**

MatchWare is used to standardize carriers and to rank candidates against
a query. Since MatchWare is so fundamental to the Carrier Search and
Match Algorithm, a minimum understanding of MatchWare functionality is
required. Therefore, a summary of that functionality is provided below.

The Carrier Search and Match Algorithm utilizes several functions from
the MatchWare callable libraries in its processing. They are:

-   Standardize. The query is sent to the MatchWare standardizer, which
    returns the standardized values. Appendix B provides details of the
    standardization rules and all the keys used by MatchWare
    applications for New MCMIS. Calls to the standardizer also
    initialize an internal MatchWare match key. All candidates are
    subsequently matched against this match key.

-   Add Candidate. Candidates returned from database searches are
    inserted into the MatchWare environment as candidates using this
    function.

-   Match. MatchWare compares each candidate against the match key and
    assigns it a score, or weight.

-   Fetch Candidate. After matching, the candidates are fetched
    one-by-one from the MatchWare environment along with their total
    MatchWare score. MatchWare ranks the candidates in descending order
    by their score.

MatchWare assigns a score to each candidate it matches against the
query. In addition, the algorithm determines the numerical contribution
each component of the query makes to the overall score. The way the
algorithm uses these score is critical to understanding how the
algorithm works. Details and terminology regarding MatchWare scores and
how the algorithm uses those scores is provided below.

-   The overall, or **composite** **score** that MatchWare assigns a
    candidate is composed of four **component score** contributions
    based on USDOT Number, ICC Docket Number, name, and address.

-   As part of matching process, the algorithm obtains not only the
    composite score, but also the four component scores for USDOT
    number, ICC Docket Number, name and address.

-   JHU/APL has heuristically determined the threshold value that a
    candidate's composite score must equal or surpass to be considered a
    Confirmed Definite Match. It has likewise determined the similar
    threshold for a Potential Match. Below that latter threshold, a
    candidate is considered a Definite Non Match.

-   MatchWare uses a step-function to assign the *component* score
    values. For example, the component score for the USDOT Number will
    *always* be assigned a value of 2.0 when the candidate USDOT Number
    matches the query's, -0.58 when it does not match the query, and 0.0
    when the query has no USDOT Number.

This consistency enables the algorithm to analyze the quality of matches
in detail, and based on that analysis, heuristically adjust the weights
in some circumstances.

**Rules and Heuristics**

FMCSA has mandated that any carrier candidate whose USDOT Number or ICC
Docket Number matches that of the query should get special
consideration, irrespective of its overall MatchWare score. (For the
purpose of this discussion, such a carrier will be referred to as a
"**DOT/ICC match**"). If a DOT/ICC match candidate was found, the
processing of remaining candidates in the results list is affected as
described below. The Rules defined by the FMCSA are discussed in
Section 4 of this document and summarized in Table 4--1. JHU/APL has
developed a set of heuristics that allow the algorithm to apply the
FMCSA rules to candidate records by adjusting the scores assigned to
these records on a scale consistent with the one used by MatchWare. By
following this strategy, the heuristics allow the algorithm to use a
common and consistent strategy for declaring matching results regardless
of whether the FMCSA rules are applied or not. The following general
rules apply:

-   If a DOT/ICC match candidate is found and the composite MatchWare
    score for that candidate is at or above the threshold to be
    considered a Confirmed Definite Match, no more candidates are
    considered for rule-based score alteration.

-   Due to the application of business rules mandated by the FMCSA,
    candidates that can be considered Confirmed Definite Matches fall
    into two categories **MatchWare Definite Candidates** and
    **Rule-based** **Definite Candidate** or **Heuristic Definite
    Candidates**.

-   A candidate that is assigned a composite score by MatchWare that is
    at or above the definite-match threshold is referred to as a
    **MatchWare Definite Candidate**. Likewise, one that MatchWare
    assigned a potential-match level score is referred to as a
    **MatchWare Potential Candidate.**

-   A candidate with a combine MatchWare score below the definite match
    threshold may have its score "promoted" by the JHU/APL algorithm to
    a value that is above that definite match threshold due to the
    application of business rules specified by the FMCSA. Such a
    candidate is referred to as a **Rule-based, or heuristic definite**.

-   A candidate with a composite MatchWare score below the potential
    match threshold may have its score "promoted" to a value above that
    threshold due to the application of a business rule specified by the
    FMCSA. Similarly, a candidate with a composite MatchWare Score above
    the definite match threshold may have its score demoted to a value
    below the definite match threshold but above the potential match
    threshold. Such Rule-based promotions -- or demotions -- can result
    in a candidate being a **Rule-based potential, or Heuristic
    potential.**

-   If a DOT/ICC potential match candidate was found, rules provided by
    the FMCSA require that any candidate with a different USDOT Number
    or ICC Docket Number than that of the DOT/ICC potential match
    candidate not over ride that candidate as a definite match unless
    its name and address match the query at least as well as the DOT/ICC
    candidate's name and address match the query. This can affect both
    promotions and demotions.

-   FMCSA has provided instructions on adjudicating conflicts when more
    than one of its criteria for declaring a definite match candidate
    has been satisfied. See Table 4--1 for a summary of these
    instructions.

**Algorithms**

The Carrier Search and Match Algorithm combines the database searches,
MatchWare calls, and heuristics in a complex algorithm. A description of
that algorithm follows, starting with the highest-level function,
Process Query. Each algorithm description corresponds to a separate
Visio diagram, included later in this appendix.

**Process Query (1.0)**

1.  **Input.** The carrier query input to the carrier Search and Match
    Algorithm must consist of a full name and full address, and
    optionally a USDOT number and /or an ICC Number. The input should
    not contain a partial name or address because the underlying
    MatchWare software uses a probabilistic algorithm to determine
    which, if any, carriers definitely match the query. The Carrier
    Search and Match Algorithm is not designed to function as a search
    engine and therefore returns numerous poor-quality results when
    given partial names and / or addresses.

2.  **Standardize**

    1.  The Algorithm passes the input from above to the MatchWare
        standardizer function, with a two-fold result. Some of the
        standardized fields returned are used in targeted database
        searches for candidates. (The candidates are subsequently sent
        to MatchWare for matching). Additionally, standardizing has the
        side effect of initializing the MatchWare environment with the
        information in the query as the "match key" -- the carrier
        information against which all candidates will be compared.

    2.  The Carrier Search and Match Algorithm analyzes the standardizer
        output, setting processing flags for the present query based on
        the presence or absence of values in specific standardized
        fields. These flags affect the sequence of database searches.
        For example, the search that queries on REVERSE-STREET-SOUNDEX,
        CITY, and STATE will not be performed if the query contains a
        post office box.

3.  **Step through sequence of database searches**. The Carrier Search
    and Match Algorithm has an ordered progression of database queries,
    or searches, that it performs until either no searches are left to
    perform or the criteria for terminating searching for a better
    candidate has been met.

4.  **Determining whether or not to perform a search** at any given step
    of the progression, the algorithm analyzes the make-up of the query
    itself (see 1.2.2, above) as well as the number of candidates that
    would be returned by the search. The algorithm is designed to
    execute a search that returns fewer candidates before executing a
    more time-consuming search that returns more candidates (in orders
    of magnitude).

5.  **Search and Match.** Search the database based on a given query and
    match the results against the carrier query with MatchWare. Adjust
    the MatchWare scores if necessary and apply FMCSA rules to further
    adjust the scores. Sort the results list in descending score order.

6.  **If MatchWare definite found**, then do not perform any additional
    searches . Otherwise proceed with the next database search in the
    sequence (Step 1.3 above)

7.  **Merge results.** When one of search loop terminating conditions
    has been satisfied, merge each database search's results list (if
    any candidates were found) into a single results list. In the
    process, whenever two candidates are found with the same USDOT
    Number, retain the candidate with the highest score and discard the
    other.

8.  **Declare the query result.** The following criteria are used.

    1.  **Confirmed Definite match**

        1.  Only one carrier candidate *definitely* matches the carrier
            in the query, as reflected by either its composite MatchWare
            score or by its "promoted" score based on application of a
            rule provided by the FMCSA.

        2.  Normally, carriers must be active to be considered definite
            matches. However, if a query has just one definite match
            candidate whose DOT Number or ICC Docket Number matches the
            value in the query, then the candidate can be declared a
            Confirmed Definite Match even if it is an inactive carrier.

    2.  **Potential match.** (Note, in all cases that the Carrier Search
        and Match Algorithm declares a query a potential match, a human
        operator must inspect the query and its candidates and either
        declare the query a definite match by selecting one of the
        candidates or else declare the query a Definite Non Match).

        1.  [A single potential match candidate]{.underline} exists. In
            other words, the carrier candidate has some degree of
            similarity to the query, but an insufficient score to be
            declared a confirmed definite match.

        2.  [Multiple potential match candidates]{.underline} exist.
            Again, all the carrier candidates have some degree of
            similarity to the query, but no candidate has a combined
            score that is high enough for that candidate to be declared
            a definite match. This condition is known as "multiple
            potentials."

        3.  [Two or more definite match candidates]{.underline} with
            active status exist: this condition is known as "conflicting
            definites".

        4.  A single, non-DOT/ICC definite match candidate that has
            inactive status.

        5.  Multiple definite match candidates (irrespective of search
            type) that have inactive status.

    3.  **Definite Non Match**: no carriers were found which combined
        scores that are high enough to be considered even a potential
        match.

9.  **Output:** The output of the Process Query function is a query
    result declaration and a candidate list. Note that queries with
    non-match result may have empty results lists.

Search and Match (1.5)

1.  **Search type (input).** All Carrier Search and Match Algorithm
    database queries search for equality matches on indexed columns
    using one of several predefined searches. *See Database Searches*
    later in this appendix for the details about these searches. Each
    invocation of the Search and Match function takes one of these
    search types and the standardized values from the query as an
    argument.

2.  **Standardized query values (input).** Used as run time "bind"
    variables in the pre-defined database searches.

3.  **Query Database.** The reference database tables are searched for
    candidates using the search type specified and the standardized
    values supplied. The SQL query returns column values that MatchWare
    requires for matching against the query.

4.  **Load candidates into the MatchWare Matching Environment.**
    MatchWare can accept an unlimited number of candidates to match
    against the query that has previously been loaded into the match
    key.

5.  **Match.** Once all candidates have been loaded into the MatchWare
    environment, a single function call matches all candidates against
    the match key and results in the assignment of the combined
    MatchWare score to each candidate. Subsequently, candidates are
    retrieved from the MatchWare matching environment for evaluation by
    the algorithm in the descending order of combined MatchWare score
    (best candidates first). The Carrier Search and Match Algorithm
    places each candidate into a results list for the current search,
    and continues retrieving candidates until the scores for the
    candidate retrieved drop below a pre-defined cut off threshold. All
    candidates with scores below the cut off threshold are discarded
    because such a low score implies that there is no match between the
    candidate record and the query.

6.  **Adjust name weights.** Sometimes the score that MatchWare assigns
    to the name component of a candidate can be misleadingly high. This
    happens when the number of words in the query and candidate names
    differs, and the words in shorter name match very well with words in
    the longer name. For example, if the query had four words and the
    candidate had two, and they matched exactly on those two words,
    MatchWare would score a perfect match on name. However, the
    algorithm is designed to match based on the *full* name. Therefore,
    the algorithm will apply a correction to the name component of the
    score and lower the combined score as well to reflect the fact that
    the name matches on just two out the possible four words.

7.  **DOT or ICC Candidate?** If DOT or ICC Candidate found, apply FMCSA
    rules for DOT or ICC Candidates to comply with directives issued by
    the FMCSA. This ensures that DOT or ICC candidates with low
    MatchWare scores are included in the final list of candidates and
    not prematurely eliminated because of low MatchWare scores

8.  **Set best name and address weights.** Scores for each of the four
    components that make up the composite MatchWare Score -- USDOT
    Number, ICC Docket Number, name and address for each candidate
    record are determined by the algorithm during this step by using a
    special process developed by JHU/APL. In this step, the algorithm
    assigns the candidate records the best component score based on the
    closeness of match with the query. These component scores are needed
    for applying the FMCSA rules.

9.  **Apply heuristics.** To apply the FMCSA rules for declaring
    matches, apply JHU/APL heuristics to adjust a candidate's score
    under various circumstances. See the following Apply Heuristics
    section for details of this algorithm. After applying these rules to
    the scores, the algorithm re-sorts the list.

Apply Heuristics (1.5.9)

1.  Loop through the candidates in the current result list until either
    there are no more candidates left to process or until a terminating
    condition has been met.

2.  Is the candidate a DOT/ICC match?

    1.  If so, then it is automatically eligible for rule-based
        promotion.

    2.  If not, then set the candidate as promotable if the candidate's
        name and address weights are at least as good as the best name
        and address weights from any DOT/ICC match candidates.

3.  Is the candidate a MatchWare definite?

    1.  If MatchWare definite, is this candidate promotable?

        1.  If not promotable, then drop the candidate's score to a high
            potential match score (demote).

        2.  If promotable, is this candidate active?

        3.  If active, set the MatchWare Definite Found flag (to be
            returned from function call).

            1.  Has a DOT/ICC Heuristic Definite candidate been found
                previously? If not, exit the loop. If so, continue
                looping: since the algorithm now has two definite match
                candidates (the current MatchWare definite and the
                DOT/ICC heuristic definite) and the query will require
                operator resolution, continue looping to provide the
                operator with all possible candidates that this search
                can provide.

    2.  If not MatchWare definite then is this candidate promotable?

        1.  If promotable, compute possible promotion -- score
            improvement -- by FMCSA rules.

        2.  Is candidate active, definite, and DOT/ICC type?

        3.  If so, set the DOT/ICC Heuristic Definite Found flag.

4.  End of loop: re-sort the list if any scores changed.

**Database Search Types**

Each of the following queries is named after the columns that they
search on. The query's description includes the condition for employing
it.

1.  **US DOT Number.**

    1.  Executed: if query has a US DOT number.

    2.  Where: query-DOT = cand-DOT.

2.  **ICC Number.**

    1.  Executed: if query has an ICC number

    2.  Where: query-ICC = cand-ICC.

3.  **Pure NYSIIS**

    1.  Background.

        1.  Every carrier in the reference database has the first two
            words of its name standardized into NYSIIS values and stored
            in the carrier name table.

        2.  A "count" of the number of records in the database
            corresponding to each unique NYSIIS value is maintained in a
            separate table in the database. The length of time that a
            NYSIIS search will take depends on the number of records in
            the database that correspond to that NYSIIS value. This
            count is used to estimate the time required for a NYSIIS
            search and optimize the NYSIIS search. A higher count would
            take a longer time to complete a NYSIIS search.

        3.  The algorithm obtains the query name's two NYSIIS values
            when standardizing the query. When searching, The algorithm
            looks up those values' counts and uses them to determine
            which of the four NYSIIS searches, if any, would be the most
            reasonable to perform.

        4.  There are four NYSIIS searches, but only one of them is
            executed for any given query: NYSIIS1212, NYSIIS121,
            NYSIIS122, and NYSIIS12.

    2.  **NYSIIS1212**

        1.  Executed: if the counts of both query NYSIIS values are very
            low (see note 3.2.3.2).

        2.  Where:

query-NYSIIS1 = cand‑NYSIIS1 or query-NYSIIS2 = cand-NYSIIS2 or

query‑NYSIIS1 = cand‑NYSIIS2 or query-NYSIIS2 = cand-NYSIIS1

3.  Notes.

    1.  The NYSIIS1212 is the most inclusive (and most costly) of all
        NYSIIS searches. No other query that includes one of the NYSIIS
        values as part of its selection criteria can return a candidate
        that the NYSIIS1212 did not return.

    2.  When city and state are present in a query, lower count
        thresholds can be used for determining whether to perform a
        particular NYSIIS search, since the query will have another
        chance at performing a NYSIIS search later in the sequence of
        NYSIIS/city/state and NYSIIS/state searches. For that reason,
        higher count thresholds are used when city and state are missing
        from the query. This applies to all pure NYSIIS searches.

```{=html}
<!-- -->
```
3.  **NYSIIS121 and NYSIIS122**

    1.  Execute

        1.  If query standardization produced only one NYSIIS value and
            its count is moderate.

        2.  If query standardization produced two NYSIIS values, but the
            counts of one was high, while the other was moderate.

    2.  Where ("query-NYSIISn" is either NYSIIS1 or NYSIIS2):

query-NYSIISn = cand-NYSIIS1 or query-NYSIISn = cand-NYSIIS2

4.  **NYSIIS12**

    1.  Executed: if the counts of both query NYSIIS values are high.

    2.  Where

(query-NYSIIS1 = cand‑NYSIIS1 and query-NYSIIS2 = cand-NYSIIS2) or
(query‑NYSIIS1 = cand‑NYSIIS2 and query-NYSIIS2 = cand-NYSIIS1)

3.  The NYSIIS12 is the least inclusive and least costly NYSIIS search.

```{=html}
<!-- -->
```
4.  **REVERSE-STREET-SOUNDEX/CITY-SOUNDEX/STATE.**

    1.  Execute: if the carrier query has a street address, in addition
        to city and state.

    2.  Where:

> query-revstreetsndx = cand-revstreetsndx and
>
> query-citysndx = cand-citysndx and query-state = cand-state

5.  **UNIT-VALUE/CITY-SOUNDEX/STATE.**

    1.  Execute: if the carrier query has a PO Box, in addition to city
        and state

    2.  Where:

> query-unitval = cand-unitval and query-citysndx = cand-citysndx and
>
> query-state = cand-state

6.  **NYSIIS/CITY-SOUNDEX/STATE.**

    1.  Execute: only if the search performed in the NYSIIS step was
        *not* NYSIIS1212.

    2.  Where (query-NYSIISn is either NYSIIS1 or NYSIIS2):

> (query-NYSIISn = cand-NYSIIS1 or query-NYSIISn = cand-NYSIIS2) and
>
> query-citysndx = cand-citysndx and query-state = cand-state

3.  If either NYSIIS121 or NYSIIS122 searches were performed previously,
    then the other, higher count, NYSIIS is used here.

```{=html}
<!-- -->
```
7.  **REVERSE-STREET-SOUNDEX/STATE.**

    1.  Execute: if the carrier query has a street address, in addition
        to state

    2.  Where:

> query-revstreetsndx = cand-revstreetsndx and query-state = cand-state

8.  **UNIT-VALUE/STATE.**

    1.  Execute: if the carrier query has a PO Box, in addition to
        state.

    2.  Where:

> query-unitval = cand-unitval and query-state = cand-state

9.  **NYSIIS/STATE.**

    1.  Execute: only if the search performed in the NYSIIS step was
        *not* NYSIIS1212.

    2.  Where (query-NYSIISn is either NYSIIS1 or NYSIIS2):

> (query-NYSIISn = cand-NYSIIS1 or query-NYSIISn = cand-NYSIIS2) and
>
> query-state = cand-state

**Flow Diagram**s

![](media/image5.wmf)

![](media/image6.wmf)

![](media/image7.wmf)

![](media/image8.wmf)

![](media/image9.wmf)

########  Match Handler for New MCMIS

This Page Intentionally Blank

######### Match Handler

The Match Handler provides Standardization and Search-and-Match
functionality to New MCMIS. It is composed of the Match Handler program
written in C++ and a set of PL/SQL packages. The New MCMIS PL/SQL
procedures call the Match Handler PL/SQL procedures directly, which in
turn communicate with the Match Handler program via Oracle pipes. The
Match Handler program links to the MatchWare Services API (see separate
appendix), which is, in fact, the bulk of the code. The API, in turn,
makes calls to the MatchWare callable library functions.

######### Match Handler Architecture

**The Problem**

The problem, which the Match Handler solved, is how to make MatchWare
functionality available to the New MCMIS procedures, which are written
in PL/SQL, in an efficient way, with as much code reuse as possible,
given the following issues:

-   MatchWare is written in C.

-   APL's MatchWare Services API, which encapsulates the MatchWare
    functions and adds an intelligent and efficient search algorithm and
    heuristic processing, is also written in C (C++).

-   There is considerable startup overhead associated with the MatchWare
    Services API, including connecting to the database and MatchWare
    environment initialization.

-   Although Oracle does provide the ability to invoke C functions from
    PL/SQL code, they implemented that call as a forked subprocess with
    a wait for the subprocess to terminate. Consequently, there can be
    no continuity of information between calls within the Match Handler
    code.

-   The Match Handler interleaves database queries with numerous calls
    to MatchWare library functions.

One solution would have been to perform the database queries in PL/SQL
from the session of the calling procedure, calling the MatchWare API
in-between queries for just the minimum MatchWare services needed. That
implementation would require re-writing the formidable amount of C++
code that processes the query results before and after sending them to
the MatchWare API into PL/SQL. It is even questionable whether PL/SQL
has the needed capabilities. The performance would suffer due to the
relative inefficiency of PL/SQL compared to C++ and the overhead of
MatchWare environment initialization every time the MatchWare API was
called. Consequently, this solution was never implemented.

A better solution would have been to implement a C++ Match Handler with
it's own database connection. The PL/SQL would make a simple function
call for search-and-match functionality. However, this implementation
would require MatchWare environment initialization and a database
connect each time the Match Handler was called. Since we desired to
avoid the performance impact this overhead would incur, an alternative
solution was investigated.

**The Solution**

The initialization performance goal was to achieve minimal startup
overhead while invoking a callable Match Handler. This required that the
Match Handler executable once started, run continuously in its own
process with its MatchWare environment and a persistent database
connection established. Interprocess communications allowing a PL.SQL
procedure to communicate with an asynchronous C++ executable was
provided via an Oracle pipes solution.

Oracle pipes are database objects, which allow two distinct processes,
each of which have a database connection to the same Oracle instance, to
communicate with each other. Similar to Unix pipes, processes can use
Oracle Pipes to compose, send, listen for, receive and read messages
from another process. (For detailed information on Oracle pipes see
Oracle online documentation, Supplied PL/SQL Packages Reference
document, package DBMS_PIPES).

Use of Oracle Pipes, supported the implementation of a callable Match
Handler with the following flow characteristics:

-   New MCMIS procedures requiring MatchWare services make calls to one
    of the Match Handler PL/SQL procedures.

-   The Match Handler PL/SQL procedures pack the call arguments into a
    message and send it on a predefined "request" pipe.

-   The Match Handler program, which listens for messages on the request
    pipe, picks up the message, unpacks it, processes the request, and
    packs the results into a return message. It sends that message on a
    unique, temporary pipe back to the listening Match Handler PL/SQL
    process.

-   When the Match Handler PL/SQL receives the message, it unpacks the
    information and returns it to the calling New MCMIS procedure.

An important characteristic of Oracle pipes warranting special note is
that pipes are *transaction independent*. Each process sending and
receiving messages on pipes runs in its own session and its own
transaction; any uncommitted updates, inserts, or deletes in one process
*will not be visible* to other processes.

######### Match Handler Program Design

The Match Handler program which runs asynchronously and processes the
standardization and search-and-match requests has a simple design: a
"main" function, an mh_class object, and calls to the MatchWare Services
API.

Mh_class functions:

-   Set up and handle all communication with the Match Handler PL/SQL
    over the Oracle pipes.

-   Field user requests for standardization and search-and-match by
    calling MatchWare Services API functions.

-   Handle all administrative tasks, including logging, heartbeat
    posting, ping, and termination.

The "main" function in match_handler.cpp instantiates an object of type
mh_class and then goes into an infinite event loop within which two
mh_class functions are called:

-   *heartbeat* checks for administrative requests on the administrative
    pipe and if one is present, responds to it. It also posts a
    timestamp to the heartbeat log if the heartbeat interval has
    transpired.

-   *user_request* waits for a message on the request pipe based on the
    wait time established at initialization time. If a request is
    detected, it services it.

The "main" function's event loop is exited if an administrative
terminate request was received or if there is an error logged to the
heartbeat file.

The MatchWare Services API is invoked through the cm_services interface.
This is where the standardization and search-and-match requests are
completely processed. See MatchWare Services API documentation for
details.

######### Match Handler Database Setup

Before Match Handlers can execute, the following database administration
tasks have to be completed:

-   The Oracle database user under whose database account the Match
    Handler PL/SQL process will be created must exist and posses execute
    privilege on Oracle package dbms_pipe. This user will be referred to
    as the match handler user.

-   Run the following scripts logged in as the match handler user:

```{=html}
<!-- -->
```
-   \\api\\v3\\sql\\build\\match_handler\\mh_build script.

-   \\api\\v3\\sql\\plsql\\match_handler\\build.sql

```{=html}
<!-- -->
```
-   Execute privilege on pkg_mh_defs and pkg_match_handler must be
    granted to any users or roles needing to call the Match Handler.

######### Match Handler Program Operation and Administration

More than one Match Handler program can be executed at the same time.
Even though all handlers listen on the same request pipe, individual
messages can only be retrieved and processed by individual handlers. The
Oracle pipes package ensures that messages are removed from their pipes
once received by a process. Multiple handlers could potentially greatly
improve performance in a high user-request scenario, provided that
system resources are available to support them.

Match Handlers post significant events to log files as well as a
periodic "heartbeat" to a heartbeat file. Heartbeats consist of the
handler's unique id number and a date/time stamp. The purpose of
heartbeat and log files are to give the administrator a way of
determining each handler's status -- particularly to see whether a given
Match Handler process is still running, or whether it has entered a
"hung" state.

**Running Match Handlers**

Match Handler programs can be executed in the foreground from a NT
command window or in the background using NT's AT scheduler. The Match
Handler has required and optional parameters. It is invoked from its bin
directory using its executable name, match_handler.

Required Arguments:

-   Database host name

-   Database username

-   Database password

-   Root directory spec for logging: Two subdirectories of the root
    directory, one named "logs" and the other named "heartbeats" must
    exist.

Optional Flags (case insensitive)

1.  /D \-- Debug mode. Generates debug information for fixing software
    problems. Information output to the log file in debug mode will
    likely not be meaningful to an operator, and will merely clutter up
    the log file.

2.  /F \-- Foreground heartbeats. Writes all debug, log, and heartbeat
    information to STDOUT. Used when running the Match Handler from an
    NT command window. Ignored if running in the background.

3.  /H\<n\> \-- Heartbeat interval (in minutes). Default is15 minutes.

4.  /Q \-- Quiet mode \-- does not prompt user for confirmation. The /q
    switch is required if running in the background. If not present, the
    process will hang up forever in the background waiting for user
    confirmation.

5.  /W\<n\> \-- Wait time for user request (in seconds). Default is 1
    second. Determines how long the handler waits for a user request
    before checking for an administrative request and posting a
    heartbeat (if it is time).

As soon as a new handler is started, log and heartbeat files for it will
appear in its respective directories. For example, if a new handler's Id
(automatically assigned) is "15", and the root log directory is
d:\\matchWork\\handler, then a 15.log file will appear in the
d:\\matchwork\\handler\\logs directory and in the
d:\\matchwork\\handler\\heartbeats directory. When handler 15
terminates, the heartbeat log will disappear, but the log file will
remain.

**Running Handlers in the Background**

To run a match handler in the background, create a command file similar
to the following one used on psafer7:

> d:
>
> cd \\api\\v3\\bin
>
> match_handler.exe psafer7 nmMatch test d:\\matchWork\\handler /d /f
> /h1 /q

The /q (quiet) switch is important for running in the background. It
prevents the executable from asking for user confirmation, which would
only serve to hang the executable up forever, since there\'s no way of
answering questions asked from a background process.

The job is then scheduled in the normal way, for example:

> at 11:00 runMH.cmd

**Terminating Match Handlers**

A running match handler can be terminated using a function in the
pkg_mh_admin as follows:

SQL\> select pkg_mh_admin.fnc_terminate_handler(\<handlerId\>,
\<timeout\>) from dual;

The handlerId is the unique Id of the handler that is to be terminated.
The timeout value must be at least as long as the wait time that the
target handler was initialized with.

This Page Intentionally Blank

########  MatchWare Applications Distribution CD 

This Page Intentionally Blank

The information in this appendix describes the contents of the MatchWare
Application for New MCMIS CD that was provided to the New MCMIS team as
part of the software delivery in June 2002. This information is provided
for members of the New MCMIS team at the FMCSA who are responsible for
installing, supporting and maintaining MatchWare applications for New
MCMIS.

######### MatchWare Applications for New MCMIS CD

The referenced CD contains the MatchWare Applications for New MCMIS as
well as all the source code and supporting scripts for these
applications that were developed by JHU/APL. A CD containing the
MatchWare applications for New MCMIS and the supporting source code were
delivered by JHU/APL to the New MCMIS development team in June 2002. A
patch for the applications was released and delivered to the New MCMIS
development team electronically in July 2002. A fix for the Match
Handler was implemented in August 2002 and a CD incorporating all
versions of the MatchWare applications and source code was delivered to
the New MCMIS development team on August 20, 2002.

######### Call Hierarchy and Cross Reference

JHU/APL has prepared an Excel spreadsheet to explain the call hierarchy
among the major components. The spreadsheet also contains a
cross-reference table of the MatchWare Applications for New MCMIS.

Screen snapshots of the Call Hierarchy Spreadsheets are provided in this
appendix so that members of the New MCMIS development team can get
familiar with the contents of the spreadsheet. On the actual
spreadsheet, viewers can drill down to get details of any particular
component by clicking the "+" tab on the left hand side of the
spreadsheet.

Finally, the Cross Reference table is also provided in this appendix as
a reference tool.

**MatchHandler**

![](media/image10.png){width="8.99375in" height="3.5194444444444444in"}

**Top Level Match Handler Call Hierarchy**

**MatchHandler**

![](media/image11.png){width="8.995833333333334in"
height="5.436111111111111in"}

**Second Level Match Handler Call Hierarchy**

**MatchHandler**![](media/image12.png){width="8.988888888888889in"
height="5.277777777777778in"}

**Details of Match Handler mh_class.register_handler call hierarchy**

**MatchHandler**

![](media/image13.png){width="8.99375in" height="3.717361111111111in"}

**Details of Match Handler mh_class.heartbeat call hierarchy**

**MatchHandler**

![](media/image14.png){width="8.011111111111111in"
height="5.061805555555556in"}

**Details of Match Handler Loop Call Hierarchy**

**interMatch**

![](media/image15.png){width="8.99375in" height="2.5881944444444445in"}

**Top Level interMatch Call Hierarchy**

**interMatch**

![](media/image16.png){width="8.991666666666667in"
height="5.522916666666666in"}

**Second Level interMatch Call Hierarchy**

**interMatch**

![](media/image17.png){width="8.991666666666667in"
height="5.1194444444444445in"}

**Top Level cm_services.search_and_match call hierarchy**

**interMatch**

![](media/image18.png){width="7.598611111111111in"
height="5.266666666666667in"}

**Details of cm_services.search_and_match call hierarchy**

**interMatch**

![](media/image19.png){width="7.668055555555555in"
height="5.460416666666666in"}

**Details of match_engine.search_and_match call hierarchy**

**interMatch**

![](media/image20.png){width="8.990972222222222in"
height="4.2652777777777775in"}

**Details of matchlib.add_candidates call hierarchy**

**interMatch**

![](media/image21.png){width="8.997916666666667in"
height="5.269444444444445in"}

**Details of matchlib.do_ranking call hierarchy**

This Page Intentionally Blank

Cross Reference Table

  ------------------------------------ ----------------------------------
  Function Name                        Module Name

  add_candidate                        matchware_class.cpp

  add_candidates                       matchlib.cpp

  add_one                              match_rec_class.cpp

  apply_heuristics                     application_logic.cpp

  \_admin_request                      mh_class.cpp

  close_search_cursor                  db_search.pc

  cm_services                          cm_services.cpp

  compute_rule_weight                  application_logic.cpp

  create_pipe                          db_pipe.pc

  cut_low_cands                        match_rec_class.cpp

  db_init                              db_lib.pc

  definites_exist                      match_rec_class.cpp

  Dip                                  matchware_class.cpp

  do_ranking                           rank.cpp

  Domtch                               matchware_wrapper.c

  end_matching                         matchware_class.cpp

  end_ranking                          rank.cpp

  Endcase                              matchware_wrapper.c

  fetch_search_cursor                  db_search.pc

  Freecan                              matchware_wrapper.c

  get_handler_id                       db_mh.pc

  Heartbeat                            mh_class.cpp

  fetch_candidate                      matchware_class.cpp

  fetch_next_candidate                 matchware_class.cpp

  Getcand                              matchware_wrapper.c

  Init                                 match_rec_class.cpp

  Init                                 matchware_class.cpp

  init_ranking                         rank.cpp

  initialize_matching                  matchware_class.cpp

  insert_results                       db_mh.pc

  InterMatch                           cm_services.cpp

  InterStd                             cm_services.cpp

  Keyinit                              matchware_wrapper.c

  Main                                 match_handler.cpp

  \_make_match_input_str               matchware_class.cpp

  match_candidates                     matchware_class.cpp

  match_engine                         match_engine.cpp

  match_rec_class                      match_rec_class.cpp

  Matchlib                             matchlib.cpp

  matchware_class                      matchware_class.cpp

  Matinit                              matchware_wrapper.c

  Merge                                match_rec_class.cpp

  merge_searches                       match_rec_class.cpp

  mh_class                             mh_class.cpp

  multiple_definites                   match_rec_class.cpp

  Function Name                        Module Name

  name_weight_adjusted                 match_rec_class.cpp

  Newcand                              matchware_wrapper.c

  Newlist                              matchware_wrapper.c

  next_item_type                       db_pipe.pc

  num_is_list                          match_rec_class.cpp

  number_candidates                    match_rec_class.cpp

  nysiis_counts                        db_search.pc

  \_open_search_cursor_id              db_search.pc

  open_search_cursor_id                db_search.pc

  pack_message                         db_pipe.pc

  place_char                           utils.cpp

  place_chars                          utils.cpp

  place_int                            utils.cpp

  \_post_heartbeat                     mh_class.cpp

  \_post_heartbeat                     mh_class.cpp

  promotion_criteria_met               application_logic.cpp

  preview_nysiis_counts                search.cpp

  process_search                       match_engine.cpp

  process_search                       match_engine.cpp

  receive_message                      db_pipe.pc

  recombine                            match_rec_class.cpp

  register_handler                     mh_class.cpp

  resolve_intrastate_status            application_logic.cpp

  resolve_match_status                 match_rec_class.cpp

  s_init_all_chars                     db_search.pc

  s_init_all_inds                      db_search.pc

  s_init_all_numbers                   db_search.pc

  s_init_all_varchars                  db_search.pc

  s_terminate_all_varchars             db_search.pc

  \_search_and_match                   cm_services.cpp

  search_and_match                     match_engine.cpp

  \_search_and_match                   mh_class.cpp

  search_and_rank                      search_and_rank.cpp

  search_condition                     search_conditions.cpp

  self_match                           matchware_class.cpp

  send_message                         db_pipe.pc

  set_best_weights                     match_rec_class.cpp

  sort                                 match_rec_class.cpp

  \_standardize                        mh_class.cpp

  standardize                          standardize.cpp

  standardize                          matchware_class.cpp

  standardize_and_fetch                matchware_class.cpp

  stdstr_to_stdrec                     request_utils.cpp

  stdrec_to_stdstr                     request_utils.cpp

  stninit                              matchware_wrapper.c

  unpack_message                       db_pipe.pc

  user_request                         mh_class.cpp
  ------------------------------------ ----------------------------------

########  Source Code Description 

This Page Intentionally Blank

######### Introduction

This section of the document is provided as reference guide for the
source code of the MatchWare Applications for New MCMIS delivered by
JHU/APL. The source code that was provided to the New MCMIS team on a CD
in June 2002 and August 2002 follows a specific directory structure,
which is described in this appendix. This directory structure must be
maintained on the target computer systems to ensure that the environment
necessary for MatchWare applications for New MCMIS is established
correctly. The reader of this section is expected to know how to develop
C/C++ applications in a Microsoft Windows NT/2000 environment using
Oracle Pro\*C for embedded SQL functions.

######### Directory Structure

All source code of all types directly or indirectly related to the
MatchWare API resides under a version subdirectory of the API top-level
directory. The current version of code resides under \\API\\V3. All C++
code resides in a directory tree structure underneath \\API\\V3\\cpp on
the target application server. The Match Handler PL/SQL resides under
\\API\\V3\\SQL on the target database server.

The following outline describes the tree for the C++ code. This document
describes the C++ code in the tree that is related to the Match Handler
delivered to New MCMIS. Many of the modules in these directories were
developed for MatchWare applications for legacy MCMIS and will not be
described here.

-   **cpp\\include**: All header (.h) files, irrespective of the
    directory where corresponding source file resides.

-   **cpp\\programs**: Modules containing program main functions and
    Visual C++ project files. Similar programs are grouped in
    subdirectories. Main module normally includes invocation
    instructions, argument and switch descriptions.

```{=html}
<!-- -->
```
-   **match_handler:** Directory containing the match handler
    executable.

```{=html}
<!-- -->
```
-   **cpp\\source**

```{=html}
<!-- -->
```
-   **app_specific:** Application-specific code. For example,
    definitions only used by Safetynet 2000 applications.

-   **dblib:** Pro\*C modules.

-   **common:** Utility modules serving all applications.

-   **matchlib:** Application-independent code related to the MatchWare
    API.

```{=html}
<!-- -->
```
-   **sql\\plsql\\match_handler:** PL/SQL code providing interface to
    Match Handler from New MCMIS database-resident code and
    communicating with the C++ Match Handler executable.

######### Module Function Descriptions

**Directory: cpp\\programs\\match_handler**

> **match_handler.cpp**

-   ***main.*** Initialize mh_class object, validate and process
    invocation arguments and switches, initialize logging, and register
    the handler with the Oracle pipes communication protocol. Go into
    event loop forever or until termination condition met.

**Directory: cpp\\source\\app_specific**

> **application_logic.cpp (match_rec_class class)**

-   ***Significant variables***

```{=html}
<!-- -->
```
-   ***minWt:*** array of float. Holds predefined weights used for
    decisions and assignments in the heuristics and the search and match
    algorithm in general.

```{=html}
<!-- -->
```
-   ***add_recombs***. Used when two name/address pairs were passed in
    the query. This function is used to recombine the name from one
    name/address pair search with the address from the other if their
    weights meet a predefined threshold. The recombined record is added
    to the list.

-   ***adjust_inactives***. Drop the weight of an inactive definite to
    lowest score that is still above the definite match threshold.

-   ***apply_heuristics***. Loop through each member of the list going
    from best to worst until the end of the list or until loop exit
    condition is met. Use heuristic criteria to determine whether to
    promote, demote the candidate's weight, or to leave it alone. Calls
    *promotion_criteria_met* and *compute_rule_weight.*

-   ***check_guarding_condition***. Demote a definite match candidate to
    just below the definite match threshold where its DOT and ICC
    numbers *mis*-match, and it has a fair name match, but outstanding
    address match.

-   ***compute_rule_weight***. This is a critical function in MatchWare
    API, as it encapsulates many sponsor-mandated rules for modifying a
    candidates score from that which MatchWare assigned it. It contains
    46 special conditions for modifying the score. Called by
    *apply_heuristics.*

-   ***demote definite***. Lower a definite match candidate to just
    under the definite match threshold.

-   ***detail_string***. Fabricate a position-formatted string from
    candidate information for writing the details output file.

-   ***post­\_bat1000_results***.Write the list's result information
    (result declaration and DOT number if definite match) into the
    1000-byte input string.

-   ***post_snet2k_results***. Write the list's result information
    (result declaration and DOT number if definite match) into the
    233-byte input string.

-   ***promotion_criteria_met***. Compares name/address search
    candidates' name and address weights to the best from the DOT and
    ICC searches to determine whether the candidate is "promotable."
    Called by *appy_heuristics.*

-   ***resolve_intrastate_status***. Queries that are intrastate
    carriers must be declared either a definite match or definite
    no-match since they do not undergo the potential resolution process.
    When the algorithm has declared the query a potential match, this
    function resolves the declaration using sponsor-mandated rules,
    which are basically more lenient rules for declaring definites.

> **search_conditions.cpp (match_engine class)**

-   ***search_condition***. The match engine has a predefined sequence
    of database search types that are considered for each query. The
    match engine interates through that sequence and, for each step in
    the sequence, calls *search_condition* to determine whether or not
    to execute that search type. *Search_condition* uses the attributes
    of the query to make that decision and, in types that have multiple
    search options, to decide which particular search to return.

> **system_utils.cpp**
>
> To increase portability of the MatchWare API, all system-specific
> functions were relagated to a single module, *system_utils.*

-   ***append_file***. Append one file to another

-   ***compress_files***. Use WinZip to compress a file.

-   ***copy_file***. Copy a file.

-   ***decompress_file***. Use WinZip to decompress a file.

-   ***delete_file***. Delete a file.

-   ***delete_file_type***. Delete files in a directory of a given type
    (extension).

-   ***dir_count***. Return the count of files in a directory.

-   ***file_exists***. Determine whether or not a given file exists in a
    directory.

-   ***make_dir***. Create a directory.

-   ***make_dir_list***. Create a listing of files in a given directory.

-   ***move_file***. Move a file.

**Directory: cpp\\source\\dblib**

> **db_lib.pc**

-   ***db_status***. Return sqlcode if negative. If sqlcode is zero or
    positive (100/1403) return zero.

-   ***db_error***. If sqlcode is negative log the database error and an
    error message passed in as an argument (if any).

-   ***get_db_errmsg***. Use Oracle function to retrieve database error
    message from the database.

-   ***row_not_found***. Returns true if sqlcode is positive (100/1403).

-   ***no_more_data***. Same as *row_not_found*

-   ***db_init***. Connect to the database with the given host, username
    and password.

-   ***db_close***. Disconnect from the database.

-   ***outline_off***. Alter the session to set stored outlining off.

-   ***outline_on***. Alter the session to set stored outlining on.

-   ***trace_off***. Alter the session to set tracing off.

-   ***trace_on***. Alter the session to set tracing on.

> **db_mh.pc**
>
> Non-pipe-related database function for the match handler.

-   ***get_handler_id***. Returns a unique integer, which can be used
    for identifying match handler client requests.

-   ***insert_results.*** Inserts candidate DOT numbers and MatchWare
    scores into the search results database.

> **db_pipe.pc**
>
> Since the Match Handler executables run asynchronously, Oracle pipes
> (package DBMS_PIPE) are used to communicate with them from the match
> handler PL/SQL. Db_pipe encapsulates calls to the DBMS_PIPE package.
>
> Pipes are database objects and so can be created and dropped.
>
> Messages are created by "packing" numbers and character string message
> "items" on the pipe. The message is then "sent" over the pipe.
>
> On the receiving end, a session can listen on a pipe for a message.
> When a message is received, the message "items" are "unpacked".

-   ***create_pipe***. Create a public or private pipe.

-   ***next_item_type***. Find out whether the next message item is a
    number or a character string.

-   ***pack_message***. Pack a number or character string into a
    message.

-   ***receive_message***. Listen for a message on a pipe with a given
    timeout. Return when either a message has been received or the
    timeout has been reached.

-   ***remove_pipe***. Drop the pipe.

-   ***reset_buffer***. Clear a pipe's buffer of any unreceived
    messages.

-   ***send_message***. Send a message over a pipe.

-   ***unpack_message***. Unpack an "item" from a "message".

> **db_search.pc**
>
> Uses dynamic SQL to fabricate and execute all database queries used by
> the search and match algorithm.

-   Significant global variables

```{=html}
<!-- -->
```
-   All Pro\*C host variables and indicator variables.

-   String length definitions.

-   Cursor for select from the nysiis_counts table.

```{=html}
<!-- -->
```
-   ***nysiis_counts***. Obtain the counts of occurrences of two given
    NYSIIS values in the reference database from a pre-loaded table.

-   ***open_search_cursor_str***. Fabricate a SQL query with predefined
    select and table-join clauses and a user-defined where clause.

-   ***open_search_cursor_id***. Fabricate a SQL query with predefined
    select and table-join clauses and a where clause

-   ***\_open_search_cursor***. Use dynamic SQL to prepare the
    fabricated SQL statement and then use the prepared statement to open
    a SQL cursor. Bind variables are passed to the cursor open statement
    depending on which search is being executed.

-   ***fetch_search_cursor***. Fetch rows from the previously opened
    cursor into host arrays (one for each column). Each array can hold
    up to 1000 elements.

-   ***close_search_cursor***. Close the dynamic SQL cursor.

-   ***s_init_search_strings***. Initialize an array of "where clause"
    strings for the predefined database searches.

-   ***s_assign_searchrecs***. Assign host variable values to record
    fields in an array of those records. Takes place after each database
    fetch. The array of records is passed back to the calling function.

-   ***s_init_all_chars***. Initialize all character-type host
    variables.

-   ***s_init_all_numbers***. Initialize all numeric-type host
    variables.

-   ***s_init_all_varchars***. Initialize all varchar-type host
    variables.

-   ***s_init_all_inds***. Initialize all indicator variables.

-   ***s_terminate_all_varchars***. After fetching, null-terminate all
    varchar host variables.

> **db_vars.pc**

-   ***Significant global variables.*** db_vars.pc has not source code.
    It contains host variable declarations that are used by other Pro\*C
    modules. Db_vars.h has an extern statement for each variable
    declared in db_vars.pc. The other modules access the global variable
    declarations in db_vars.pc by including db_vars.h.

> **varchar_utils.cpp**
>
> For manipulating varchar host variables, handling the len and arr
> fields and the indicator variable.

-   ***assign_vc_from_lstr***. Assigns one position-delimited field from
    a long string into a varchar variable. If field is all blanks,
    assigns null to the varchar.

-   ***assign_vc_from_lstr2***. Same as *assign_vc_from_lstr*, except
    that if the field is all blanks, it assigns those blanks to the
    varchar.

-   ***assign_varchar***. Assign a varchar from a C character string.

-   ***init_varchars***. Initialize a varchar host variable.

-   ***init_indicators***. Initialize an array of indicator variables.

-   ***terminate_varchars***. Null terminate the varchar arr field based
    on the varchar's len field and indicator variable.

**Directory: source\\common**

> **Sqlglm.c**
>
> A wrapper for Oracle's sqlglm function for getting error messages.
>
> **debug.cpp**
>
> Contains a global Boolean. Allows for centralization of control of
> whether to print debug messages or not. Other modules merely include
> debug.h
>
> **log.cpp**
>
> Centralizes logging to a single file into a C++ class. Enables
> printing to STDOUT in addition to the log file.

-   **\_*init. ***Opens the log file and initializes class variables.

-   ***log_class***. Overloaded class constructor. Each version calls
    *\_init.*

-   ***\_print***. Prints to the log file.

-   ***print***. Multiply overloaded function to enable differing
    numbers of arguments. All call *­\_print.*

> **msglog.cpp**
>
> Consolidates and simplifies logging for the Match Handler API.

-   ***init_msgfiles***. Initializes the message and error files that
    the API writes to.

-   ***log_err***. Logs a message to the message file.

-   ***log_msg***. Logs a message to the error file.

> **struct_defs.cpp**
>
> Utility functions for API record structures.

-   ***init_stnrec***. Initializes all fields in one or more
    stdz_rec_type record.

-   ***cout_stnrec***. Outputs the fields in a stdz_rec_type record.

-   ***init***. Initializes all the fields in a request_rec_type record.

> **utils.cpp**
>
> Utils.cpp contains functions, which perform relatively simple tasks
> which are performed frequently. Often the functions will add error
> handling and safety features such as string boundary protection that
> their similar C functions neglect.

-   ***assign_dbchar***. Assigns a character to a Pro\*C character (not
    varchar) host variable. Handles the indicator variable too.

-   ***assign_dbchar_from_lstr***. Assigns a single character from a
    position in a long string to a Pro\*C character host variable.
    Handles error conditions and indicator.

-   ***assign_dbint_from_lstr***. Assigns positionally defined numeric
    character data in a long string to an integer, handling the
    indicator. Calls *assign_int_from_lstr*.

-   ***assign_int_from_lstr***. Assigns positionally defined numeric
    character data in a long string to an integer. Protects string
    boundaries and attempts to convert non-numeric characters.

-   ***assign_onechar***. Assign a char into a character string
    variable.

-   ***assign_str_from_lstr***. Assign a position-defined field within a
    long string to a C string.

-   ***change_suffix***. Substitute a filename's suffix with some other.

-   ***char_from_lstr***. Extract a single character from a long string.

-   ***convert_date***. Convert a date string in month/day/year date
    format (e.g., may/02/2002) to yyyymmdd format (e.g., 20020502), or
    visa-versa.

-   ***datestr***. Return a date-stamp string for today's date in format
    dd_mon_yyyy (e.g., 02_may_2002).

-   ***datetimestr***. Return a string with the current date- and
    time-stamp. Calls the standard C ctime function.

-   ***fab_timestamp***. Returns the current date in a string formatted
    mm-dd-yyyy (e.g., 05-02-2002).

-   ***isnumeric***. Returns non-zero (true) if a non-blank string
    contains only numeric digits.

-   ***longStrcmp***. Compares a position-defined field within two long
    strings. Returns 0 if they are the same (mimicking C's strcmp).

-   ***lstrcpy***. Copy a position-defined field within a long string
    into a target character string.

-   ***my_asctime***. Converts a date in format yyymmdd to that returned
    by C's asctime function.

-   ***nocase_strcmp***. Does a case-insensitive string comparison of
    two strings, returning the same values as strcmp.

-   ***non_blank***. Returns non-zero (true) if the string argument is
    non-blank.

-   ***non_zero***. Returns zero (false) if the string argument contains
    only zeroes, otherwise non-zero (true).

-   ***non_blank***. Returns non-zero (true) if a position-defined field
    within the long string argument is non-blank.

-   ***non_zero***. Returns zero (false) if a position-defined field
    within a long string argument contains only zeroes, otherwise
    non-zero (true).

-   ***pad_leading_zeroes***. Fill a character string to its full
    allocated length with its original string value and leading zeroes.

-   ***place_char***. Place a single character into its defined position
    within a long string.

-   ***place_chars***. Place a character string into its defined
    position within a long string.

-   ***place_int***. Place an integer into its defined position within a
    long string.

-   ***safe_atoi***. Convert a character string to an integer with error
    checking. Returns zero if the string contains non-numeric data.

-   ***safe_strcpy***. String-boundary protecting version of C's strcpy.

-   ***safe_strncpy***. String-boundary protecting version of C's
    strncpy.

-   ***something_there***. Returns zero if string argument is null or
    all blanks, otherwise non-zero.

-   ***Something_there***. Returns false if string argument is null or
    all blanks, otherwise true.

-   ***strcmp_with_strip***. Performs a C strcmp on two character
    strings, stripping any leading zeroes from local copies of both
    strings first. Returns the same values as strcmp.

-   ***strcpy2***. Same as lstrcpy, only safer.

-   ***strip_leading_zeroes***. Return the string argument with any
    leading zeroes stripped off.

-   ***strip_trailing_blanks***. Returns the string argument with any
    trailing blanks removed.

-   ***substr***. Return the substring of the string argument starting
    at a given position and of a given length.

-   ***timestr***. Return a time stamp string formatted hh_mm_ss.

-   ***to_lower***. Convert all characters in the string argument to
    lower case.

-   ***to_upper***. Convert all characters in the string argument to
    upper case.

**Directory: source\\matchlib**

> **cm_services.cpp**

-   ***cm_services***. Create matchlib and match_engine objects.

-   ***\~cm_services***. Delete the matchlib and match_engine objects.

-   ***db_connect***. Connect to the Oracle database.

-   ***interStd***. Calls the matchlib standardize function.

-   ***interMatch***. Overloaded interface to search and match
    functionality for the interactive Match Handler. Calls
    *\_search_and_match.*

-   ***doubleMatch***. Processes input files of carriers represented by
    two name/address pairs in what is known as "1000-byte" format. For
    each record, calls *\_search_and_match*, and then posts the results
    to predefined output files.

-   ***\_init_totals***. For the batch processing functions --
    *doubleMatch* and *singleMatch* -- cm_services tabulates counts of
    input characteristics and result information. *\_init_totals* zeroes
    out all the counters.

-   ***\_log_totals***. Formats the tabulated counts and logs to a file
    stream.

-   ***\_search_and_match***. Private function called by all public
    functions providing batch or interactive search-and-match
    functionality. Completely processes one carrier represented by one
    or two name/address pairs. When two pairs are provided, it calls
    *match_engine.process_search* twice, and attempts to recombine the
    results of the two searches to obtain better results. Finally the
    three results lists are merged and a single list is returned. When
    one pair is provided, *process_search* is only called once and the
    recombine step is skipped.

-   ***singleMatch***. Processes input files of carriers represented by
    one name/address pair in the 233-byte format defined by the
    Safetynet 2000 crash and inspection reports. For each record, calls
    *\_search_and_match*, and then posts the results to predefined
    output files.

> **match_engine.cpp**

-   ***match_engine***. Create a matchlib object and an array of
    match_rec_class objects.

-   ***\~match_engine***. Delete the array of match_rec_class objects.

-   ***convert_input***. Convert input from request_rec_type format to
    stdz_rec_format.

-   ***find_best_name_addr***. Find the best name weight and address
    weight from the DOT and ICC carriers in a results list.

-   ***merge_searches***. Merge all the results list in the array of
    match_rec_class that contain any results into a single results list.
    Calls *match_rec_class.merge*.

-   ***process_search***. Main entry point of the match_engine class for
    a given carrier query defined by a single name and address. Makes
    sure the carrier input is standardized. Loops through the predefined
    search steps, calling match_engine's *search_and_match* function to
    query the database and score the results for each search executed.
    Merges the results into a single results list.

-   ***search_and_match***. Completely processes a single search for a
    carrier query. Calls matchlib's *search_and_rank* function and
    applies the heuristics to adjust the MatchWare-assigned weight.

> **match_rec_class.cpp**
>
> The match_rec_class class has three categories of methods: (1) List
> handling functions like *sort*, *merge*, and *pop*. (2) List
> processing functions, like *adjust_name_weights*, which adjusts the
> name weight of each list member based on certain heuristic criteria.
> (3) List state functions. For example, whether the list contains an
> active definite. A list index number can be supplied to these
> functions: if none is supplied, then the "current" element will be
> queried. *Match_rec_class* keeps track of the *current* list top as
> the list is being traversed using the *pop* function.

-   Significant class variables

```{=html}
<!-- -->
```
-   ***match_rec_array***. An array of records of type match_rec_type.
    This is the candidate list around which the match_rec_class
    functions revolve.

-   ***count*.** Number of candidates in the list.

-   ***position***. Array index of the current "stack top." *Position*
    allows *match_rec_class* to treat its internal array of records as a
    stack.

-   ***minWt***. Array of predefined weights for manipulating, comparing
    and assigning MatchWare and heuristic scores.

```{=html}
<!-- -->
```
-   ***match_rec_class***. Initializes class variables, particularly
    *match_rec_array* by calling *init*.

-   ***\~match_rec_class***. Deallocates the *match_rec_array* candidate
    list.

-   ***add***. Adds multiple records to the *match_rec_array*. Maintains
    uniqueness of dot number in the list. Reallocates the list based on
    the number of new, unique records it is adding.

-   ***add_one***. Adds one new record to the *match_rec_array* in
    similar fashion to *add*.

-   ***name_weight_adjusted***. Considers adjusting a candidate's name
    weight according to heuristic criteria. If adjusted, reflects that
    change in the overall weight and returns true. If unchanged, returns
    false.

-   ***adjust_name_weights***. Traverses the *match_rec_array* candidate
    list, calling *name_weight­\_adjusted* for each element. Resorts the
    list if any candidates had their weight(s) adjusted.

-   ***confirmed_dotno***. Returns a character string with the confirmed
    DOT number if the query has been confirmed a definite match.
    Otherwise returns a null string.

-   ***cout_item***. Returns a long character string with a formatted
    listing of a candidate's attributes.

-   ***cout_mrc***. Formats and prints up to the top 25 candidates in
    the list to STDOUT.

-   ***cut_low_cands***. "Discards" candidates with low weights by
    changing the *count* variable to not include their indices. Uses a
    higher threshold for queries declared a definite match versus those
    declared a potential match.

-   ***definites_exist***. Returns true if the list contains at least on
    definite match candidate.

-   ***defmatch***. Returns true if the list has been declared a
    definite match.

-   ***doticc_match***. Returns true if the current candidate matches
    the query's DOT and ICC numbers.

-   ***dot_in_list***. Returns true if the DOT number argument is the
    same as a candidate currently in the list.

-   ***effective_weight***. Returns a candidate's effective weight,
    which is always the MatchWare weight before heuristics application
    and the heuristic weight thereafter.

-   ***end_of_stack***. Returns true if there are no more elements to
    for *pop* to return from the list. Internally, when the list
    position variable equals the number of elements in the list.

-   ***find_best_weights***. Returns the best name and address weights
    from the ICC and DOT candidates in the list (if any).

-   ***fout_mrc***. Formats and prints up to the top 25 candidates in
    the list to a file.

-   ***how_many***. Returns the number of candidates in the list.

-   ***in_range***. Returns true if the integer argument is between 0
    and the number of candidates in the list.

-   ***init***. Class method that initializes class variables,
    particularly *match_rec_array*.

-   ***init***. Initializes one or more match_rec_type records. Not a
    class method.

-   ***is_active***. Returns true if the candidate is an active carrier.

-   ***is_definite***. Returns true if the candidate's score meets the
    definite match threshold.

-   ***is_dot_match***. Returns true if the candidate's DOT number is
    the same as the query's.

-   ***is_icc_match***. Returns true if the candidate's ICC number is
    the same as the query's.

-   ***is_in_list***. Same as *num_in_list*, but returns true if the
    candidate is in the list instead of its position and false if it is
    not instead of --1.

-   ***is_mw_definite***. Returns true if the candidate's MatchWare (as
    opposed to effective) weight meets the definite match threshold.

-   ***is_potential***. Returns true if the candidate's weight meets the
    potential match threshold but is less than the definite match
    threshold.

-   ***item***. Returns a C pointer to the specified candidate in the
    list. Defaults to the current candidate if no index argument
    supplied.

-   ***merge***. Takes an array of match_rec_class objects as arguments
    and merges them all into the objects candidate list. *Merge*
    excludes duplicates, preserving the best candidate for any DOT
    number.

-   ***minMinus***. Returns the float value from the *minWt* array for
    the integer argument with a ten-thousandth shaved off. Used to
    compare MatchWare result scores to values in the *minWt* array to
    avoid problems resulting from floating point rounding.

-   ***minPlus***. Returns the float value from the *minWt* array for
    the integer argument with a ten-thousandth added on. Used to compare
    MatchWare result scores to values in the *minWt* array to avoid
    problems resulting from floating point rounding.

-   ***multiple_definites***. Returns true if the list contains more
    than one definite match candidate.

-   ***nomatch***. Returns true if the list has been declared a definite
    non-match.

-   ***num_in_list***. Takes an argument of match_rec_type. Finds the
    argument's position in the candidate list based on a predefined
    comparison criteria (normally DOT number match). Returns --1 if the
    argument is not in the list.

-   ***number_candidates***. Returns the number of candidates in the
    list.

-   ***outcome***. Returns the single character representation of the
    numeric query declaration.

-   ***pop***. Returns a C pointer to the current candidate in the list.
    Treats the list as a stack. Used for traversing the candidates in
    the list. Internally, *pop* returns a pointer to the record at array
    index *position*, and then increments position by 1.

-   ***potentials_exist***. Returns true if the list contains at least
    one candidate that meets the potential match threshold but is less
    than the definite match threshold.

-   ***potmatch***. Returns true if the list has been declared a
    potential match.

-   ***reccmp***. Compares two match_rec_type records. Returns 0 if they
    are the same. Normally compares only DOT number.

-   ***recomb_rec***. Takes two match_rec_type records as arguments.
    Combines the name components of one to the address components of the
    other into a new match_rec_type record and returns the new record.

-   ***recombine***. Takes two match_rec_class candidate lists as
    arguments. Attempts to recombine names and addresses from the two
    lists for like DOT numbers that have better scores than the
    candidates in the original two lists for that DOT number. Any
    recombination candidates found are added to a third list.

-   ***remove_duplicates***. Not used.

-   ***reset_stack***. Resets the "stack pointer" to the "top" of the
    stack. Internally, sets the position variable to 0.

-   ***resolve_match_status***. Using simple logic plus special rules
    set down by FMCSA, declare the overall query result from the list of
    candidates.

-   ***result***. Returns the integer list result declaration.

-   ***search_type***. Return the search Id for the database query used
    to populate the list.

-   ***seek_dotnum***. Seeks the position in the list where the DOT
    number argument is found. Internally sets the position of the
    position variable to that array element's index.

-   ***set_best_weights***. Returns the best name and address weights
    for a candidate list containing only DOT number candidates or ICC
    number candidates.

-   ***sort***. Sorts the candidates in descending order of effective
    weight. Uses MatchWare weight to break a tie.

-   ***top***. Returns the array index of the current stack top.
    Internally, returns the value of the position variable.

-   ***usdotnum***. Returns the DOT number of the current candidate.

> **matchlib.cpp**

-   ***\_read_params***. Read in the label-value pairs from the
    parameters file. These tell the MatchWare configuration files to
    use.

-   ***\_constructor**.* Initialize the matchlib object. Open the log
    files, instantiate the combined MatchWare_class object, assign
    values to the nysiis_max array.

-   ***matchlib***. Calls *\_constructor.*

-   ***\~matchlib***. Deletes all *MatchWare_class* objects.

-   ***init_db***. Connects to the database.

> **MatchWare_class.cpp**

-   ***add_candidate**.* Add a candidate to the MatchWare environment
    for later matching against the query candidate.

-   ***\_constructor***. Initialize class variables.

-   ***dip**.* Performs a single-candidate match against a query. Used
    for obtaining name, address, USDOT, or ICC weight.

-   ***fetch_candidate**.* Fetch a matched candidate from the MatchWare
    environment given its candidate index number.

-   ***fetch_next_candidate**.* After matching, the candidates can be
    fetched in ranked order, best first. *Fetch_next_candidate* returns
    the next-best candidate until there is none left.

-   ***end_matching**.* Makes MatchWare function calls needed to clear
    the MatchWare environment of candidates.

-   ***error_message**.* Returns the MatchWare error message when there
    was a MatchWare error.

-   ***extract_fields**.* When a candidate is fetched after matching a
    formatted string is return. *Extract_fields* parses the carrier
    components into a record structure from that string.

-   ***fetch_keys**.* Fetches the standardized fields from the MatchWare
    environment after standardizing. Some of the keys are used for
    searching the database for candidates.

-   ***\_keycpy***. After standardizing a carrier, \_*keycpy* fetches a
    specified field value out of the MatchWare environment and copies it
    into a C string. The field to fetch is specified to MatchWare using
    the field's key identifier. The key identifiers are specified in the
    configuration files.

-   ***init**.* Initialize MatchWare environment with specified
    configuration files.

-   ***\_make_match_input_str**.* Accepts a candidate carrier in the
    form of a C record structure and fabricates a MatchWare candidate
    string by mapping the record fields to their positions in the
    string.

-   ***\_make_stdz_input_str**.* Accepts a query carrier in the form of
    a C record structure and fabricates a MatchWare standardization
    string by mapping the record fields to their positions in the
    string.

-   ***match_candidates**.* Once all the candidates have been loaded
    into the MatchWare environment, instruct MatchWare to score them
    against the query carrier.

-   ***MatchWare_class**.* Invoke \_constructor. Takes configuration
    type as an argument.

-   ***\~MatchWare_class***. Deallocate MatchWare class globals.

-   ***number_candidates**.* Returns the number of candidates loaded
    into the MatchWare environment for matching.

-   ***\_push_key**.* Forces a value for a field into the MatchWare
    environment's Match Key. The field is specified using its key
    identifier (see \_*keycpy,* above).

-   *\_**setkeys. ***Although standardizing initializes most fields in
    the Match Key for matching, some fields need to be manually
    initialized using *\_push_key. \_Setkeys* does so for all fields
    that need it.

-   ***standardize***. Accepts a record containing the carrier
    information, fabricates a specially formatted string with that
    information, and calls the MatchWare standardize function with that
    string.

-   ***standardize_and_fetch**.* A convenience function: calls
    *standardize* and *fetch_keys* functions, above.

-   ***self_match**.* Match a carrier against itself.

> **MatchWare_defs.cpp**

-   ***Significant variables***

```{=html}
<!-- -->
```
-   ***stdpos***. Field position definitions for the string sent to
    MatchWare when standardizing a carrier.

-   ***stdlen***. Field length definitions for the string sent to
    MatchWare when standardizing a carrier.

-   ***mwpos***. Field position definitions for the string sent to
    MatchWare when adding a candidate.

-   ***mwlen***. Field length definitions for the string sent to
    MatchWare when adding a candidate.

> MatchWare_wrapper.c

The actual MatchWare callable library functions are not callable from
C++. MatchWare_wrapper functions are simply single MatchWare functions
wrapped in such a way as to enable C++ code to call them. For
information on what each MatchWare function does, see the MatchWare
documentation.

> **mh_class.cpp**

-   ***\_admin_request***. If there is a message on the administrative
    pipe, unpack it and respond to it.

-   ***\_heartbeat***. Each match handler that gets started up has its
    own heartbeat file. Each match handler gets started up with a
    specified interval of time over which it should listen for a user
    request on the request pipe. It has a second interval, which is the
    frequency with which it should post a timestamp to the heartbeat log
    file. At the pre-defined listening interval, call \_admin_request.
    If the heartbeat interval has transpired, call_post_heartbeat.

-   ***\_post_heartbeat***. Post a timestamp to the heartbeat file.

-   ***register_handler.*** Instantiate cm_services object. Create an
    administrative pipe according to its unique handler Id. Open the log
    file and heartbeat file.

-   ***search_and_match***. Unpack the search request arguments from the
    pipe, including the user pipe id and the request string. Call
    cm_services.interMatch with the arguments. Pack the results into the
    user's pipe and send them back.

-   ***Standardize***. Unpack the standardize request arguments from the
    pipe, including the user pipe id and the string to standardize. Call
    cm_services.interStd with the arguments. Pack the results onto the
    user's pipe and send them back.

-   ***user_request***. Wait for a user request on the request pipe for
    the pre-defined interval. If a request comes, determine the request
    type, calling \_search_and_match or \_standardize accordingly.

> **rank.cpp**

-   ***init_ranking.*** Initializes any MatchWare environments not
    already initialized, Standardizes the carrier query in each
    environment, thereby initializing its match key, and prepares the
    default (full) MatchWare environment for matching.

-   ***add_candidates***. Adds one or more candidates to the MatchWare
    environment.

-   ***do_ranking.*** Use MatchWare to match the candidates against the
    carrier query, all of which have previously been loaded into the
    MatchWare environment. Fetch the candidates in ranked order until
    the weights begin to fall below a predefined threshold. For each
    qualified candidate, send it to the four specialized MatchWare
    environments to determine its component weights. Adjust the name
    component weight when necessary, adjusting the combined weight
    accordingly. Add the candidate to the match record list (see
    match_rec_list).

-   ***end_ranking***. Calls the *MatchWare_class.end_ranking*
    function*.*

-   ***rank***. A stand-alone function that takes a standardized carrier
    query as *stdz_rec_type*, and an candidates as array of
    *search_rec_type*. *Rank* adds all the candidates to the MatchWare
    environment, invokes MatchWare to rank them, ends the ranking, and
    then returns a *match_rec_class* object with the results.

> **search_and_rank.cpp**

-   ***search_and_rank***. Overloaded function which calls
    *\_search_and_rank.*

-   ***\_search_and_rank***. If the carrier query has not already been
    standardized, *­\_search_and_rank* does so now. Opens a database
    cursor with the current search definition. Fetches candidates from
    the database in batches of 1,000. Adds all candidates from each
    batch fetched to the MatchWare environment. Once all candidates have
    been fetched from the database, calls *matchlib.do_ranking* to
    invoke MatchWare to rank the candidates. Lastly it adjusts the name
    weights using heuristic criteria by calling
    *match_rec_class.adjust_name_weights.*

> **Standardize.cpp**

-   ***Standardize.*** Standardizes one or more carriers. For each
    carrier name and address pair passed, it captures all the
    standardized field values the return (C++) record structure and
    additionally matches the carrier against itself.

-   ***upd_ins_stn_tbls***. Accepts an array of standardized records and
    sends them to a Pro\*C function that checks for existence of each
    record and then updates or inserts accordingly.

-   ***stdz_and_updins***. Accepts an array of unstandardized records,
    standardizes them, and sends them to a Pro\*C function that checks
    for existence of each record and then updates or inserts
    accordingly.

-   ***stdz_and_update***. Accepts an array of unstandardized records,
    standardizes them, and updates the database with the results.

-   ***stdz_and_insert***. Accepts an array of unstandardized records,
    standardizes them, and inserts the results into the database.

-   ***reconcile_std_tables***. Determines which, if any, carriers in
    the database have been updated without having their corresponding
    rows in the standardization tables updated (or inserted).
    Standardizes those carriers and updates or inserts into the
    standardization tables as needed.

**Directory: sql\\plsql\\match_handler**

With one exception, each Match Handler PL/SQL package has a
specification and a body. The body's file name is the same as its
specification, with "\_body" appended to it. New MCMIS naming
conventions are used throughout.

> **pkg_match_handler**

-   ***Purpose***. The Match Handler interface package. Contains all
    callable PL/SQL functions providing MatchWare services. All
    functions return 0 for success, 1 for timeout, anything else for an
    error.

-   ***Callable Functions and Procedures***

```{=html}
<!-- -->
```
-   ***General:*** All the pkg_match_handler functions have the
    following in common:

```{=html}
<!-- -->
```
-   They are either passed or generate a unique identifier that is used
    name a pipe which they create to receive their response from the
    Match Handler executable.

-   They convert their arguments to a format in which they can easily be
    packed into the pipe message.

-   Message items on all outgoing and incoming messages must conform to
    a predefined order expected by the Match Handler executable as well
    as these PL/SQL functions.

-   Match Handler requests are sent to the Match Handler executable on
    the (permanent) request pipe.

-   They listen on their own, uniquely named, temporary, response pipe
    for their request's response from the Match Handler executable.

-   When (and if) the response message is received, the message items
    are unpacked in the predefined order. Absence of an item or an item
    of the wrong data type is reported as an error.

```{=html}
<!-- -->
```
-   ***fnc_search_and_match***. Called by the New MCMIS registration
    module. Intended to provide interactive search and match
    functionality. Requires at least one full name and address. Returns
    number of candidates (if any) found. The candidate DOT numbers and
    weights are inserted into the mh_results table. Calls *fnc_cm*
    (below).

-   ***fnc_carrier_match***. Called by the New MCMIS Crash and
    Inspection report processing module. Can also be used for batch adds
    and OP1 processing. Requires one full name and address. US DOT
    number and/or ICC number improve the results. Returns the query
    declaration -- confirmed definite match (C), potential match (P), or
    definite no match (N). If (and only if) the result is potential
    match, candidate rows will be inserted into the mh_results table and
    the number of rows inserted will be returned along with the query
    result. Calls *fnc_cm* (below).

-   ***fnc_standardize***. Used by New MCMIS to update the Match Handler
    reference tables with new Carrier data. Accepts a name and/or an
    address and returns the standardized fields.

-   ***fnc_cm.*** Processes search and match requests for
    *fnc_search_and_match* and *fnc_carrier_match* (which are really
    merely wrappers for *fnc_cm*). Implements the design described in
    the Match Handler appendix.

> **pkg_mh_admin**

-   ***Purpose***. Functions used for sending administrative messages to
    asynchronous Match Handlers. Uses the administrative pipe instead of
    the request pipe. The Match Handler breaks from listening for a
    request and checks the administrative pipe according to wait time it
    was started with (/w switch -- default 1 minute).

-   ***Functions and Procedures***

```{=html}
<!-- -->
```
-   ***fnc_ping_handler***. Sends a "ping" message to the Match Handler
    which forces it to post a timestamp to the heartbeat file, even if
    it has not reached the heartbeat interval.

-   ***fnc_terminate_handler***. Sends a "terminate" message to the
    Match Handler which causes it to gracefully terminate itself. This
    would be the only way to terminate a Match Handler running in the
    background.

> **pkg_mh_defs**

-   ***Purpose***. *All* record and constant definitions needed for
    users of the pkg_match_handler functions. *Pkg_mh_defs* has no
    functions and no package body. Package *pkg_mh_idefs* contains
    functions for manipulating data types in *pkg_mh_defs.*

-   ***Public Variables***

```{=html}
<!-- -->
```
-   ***Return codes***. Integer codes returned by the match handler
    functions indicating,

```{=html}
<!-- -->
```
-   success,

-   one of a number of pipe-related errors,

-   a Match Handler application error.

```{=html}
<!-- -->
```
-   ***wr_searchRec***. Record structure used to pass query fields to
    the search-and-match functions.

-   ***wr_stdinRec***. Record structure used to pass carrier name and
    address to the standardization function.

-   ***wr_stdoutRec***. Record structure used to pass standardized
    fields back from the standardization function.

```{=html}
<!-- -->
```
-   ***Functions and Procedures:*** none.

> **pkg_mh_idefs**

-   ***Purpose***. Three record types are used as arguments to
    *pkg_match_handler* functions. Internally, these arguments are
    converted to a character string for sending over the Oracle pipe.
    *Pkg_mh_idefs* contains the functions that map the record fields to
    their respective positions in the string.

-   ***Strategy.***

```{=html}
<!-- -->
```
-   Pkg*\_mh_idefs* uses a data-driven approach for ease of maintenance
    in the event of changes to the MatchWare configuration files (which
    could be -- and has been -- the result of database changes) as well
    as code readability, as follows:

-   A constant integer variable is created as an identifier for each
    field in each record. Each constant is assigned an integer value
    that is unique for its record.

-   Two PL/SQL tables for mapping record fields to their corresponding
    offset and length within the character string are declared for each
    record type. Each field's constant identifier defines its position
    within each of the two tables.

-   Aggregate initializations are used to assign field position and
    field length values to the position and length tables, respectively,
    for each record type. **IMPORTANT NOTE:** These definitions must
    agree ***exactly*** with those found in the MatchWare configuration
    files *aplmatch41.rul* and *cmatch41.stn*, and C++ file
    *MatchWare_defs.cpp***.**

-   There is also a PL/SQL table of varchars containing the field names,
    not used by the *pkg_match_handler* functions, indexed in the same
    manner as the position and length tables.

```{=html}
<!-- -->
```
-   ***Package Data Types***

```{=html}
<!-- -->
```
-   ***numType***. PL/SQL table of smallint. Used in package variable
    definitions.

-   ***strType***. PL/SQL table of varchar2. Used in package variable
    definitions.

```{=html}
<!-- -->
```
-   ***Package Variables***

```{=html}
<!-- -->
```
-   ***Field identifier constants***. See Strategy discussion, above.

-   ***vavv_results***. Used for mapping the query result declaration
    number returned over the pipe to a single character.

-   ***vavi_slen***, ***vavi_spos***, ***vavv_snames***. The field
    length, position, and name tables corresponding to
    *mh_defs.wr_searchRec.*

-   ***vavi_stiLen***, ***vavi_stiPos***, ***vavv_stiNames***. The field
    length, position, and name tables corresponding to
    *mh_defs.wr_stdinRec*.

-   ***vavi_stoLen***, ***vavi_stoPos***, ***vavv_stoNames***. The field
    length, position, and name tables corresponding to
    *mh_defs.wr_stdoutRec.*

```{=html}
<!-- -->
```
-   ***Callable Functions and Procedures***

```{=html}
<!-- -->
```
-   ***fnc_search_rec_to_str***. Accepts a carrier query record of type
    *mh_defs.wr_searchRec* and maps its values into a varchar2 string.

-   ***fnc_stdin_rec_to_str***. Accepts a carrier name and address in a
    record of type *mh_defs.wr_stdinRec* and maps its values into a
    varchar2 string.

-   ***fnc_str_to_stdrec***. Accepts a varchar2 string containing a
    carrier's standardized name and address values. It maps those
    position-defined field values into a record of type
    *mh_defs.wr.stdoutRec*.

-   ***fnc_result_declaration***. Returns a character from vavv_results
    given the integer input. Does input value check.

-   ***prc_search_positions, prc_stdin_positions,
    prc_stdout_positions***. These functions provide a way to double
    check the values in the length and position tables by *deriving* the
    string positions from the field lengths. The derived positions
    *must* agree with the corresponding entries in the position table.
    (SLQ\*Plus script positions.sql, located in the same directory as
    this PL/SQL, runs these procedures).

```{=html}
<!-- -->
```
-   ***Private Functions and Procedures***

```{=html}
<!-- -->
```
-   ***Package initialization section***. Initializes all package
    tables.

-   ***fnc_mysubstr***. Utility function which returns a string
    substring given a source string, an offset (position), and substring
    length. Used when mapping from a position-defined string to a record
    structure.

> **pkg_mh_pipe**

-   ***Purpose***. Wraps calls to Oracles dbms_pipes package with error
    handling.

-   ***Important Package Variables***

```{=html}
<!-- -->
```
-   ***cv_request_pipe***. Varchar2 constant defining the name of the
    request pipe.

```{=html}
<!-- -->
```
-   ***Functions and Procedures***

```{=html}
<!-- -->
```
-   ***fnc_delete***. Drops an existing pipe.

-   ***fnc_new***. Creates a new pipe.

-   ***prc_pack***. Packs an integer or character string item onto a
    pipe.

-   ***fn_receive***. Waits for a given length of time for a message on
    a pipe.

-   ***fnc_send***. Sends a message on a pipe.

-   ***fnc_unpack***. Unpacks an integer or character string item from a
    pipe.

########  MatchWare Services API 

This Page Intentionally Blank

The terms "MatchWare Services API," or just "API" refer to the
Application Programming Interface developed at APL, which provides
packaged MatchWare functionality to programs without requiring knowledge
of the somewhat esoteric details of using MatchWare.

In reality, there is a hierarchy of four APIs. Each one is at a higher
level of abstraction from the MatchWare libraries and provides more
application-specific processing. The MatchWare Services API employs the
Object Oriented paradigm wherever possible, and all four APIs are
written as C++ classes. Each API has a single header file but some are
implemented in multiple source modules. Each API fully incorporates the
API at the level beneath it, sometimes multiply instantiating it. The
APIs are, from lowest to highest:

-   **MatchWare_class**

-   **Matchlib**

-   **Match_engine**

-   **CM_services**

A non-API class of great importance within the API is the
match_rec_class class It serves as a container for the
MatchWare-processed search and match results. Its numerous methods
provide the information that MatchWare Services API clients are
primarily interested in. The db_searches module implements the database
queries, which are inextricable from the API's logic. Since it is a
precompiled Pro\*C module with embedded SQL, it was not implemented as a
class.

######### MatchWare

The MatchWare callable library functions work within an environment that
must be initialized before being used. Special MatchWare configuration
files contain that initialization information. These configuration files
may be customized in numerous ways, and the APL in conjunction with
MatchWare has customized a set of them for this application.
Additionally, there are special configuration file sets for matching
just on name, address, USDOT Number, or ICC Docket Number

######### MatchWare Services API Class Descriptions

It is easiest to understand the API classes by starting with the
MatchWare_class API and working upwards through the hierarchy of APIs,
since each successive class in the hierarchy makes calls to the one
below it. They will be presented here in that order. Two important
support modules will also be described here.

All header files are located in the \\api\\v3\\cpp\\include directory.
All source files are located in the indicated subdirectory of
\\api\\v3\\cpp\\source. See Appendix G, "Source Code Descriptions" for
details about each function.

-   **MatchWare_class**

```{=html}
<!-- -->
```
-   *Background: MatchWare Callable Library Functions*

-   *Description*

```{=html}
<!-- -->
```
-   The MatchWare_class API provides one level of abstraction up from
    the MatchWare library functions. It groups MatchWare library calls
    together into related functions and packages all data elements
    required by the MatchWare library functions within the class.

-   Each MatchWare_class instantiation encapsulates its own,
    independent, MatchWare environment.

-   The MatchWare class functions fall into two categories: those having
    to do with standardizing and those having to do with matching.

-   The procedure for matching is as follows:

```{=html}
<!-- -->
```
-   Initialize the MatchWare *match key* by standardizing the query
    carrier.

-   Add match candidates (usually obtained from database searches) to
    the MatchWare environment.

-   Match the match candidates against the match key.

-   Fetch the candidates out in ranked order, along with their scores.

```{=html}
<!-- -->
```
-   *Variables*

```{=html}
<!-- -->
```
-   MatchWare environment globals.

```{=html}
<!-- -->
```
-   *Header*: MatchWare_class.h

-   *Source Modules*: MatchWare_class.cpp

```{=html}
<!-- -->
```
-   **Matchlib**

```{=html}
<!-- -->
```
-   *Description*

```{=html}
<!-- -->
```
-   The Matchlib class is the API which has the highest level of
    abstraction from the MatchWare library functions while still
    maintaining application independence.

-   Matchlib bundles MatchWare and database tasks into convenient
    functions according to the search and match algorithm developed at
    APL.

-   Key functions are standardize, search, rank, and search-and-rank.

-   The Matchlib API uses the MatchWare_class API and is used by the
    Match_Engine API.

```{=html}
<!-- -->
```
-   *Variables*

```{=html}
<!-- -->
```
-   Array of MatchWare_class objects. One object for each match type:
    full, name, address, dot, icc. See MatchWare_class.

-   Array of rule file names. Corresponding to each MatchWare class
    object, the rule file used to initialize that MatchWare environment.

-   Nysiis_max: two dimensional array specifying maximums counts used to
    determine whether to perform NYSIIS searches.

```{=html}
<!-- -->
```
-   *Header:* matchlib.h

-   *Source modules*: matchlib\\matchlib.cpp, matchlib\\standardize.cpp,
    matchlib\\rank.cpp, matchlib\\search.cpp (not used in match_handler)
    and matchlib\\search_and_rank.cpp.

```{=html}
<!-- -->
```
-   **Match_rec_class**

```{=html}
<!-- -->
```
-   *Description*

```{=html}
<!-- -->
```
-   The match rec class is used to capture the results of one database
    search, and the MatchWare processing of those results.

-   Match rec class contains numerous functions for processing,
    manipulating, and providing information about the search/match
    results.

```{=html}
<!-- -->
```
-   *Variables*

```{=html}
<!-- -->
```
-   Processing flags

-   List state flags

-   List position index.

-   Search type

-   Return threshold

-   Static array of various weight thresholds.

-   Integer result declaration.

-   The results list. The list is implemented as an array of records.
    The records are type match_rec_type, defined in struct_defs.h, which
    has the following attributes:

```{=html}
<!-- -->
```
-   USDOT Number

-   weights

-   number of word tokens in the name

-   active/inactive status

-   candidate string used by MatchWare containing all the carrier
    information.

```{=html}
<!-- -->
```
-   *Header*: match_rec_class.h; See also struct_defs.h.

-   *Source modules*: matchlib\\match_rec_class.cpp,
    app_specific\\application_logic.cpp

```{=html}
<!-- -->
```
-   **Db_searches**

```{=html}
<!-- -->
```
-   *Description*

```{=html}
<!-- -->
```
-   A key component of the API are the database searches, performed
    according an algorithm developed at APL and based on an analysis of
    the input. The db_seaches Pro\*C module contains all the C and
    embedded SQL code for performing the analysis and all the searches.

-   Db_searches.pc includes search_defs.h, in which the database queries
    are defined.

-   The search sequence algorithm itself is implemented in the
    search_conditions.cpp module of the match_engine class.

```{=html}
<!-- -->
```
-   *Variables*

-   *Header*: db_searches.h

-   *Source Modules*: dblib\\db_searches.pc

```{=html}
<!-- -->
```
-   **Match_engine**

```{=html}
<!-- -->
```
-   *Description*

```{=html}
<!-- -->
```
-   Third level API. Calls Matchlib functions and is called by the
    cm_services API.

-   Encapsulates the complete search and match algorithm for a single
    query consisting of one name, one address, and optionally DOT and/or
    ICC number.

-   Analyzes the input, customizes the sequence of database searches for
    that input, iteratively performs the database searches and processes
    the results through MatchWare, heuristically alters the results,
    analyzes the results to determine when to stop searching for better
    candidates, and declares the query result based on its analysis of
    the results.

```{=html}
<!-- -->
```
-   *Variables*

```{=html}
<!-- -->
```
-   Various processing-related Booleans.

-   Thresholds.

-   Parsed carrier query fields.

-   Instantiation of matchlib.

-   An array of lists of type match_rec_class.

```{=html}
<!-- -->
```
-   *Header*: Match_engine.h

-   *Source Modules*: matchlib\\match_engine.cpp,
    app_specific\\search_conditions.cpp

```{=html}
<!-- -->
```
-   **CM_services**

```{=html}
<!-- -->
```
-   *Description*

```{=html}
<!-- -->
```
-   Highest level API; most application-oriented. Provides search and
    match functionality packaged for processing Safetynet Crash and
    Inspection reports, batch add procedures, weekly OP1/MCMIS
    reconciliation files, and for processing interactive requests from
    the Match Handler.

-   All of its public methods servicing the various applications have,
    at their core, a call to private method \_search_and_match.
    \_Search_and_match centralizes carrier query processing utilizing
    calls to the match engine class.

-   Calls Match_Engine functions; is called by mh_class functions and by
    the Carrier_Match and DoubleMatch programs (legacy support).

```{=html}
<!-- -->
```
-   *Variables*

```{=html}
<!-- -->
```
-   Match_engine object

-   processing flags

-   Matchlib objects.

```{=html}
<!-- -->
```
-   *Header*: cm_services.h

-   *Source Modules*: matchlib\\cm_services.cpp

########  Carrier Search and Match Algorithm Adaptation

This Page Intentionally Blank

This appendix contains the JHU/APL Memo dated August 6, 2001 that
documents the enhancement to the Carrier Search and Match Algorithm to
process queries containing 2 pairs of Name and Address.

![](media/image22.jpeg){width="2.8402777777777777in"
height="0.3680555555555556in"}

PSE-01-047

August 6, 2001

To: Distribution

From: P. A. Frank / P. R. Karnik

Subject: Matchware Search Algorithm Adaptation

[Introduction]{.underline}

APL's Matchware Search Algorithm has been used in Carrier Match to
successfully process daily crash and inspection reports from the states
for the Federal Motor Carrier and Safety Administration (FMCSA). It was
proposed to leverage this matching capability to a new genre of
applications whose input consisted of two pairs of names and addresses.
Since Carrier Match's input consists of one name/address pair, it
couldn't be used as-is. APL therefore undertook the adaptation of the
existing software to the double name/address pair input. Additionally,
the results database, SQL scripts, and Perl scripts required
modification. The purpose of this memorandum is to discuss this
adaptation, document its requirements, discuss their impact, and
describe the solutions arrived upon.

[Requirements]{.underline}

The requirement from these new applications to search and match with
queries containing two names and addresses resulted in enough
differences from existing software to warrant separate searching and
matching code. However, for reasons discussed below, the decision was
made to adapt the existing software, even though it was in use in the
operational prototype.

Much of the supporting software -- that which stores, manipulates, and
outputs the results from Carrier Match -- was prototypical in nature and
not easily adapted to new applications. Furthermore, the propagation of
new uses being found for the Matchware Search Algorithm was a trend that
only promised to continue. It was, therefore, seen as an implicit
requirement that this adaptation be designed such that new needs could
be easily accommodated with little or no software change.

The following requirements for adaptations and enhancements were applied
to version v1.2 (currently in system test) of the Matchware Search
Algorithm. The source version was v1.1.

-   Use Matchware to process state batch uploads, OP1/MCS150
    Reconciliation, and MCS150 batch jobs. (OP1 is the application for
    operating authority used by the Licensing and Insurance branch of
    FMCSA; MCS150 is the motor carrier identification report used for
    issuance of new US DOT numbers by FMCSA).

-   Declare query results using potentially different criteria than
    Carrier Match uses for daily crash and inspection reports.

-   Reconcile operator-supplied locators and/or potential match
    resolution results with their original records and append to the
    1000-byte return file.

-   Input:

    -   1000-byte format defined by sponsor with input from development
        team, including APL.

    -   Resolved potentials files from operator.

-   Output:

    -   1000-byte format. Updated with declared query status and
        declared DOT number (when confirmed match).

    -   Locator files. Used by operator to specify locators for new
        carriers.

    -   Unresolved Potentials files. Used by operator to resolve
        potential-result-queries into definite match or no match result.
        Use same file format as with daily crash and inspection reports.

    -   Details files in human-readable format.

**[Impact Analysis]{.underline}**

In analyzing the impact of these requirements, the recurring themes were
the need to avoid divergent code (branches of the same code which have
only slight differences) and to maximize code re-use. These applied to
all areas of the Matchware Search Algorithm program -- the C++ code,
database design, SQL scripts, and operating system-level Perl scripts.

-   The single-pair matching algorithm could not be adapted as it was to
    double-pair queries. This presented the undesirable possibility of
    separate search and match engines for single- vs.
    double-name/address pair applications.

-   The methods that the Matchware Search Algorithm used for declaring
    the outcome for each query were partially based on FMCSA directives.
    The new applications had some different requirements for declaring
    outcome. This, too, could have forced implementation of divergent
    matching algorithms.

-   Since the matching code is the heart of APL's search and match
    engine, any changes to it have always required rigorous verification
    testing. Divergent code would double the maintenance load for any
    future fixes or enhancements to the match engine.

-   Any changes affecting software in the existing single-pair match
    engine would have impacted the Volpe Center's operational prototype.

-   Two name and address pairs equate to a costly four database searches
    (the cross product of the pairs).

-   Each application required different output, causing a geometric
    increase in the number of new SQL scripts.

-   Any new applications found for the Matchware Search Algorithm in the
    future might repeat some or all of the above problems.

# [Software Design Solutions]{.underline} {#software-design-solutions .Style1}

Most of the above problems were resolved by adhering to the following
guidelines whose common threads are employing consistency and code
sharing to avoid divergent code, while providing adaptations for
application differences within shared executables and scripts.

1)  Use the same match algorithm and match engine for all (single- and
    double-pair) applications. Minimize alterations to existing code in
    use by Carrier Match at the Volpe Center as much as possible. Any
    unavoidable alterations should be thoroughly tested before replacing
    the operational prototype.

2)  The match engine shall declare identical results for all
    applications (even if they have different criteria). If required,
    alter the match engine results after processing completes. Use
    small, application-specific post-processing scripts, which will
    modify values in the database's results tables before output is
    generated from those tables.

3)  Use the same executable for all double name/address-pair
    applications. Provide invocation switches for customizing run-time
    processing.

4)  Code an object-oriented class module in Perl containing the full
    complement of attributes and methods needed by all applications. Let
    each application have its own main script module that initializes
    the class and invokes methods appropriate to its needs.

5)  Code SQL scripts in an application-independent fashion.

    a.  Make use of nested SQL scripts, script input parameters, and
        defined constants in SQL\*Plus to make the scripts data-driven.
        Standardize conventions for calling highest-level and nested
        scripts, for defining constants, and for setting and restoring
        SQL\*Plus environment settings.

    b.  Each output report type shall be defined by its format --
        1000-byte or details reports, for example. Code each report type
        into a single "library" script. Each library script will specify
        a set of SQL\*Plus constants which must be defined by the
        calling script which will serve to customize the script's
        output. These constants may be as simple as numeric or character
        values for use in a select clause, or as sophisticated as a
        column or table name, or even a full SQL statement clause.

    c.  Application-dependent scripts will generate output reports by
        calling library scripts. Each output report is merely a library
        script invocation with uniquely defined library-script
        constants. Application-dependent scripts will typically call
        multiple library scripts and/or call the same library script
        multiple times, based on the application's requirements.

    d.  Redesign the database results tables to accommodate the above
        design goals.

**[Software Design Solution for the Double Name/Address Pair Search
Problem]{.underline}**

As mentioned above, having to perform four database searches (the cross
product of two name/address pairs) threatened to impact the search and
match engine's speed in returning query results. Each "database search"
is composed of up to six SQL queries on an 800,000-carrier database. Our
solution for avoiding searching the database with the two recombined
name and address pairs is based on two facts about the match engine.
First, when it calls Matchware to rank a candidate, it also gets the
DOT, ICC, name, and address component contributions to its overall
weight at the same time. Each overall score is the simple sum of the
four composite scores. Second, the match engine will never discard a
candidate whose name *[or]{.underline}* address weight is above a
certain predefined threshold.

Searching the database with the two original name/address pairs results
in two results lists, each containing the best candidates for each DOT
number found. All that recombined searches (3^rd^ and 4^th^) could hope
to accomplish would be to find a better name and address weight
combination for those same DOT numbers (since we never discard
candidates with decent name *[or]{.underline}* address weights). Since
we know that we already have the best name and address weights for each
DOT number (albeit perhaps not in the same results list), by simply
recombining candidate names from one list with candidate addresses from
the other list, we might be able to improve the name/address combination
for that DOT. The query result can be declared by merging the two
original results lists with the new candidate recombination list.

The candidates in the recombination list could change the results from
that which the two searches alone might have obtained. For example, a
query that would have been declared a potential match based on the
results of the first two searches could be promoted to a definite match
if a good enough candidate pair was found in the recombination list. On
the other hand, the third list could turn a definite match result into a
potential match result by contributing another definite match candidate
where one already existed in the first two lists, resulting in
conflicting definite candidates (which is declared as a potential
match). However, this recombination strategy will never create a
no-match outcome where a potential or definite match outcome existed
before the recombination.

This solution requires migrating the heuristics application functions
from one C++ class to another. Since that impacts code in the
operational prototype at the Volpe Center, care must be taken to test it
against the existing executable until we are satisfied that the results
are at least as good.

**[Conclusion]{.underline}**

The Matchware Search Algorithm adaptation, currently in system test,
represents a major enhancement to the operational prototype in use at
the Volpe Center in Cambridge, Massachusetts. A direct benefit of this
exercise, the adaptation of prototype software to multiple new
applications, was a clear demonstration of how the application of
object-oriented principles could result in high code re-use and low code
divergence, particularly when compared with the prototype from which it
was derived. The strategy of creating common, non-divergent code for all
single- and double-name/address-pair queries makes upkeep, maintenance,
and potential new application development manageable, as well as
guaranteeing correctness and consistency of results.

> P. A. Frank
>
> P. R. Karnik

PAF/PRK/aes

[Distribution]{.underline}:

KS Fournier

PA Frank

PR Karnik

JR Latimer

AA Mick

PD North

EM Roane

MH Robinson

This Page Intentionally Blank

########  Evaluation of Integrity Real Time for C

This Page Intentionally Blank

######### Introduction

MatchWare™ is a commercial software product developed by MatchWare
Technologies Inc. that is used in several software applications besides
New MCMIS where FMCSA has required carrier identification capabilities
(e.g., SAFETYNET 2000 and Legacy MCMIS) since 1996. The capabilities of
MatchWare were incorporated into the software product *Integrity* after
Vality Technologies Inc acquired MatchWare in July 1999.

In 2001, Vality Technologies Inc informed JHU/APL that they would
discontinue support for MatchWare software, and that MatchWare users
could upgrade to Integrity , the replacement product , for a savings of
nearly \$150,000.00 off the full product price. Based on this
information, JHU/APL advised the FMCSA to migrate all MatchWare-based
applications to Integrity. Without this migration, all MatchWare
applications for the FMCSA would be dependant on an obsolete and
unsupported version of the MatchWare software. This would be
particularly risky for the New MCMIS system, which uses the capabilities
of MatchWare as an integral component for several applications.

During discussions with Vality Technologies Inc, JHU/APL negotiated an
arrangement by which a copy of the Integrity software would be made
available to the New MCMIS team for evaluation prior to the FMCSA
purchasing of the software. This appendix provides details of the
evaluation that was performed to ensure full compatibility between
components of the original MatchWare and the new Integrity products used
in the MatchWare applications for New MCMIS.

######### The Evaluation Criteria:

While the Integrity software that replaces MatchWare has many components
and features, this evaluation was limited to the component which
replaced the MatchWare Callable Libraries for C -- Integrity Real Time
for C. The goal of the evaluation was to ensure that all MatchWare
applications developed for the FMCSA would perform in the same manner
and produce the same results when using Integrity software instead of
MatchWare. Vality Technologies Inc. provided a copy of the full
Integrity software suite to the National Transportation Volpe Center and
the Integrity Real Time for C component from that suite was provided to
JHU/APL to conduct this evaluation.

In order to evaluate Integrity Real Time for C, JHU/APL selected the
following criteria to compare it with the MatchWare Callable Libraries:

-   **MatchWare Environment:** Confirm whether all configuration files
    and function calls used by MatchWare applications are fully
    compatible with Integrity Real Time for C without requiring any
    modifications to current applications. The plan used was to attempt
    to build MatchWare applications by using the Real Time for C
    libraries instead of the MatchWare callable Libraries.

-   **Results from MatchWare:** Confirm that all output (standardized
    keys) and results (scores) from Integrity Real Time for C are
    identical to the output and results from the MatchWare Callable
    Libraries.

-   **Performance of Applications:** Confirm that all MatchWare
    applications perform with identical or better accuracy and speed by
    using Integrity Real Time for C when compared to the MatchWare
    Callable Libraries. The best way to evaluate this was to compare the
    results from the new Integrity application with those from the
    original MatchWare application.

######### The Evaluation

-   **The MatchWare Environment:** The instructions provided with the
    Integrity Real Time for C software directed the use of the library
    MT.LIB from the software distribution CD. Attempting to use MT.LIB
    from the Integrity CD to build MatchWare applications resulted in a
    large number of "multiple external definition messages" for standard
    C/C++ function calls. These were also observed while using the
    MT.LIB from the MatchWare 4.0 software distribution. To eliminate
    this problem, we decided to try using two files named RealTimeC.lib
    and RealTimeC.dll in the Integrity software distribution that
    appeared to be the equivalent to the MatchWare 4.1 "lib" and "dll"
    files.

> We were successful in building MatchWare applications using the
> Integrity RealTimeC.lib without any changes to the code other than
> replacing the C "Header" files. When we ran the newly built
> applications, we received warning messages related to "user
> classification override files" from the Integrity software. Based on
> the advise of engineers from Vality Technologies Inc. we created dummy
> ".ucl" files to suppress the warning messages. This allowed us to
> create an Integrity environment that was fully compatible with
> MatchWare for all applications.

-   **Results from MatchWare:** In order to confirm that standardized
    keys and scores from applications built with Integrity Real Time for
    C were identical to the keys and scores generated by current
    MatchWare applications, we built a copy of the MatchWare Services
    API Reference Tables using the new Integrity -based applications.

> The Match Services API Reference Tables contain standardized MatchWare
> keys and score for over 750,000 carriers from the MCMIS database.
> Comparing records from the new reference tables with those in the
> existing reference tables showed no differences. This provided a
> comprehensive method of comparing the keys and scores generated by
> Integrity-based applications with those generated by MatchWare-based
> applications.

-   **Performance of Applications:** To confirm that all application
    built with Integrity Real Time for C perform with the same or better
    accuracy and speed as current MatchWare applications, we performed
    several tests.

```{=html}
<!-- -->
```
-   First, we ran the Daily Crash and Inspection report data through the
    new Integrity applications and compared the results and performance
    times with the regularly scheduled Crash and Inspection report
    process for a period of two weeks, starting from December 6, 2001
    through December 19, 2001. This comparison, conducted under normal
    operational conditions, resulted in no differences in results
    between the new (Integrity) and current (MatchWare) versions of the
    applications for processing data containing one name and address
    field.

-   Second, in order to confirm that the new versions of the
    applications would process data containing two name and address
    fields correctly, we ran the OP1 -- MCS 150 process for seven weeks,
    from November 7, 2002 through December 17, 2002 through the new
    application. There were no observed differences in results or
    performance times between the new Integrity application the current
    MatchWare application.

######### Conclusions

Based on the successful completion of these tests, JHU/APL was able to
conclude that the new product Integrity is compatible with the existing
MatchWare software under identical configuration and operating
environments. As a result, JHU/APL recommends that the FMCSA should
transition the JHU/APL developed Carrier Search and Match software from
MatchWare Callable Libraries to Integrity Real Time for C.

This Page Intentionally Blank

########  References

This Page Intentionally Blank

\[1\] Integrity Data Re-engineering Environment, INTEGRITY Real Time:
Technical Reference Manual.

\[2\] Integrity Data Re-engineering Environment, INTEGRITY Real Time:
Application Builder's Guide for C.

\[3\] Jaro, M.A., "Advances in Record Linkage Methodology as Applied to
Matching the 1985 Census of Tampa, Florida," *Journal of the American
Statistical Association*, 1989, pp. 414-420.

\[4\] MatchWare Technologies Inc., MatchWare Callable Libraries Version
4.1, Users Manual.

\[5\] Knuth, Donald E., "The Art of Computer Programming*,*" *Sorting
and Searching*, Vol. 3, 1973.

\[6\] National Institute of Standards and Technology. *Dictionary of
Algorithms and Data Structures*, <http://www.nist.gov/dads>.

This Page Intentionally Blank