Edit in JSFiddle

var Author = function(form, initial, name, affiliations){
    var self = this;
//    self.form = form;                         // これをすると依存関係の検出時に無限ループに落ち込む
//    self.form = function(){ return form; }    // これならOK
    self.initial = ko.observable(initial).extend({ 
                    required: true,
                    pattern: {
                        message: 'First and middle names should be typed as initial(s) '+
                                 'that is expected to have a period character "." at the end.',
                        params: '\\.$'
                    }
                });
    self.name = ko.observable(name).extend({ required: true });
    self.affiliations = ko.observable(affiliations).extend({ 
                    required: true,
                    pattern: {
                        message: 'Affiliation must be specified by comma separated numbers.',
                        params: '^ *[1-9][0-9]*( *, *[1-9][0-9]*)* *$'
                    },
                    validation: [ {
                        validator: function(val) {
                            var ok = true;
                            _.each(val.split(/ *, */), function(a) {
                                if(Number(a) > form.affiliations().length ||
                                    (Number(a) == 0) )
                                    ok = false;
                            });
                            return ok;
                        },
                        message: 'Specified affiliation number does not exist.'
                    }, {
                        validator: function(val) {
                            var as = _.sortBy(
                                        _.map( val.split(/ *, */), 
                                               function(a) { return Number(a); }), 
                                        function(a) {return a});
                            for(var i=0; i<as.length-1; i++)
                                if(as[i]==as[i+1])
                                    return false;
                            return true;
                        },
                        message: 'Duplicated affiliation number exist.'
                    }]
                });
    self.errors = ko.validation.group(self, { deep: true, observable: false });
};

var Affiliation = function(institute, country) {
    var self = this;

    self.institute = ko.observable(institute).extend({ required: true});
    self.country   = ko.observable(country).extend({ required: true});
    self.errors = ko.validation.group(self, { deep: true, observable: false });
};

var TopicList

var AbstractForm = function(abstract) {
    var self = this;
    if(!abstract) {
        abstract = { id: 0, title: '', presenter: '0', stylePrefered: 'Whichever', 
                     topic1index: 0, topic2index: 0,
                     authors: [{}, {}], affiliations: [{}],
                     applyPosterAward: false, dateOfBirth:undefined, recommendation:'' };
    }

    self.id             = abstract.id;
    self.title          = ko.observable(abstract.title).extend({
                                required: true
                            });
    self.presenter      = ko.observable(abstract.presenter).extend({
                                required: true
                            });
    self.stylePrefered  = ko.observable(abstract.stylePrefered);
    
    self.topics         = [
                    "-- select one --",
                    "Bio- & macromolecules and polymers",
                    "Semiconductor and metal surface structure",
                    "Adsorbates and reactions on semiconductor and metal surfaces",
                    "Magnetic systems",
                    "Nanotubes and 1-D wires",
                    "Catalysis & electrochemistry",
                    "Nano-optical phenomena",
                    "Interaction within and between single molecules",
                    "Atom and molecular manipulation",
                    "Nano-patterning",
                    "Oxides",
                    "Cells and biological systems",
                    "Theory of probe-matter interactions",
                    "Tip preparation and functionalisation",
                    "Bottom-up process",
                    "Molecular electronics "
                ];
    self.topic1         = ko.observable(self.topics[0]).extend({
                            validation: {
                                validator: function (val) {
                                    return _.indexOf(self.topics, val) >= 1;
                                },
                                message: 'Select a topic.',
                                params: undefined
                            }                            
                        });
    self.topic2         = ko.observable(self.topics[0]);
    self.topic1index    = ko.computed({
                            read: function() { return _.indexOf(self.topics, self.topic1()); },
                            write: function(v) { self.topic1(self.topics[v]); }
                         });
    self.topic1index(abstract.topic1index);
    self.topic2index    = ko.computed({
                            read: function() { return _.indexOf(self.topics, self.topic2()); },
                            write: function(v) { self.topic2(self.topics[v]); }
                          });
    self.topic2index(abstract.topic2index);

    self.affiliations   = ko.observableArray(
                    ko.utils.arrayMap(abstract.affiliations, function(entry){
                        return new Affiliation(entry.institute, entry.country);})
                );
    self.affiliationAdd = function() {
                    self.affiliations.push(new Affiliation())
                }
    self.affiliationRemove = function(affiliation) { 
                    if(self.affiliations().length>1)
                        self.affiliations.remove(affiliation) 
                };
    self.affiliationPlaceHolder = function(index) {
                    return index==0 ? ['IBM Zurich Research Laboratory','Switzerland'] : ['',''];
                };

    self.authors        = ko.observableArray(
                    ko.utils.arrayMap(abstract.authors, function(entry){
                            return new Author(self, entry.initial, entry.name, entry.affiliations);})
                );
    self.authorAdd      = function() {
                    self.authors.push(new Author(self))
                };
    self.authorRemove   = function(author) { 
                    if(self.authors().length>1)
                        self.authors.remove(author);
                };
    self.authorUp       = function(author) { 
                    for(var i=0; i<self.authors().length; i++)
                        self.authors()[i].newIndex = i;
                    i = self.authors().indexOf(author);
                    self.authors()[i].newIndex = i-1;
                    self.authors()[i-1].newIndex = i;
                    self.authors.sort(function(left, right) { 
                        return left.newIndex == right.newIndex ? 0 : (left.newIndex < right.newIndex ? -1 : 1) ;
                    });
                    self.presenter.valueHasMutated();   // なぜこれが必要か?
                };
    self.authorDown     = function(author) { 
                    for(var i=0; i<self.authors().length; i++)
                        self.authors()[i].newIndex = i;
                    i = self.authors().indexOf(author);
                    self.authors()[i].newIndex = i+1;
                    self.authors()[i+1].newIndex = i;
                    self.authors.sort(function(left, right) { 
                        return left.newIndex == right.newIndex ? 0 : (left.newIndex < right.newIndex ? -1 : 1) ;
                    });
                    self.presenter.valueHasMutated();   // なぜこれが必要か?
                };
    self.authorPlaceHolder 
                        = function(index) {
                    return index>1 ? ['','',''] : [['G.', 'Binnig', '1'], ['H.', 'Rohrer', '1']][index];
                };

    self.applyPosterAward   = ko.observable(abstract.applyPosterAward);
    self.dateOfBirth        = ko.observable(abstract.dateOfBirth).extend({
                    required: {
                        onlyIf: function () { 
                          return self.applyPosterAward();
                        }
                    },
                    pattern: {
                        params: '^(20[01][0-9]|19[0-9][0-9])-(0?[1-9]|1[0-2])-(0?[1-9]|[12][0-9]|3[01])$',
                        message: 'Input the date in a form "yyyy-mm-dd".'
                    }
                });
    self.recommendation     = ko.observable(abstract.recommendation).extend({
                    required: {
                        onlyIf: function () { 
                          return self.applyPosterAward();
                        }
                    },
                    validation: {
                        validator: function(val) {
                            return val.split(/[ \n\t]+/).length < 210;
                        },
                        message: "Too long."
                    }
                });
                
    self.previewErrors = ko.validation.group(
        [self.authors, self.affiliations, self.title], { deep: true, observable: false });

    self.errors = ko.validation.group(self, { deep: true, observable: false });
    
    self.onSave = function() {
        var js = ko.toJS(self);
        js.topics = undefined;
        js.topic1 = undefined;
        js.topic2 = undefined;
        alert(ko.toJSON(js));
    };
    
    self.onSubmit = function(formElement) {
        if(self.errors().length > 0) {
            self.errors.showAllMessages();
            alert("There are some errors. Please correct them before submission.");
            return false;
        }
        return true;
    };
}

abstract = null;

ko.validation.init( {
    decorateElement: true, 
    errorElementClass: 'validationError',
    messageTemplate: 'validationErrorMessage'
} );

ko.applyBindings(new AbstractForm(abstract));

External resources loaded into this fiddle:

<script type="text/html" id="validationErrorMessage">
    <p data-bind="visible: field.isModified() && !field.isValid(), 
                  text: field.error" class="validationMessage"></p>
</script>

<h1>Abstract Submission Form</h1>
<form id='AbstractForm' data-bind="submit: onSubmit">

    <section>
        <h3>Registration-Id:</h3>
        <!--ko text: id --><!--/ko-->
        <input type="hidden" name="id" data-bind="value: id">
    </section>

    <section>
        <h3>Presentation Title:</h3>
        <textarea data-bind="value: title" name="title"></textarea>
    </section>

    <section>
        <h3>Author List:</h3>
        <table id="authors">
            <tr><th>Presenter</th><th>Initial</th><th>Name</th><th>Affiliations</th></tr>
            <!--ko foreach: authors-->
                <tr data-bind='validationOptions: { insertMessages: false }'>
                    <td> &nbsp; <!--ko text: $index() + 1 + '.' --><!--/ko--> &nbsp; 
                        <input type="radio" name="presenter" data-bind="checked: $parent.presenter, value: $index()"></td>
                    <td><input data-bind="value: initial, attr: {name:'author['+$index()+'].initial', placeholder:  $parent.authorPlaceHolder($index())[0]}"></td>
                    <td><input data-bind="value: name, attr:{name:'author['+$index()+'].name', placeholder:  $parent.authorPlaceHolder($index())[1]}"></td>
                    <td><input data-bind="value: affiliations, attr:{name:'author['+$index()+'].affiliations', placeholder:  $parent.authorPlaceHolder($index())[2]}"></td>
                    <td>
                        <a href="" data-bind="click: $parent.authorRemove, if:$parent.authors().length>1">remove</a>
                        <a href="" data-bind="click: $parent.authorUp, if:$index()>0">up</a>
                        <a href="" data-bind="click: $parent.authorDown, if:$index()<$parent.authors().length-1">down</a>
                    </td>
                </tr>
                <tr data-bind="visible: errors().length>0">
                    <td>
                    <td colspan="3" class="validationMessage" style="width:310px">
                        <p data-bind="validationMessage: initial" fieldName="Initial"></p>
                        <p data-bind="validationMessage: name" fieldName="Name"></p>
                        <p data-bind="validationMessage: affiliations" fieldName="Affiliations"></p>
                </tr>
            <!--/ko-->
        </table>
        <div style="padding:5px 0 0 20px;"><a href="" data-bind="click: authorAdd">add a new line</a></div>
        </div>
    </section>

    <section>
        <h3>Affiliation List:</h3>
        <table id="affiliations">
            <tr><th><th>Institute</th><th>Country</th></tr>
            <!--ko foreach: affiliations-->
                <tr data-bind='validationOptions: { insertMessages: false }'>
                    <td data-bind="text: $index() + 1 + '.'"></td>
                    <td><input data-bind="value: institute, attr:{name:'affiliation['+$index()+'].institute', placeholder: $parent.affiliationPlaceHolder($index())[0] }"></td>
                    <td><input data-bind="value: country, attr:{name:'affiliation['+$index()+'].country', placeholder: $parent.affiliationPlaceHolder($index())[1] }"></td>
                    <td><a href="" data-bind="click: $parent.affiliationRemove, if: $parent.affiliations().length>1">remove</a></td>
                </tr>
                <tr data-bind="visible: errors().length>0">
                    <td>
                    <td colspan="2" class="validationMessage" style="width:400px">
                        <p data-bind="validationMessage: institute" fieldName="Institute"></p>
                        <p data-bind="validationMessage: country" fieldName="Country"></p>
                </tr>
            <!--/ko-->
        </table>
        <div style="padding:5px 0 0 20px;"><a href="" data-bind="click: affiliationAdd">add a new line</a></div>
    </section>

    <section id="preview">
        <h3>Preview:</h3>
        <!--ko if: errors().length==0 -->
            <div class="title" data-bind="html: title()==='' ? '<span class=\'alert\'>-- title is missing --</span>' : title()"></div>
            <div class="authors" data-bind="foreach: authors">
                <span data-bind="css: $index()==$parent.presenter() ? 'author presenter' : 'author'"><!--ko text: initial--><!--/ko--> 
                <!--ko text: name--><!--/ko--><span class="affiliations" 
                data-bind="text: affiliations"></span></span><!--ko text: 
                $index()===($parent.authors().length-2) ? ' and ' : 
                $index()===($parent.authors().length-1) ? '' : ', ' --><!--/ko-->
            </div>
            <div class="affiliations" data-bind="foreach: affiliations">
                <span class="affiliation"><span class="number" data-bind="text: $index()+1"></span><!--ko text: institute--><!--/ko-->, 
                <!--ko text: country--><!--/ko--></span><!--ko text: $index()===($parent.affiliations().length-1) ? '' : ', ' --><!--/ko-->
            </div>
        <!--/ko-->
        <!--ko if: errors().length>0 -->
            <p>There are some errors in the fields.</p>
        <!--/ko-->
    </section>

    <section>
        <h3>Preferential Presentation Style:</h3>
        <div>
        <label><input type="radio" name="stylePrefered" data-bind="checked: stylePrefered" value="Oral">Oral</label>
        <label><input type="radio" name="stylePrefered" data-bind="checked: stylePrefered" value="Poster">Poster</label>
        <label><input type="radio" name="stylePrefered" data-bind="checked: stylePrefered" value="Whichever">Whichever</label>
        &nbsp; &nbsp; (
        <label><input type="radio" name="stylePrefered" data-bind="checked: stylePrefered" value="Invited">Invited</label>
        <label><input type="radio" name="stylePrefered" data-bind="checked: stylePrefered" value="Plenary">Plenary</label>
        )
        </p>
        <span data-bind="if: stylePrefered()=='Invited' || stylePrefered()=='Plenary'">
            <br>
            * Select 'Invited' or 'Plenary' only if you have received an invitation letter in advance.
        </span>
    </section>

    <section>
        <h3>Topics:</h3>
        <p>Topic1:</p>
        <div><select data-bind="options: topics, value: topic1"></select>
        <input type="hidden" name="topic1" data-bind="value: topic1index"></div>
        <br>
        <p>Topic2 (optional):</p>
        <div><select data-bind="options: topics, value: topic2"></select>
        <input type="hidden" name="topic2" data-bind="value: topic2index"></div>
    </section>

    <section id="PosterAward">
        <h3>Poster Award:</h3>
        <label><input name="applyPosterAward" type="checkbox" data-bind="checked: applyPosterAward">
        Apply for Poster Award</label>
        <p>(You must be younger than or equal to 35 years old on 2013-01-01)</p>
        <br>
        <div data-bind="css: applyPosterAward() ? '' : 'disable'">
            Date of Birth:<br>
            <div>&nbsp; <input name="dateOfBirth" placeHolder="yyyy-mm-dd" data-bind="value: dateOfBirth, enable: applyPosterAward()"></div>
            <br>
            Self recommendation of your paper (less than 200 words):<br>
            <div>&nbsp; <textarea name="recommendation" data-bind="value: recommendation, enable: applyPosterAward()"></textarea></div>
        </div>
    </section>
    <br>
    <br>
    <input type="button" data-bind="click: onSave" value="Save This Form Temporarily">
    <input type="submit" value="Submit"></input><br>
    <br>
    <br>
    <br>
    <br>
</form>
/* リセットしてしまった見出しのサイズ調整 */

h1 {
    font-size: 160%;
}

h2 {
    font-size: 130%;
}

h3 {
    font-size: 100%;
}

/* ここからが AbstractForm 関連 */

form#AbstractForm h3 {
    margin: 20px 0 10px 0;
}

form#AbstractForm textarea[name='title'] {
    width: 450px;
    height: 3em;
}

input.validationError,
select.validationError,
textarea.validationError {
    background-color: #fcc;
}

form#AbstractForm {
    line-height: 140%;
}

form#AbstractForm input,
form#AbstractForm select,
form#AbstractForm textarea {
    font-size: 100%;
}

form#AbstractForm section > :not(h3) {
    margin-left: 20px;
}

form#AbstractForm table#authors tr th,
form#AbstractForm table#authors tr td,
form#AbstractForm table#affiliations tr th,
form#AbstractForm table#affiliations tr td {
    padding: 0 5px 0 5px;
    font-weight: normal;
}

form#AbstractForm table#authors tr th,
form#AbstractForm table#affiliations tr th {
    vertical-align: top;
}

form#AbstractForm table#authors tr td:nth-child(2) input {
    width: 60px;
}

form#AbstractForm table#authors tr td:nth-child(3) input {
    width: 150px;
}

form#AbstractForm table#authors tr td:nth-child(4) input {
    width: 80px;
}

form#AbstractForm table#affiliations tr td:nth-child(2) input {
    width: 300px;
}

form#AbstractForm table#affiliations tr td:nth-child(3) input {
    width: 100px;
}

form#AbstractForm section#preview div.title {
    font-weight: bold;
}

form#AbstractForm section#preview div.authors,
form#AbstractForm section#preview div.affiliations {
    font-style: italic;
}

form#AbstractForm section#preview > div.authors > span.presenter {
    text-decoration: underline;
}

form#AbstractForm section#preview > div.authors > span.author > span.affiliations {
    vertical-align: super;
    font-size: small;
}

form#AbstractForm section#preview > div.authors > span.presenter > span.affiliations {
    text-decoration: none !important;
}

form#AbstractForm section#preview div.affiliations span.affiliation span.number {
    vertical-align: super;
    font-size: small;
}

form#AbstractForm section#PosterAward div.disable {
    color: #888;
}

form#AbstractForm section#PosterAward div textarea {
    width: 450px;
    height: 5em;
}

p[data-bind^="validationMessage:"], p.validationMessage {
    color: #f33;
}

p[data-bind^="validationMessage:"][fieldName]:before {
    content: attr(fieldName) " : "
}