Task 580: .PTF File Format
Task 580: .PTF File Format
File Format Specifications for the .PTF File Format
The .PTF file format refers to the Problem Task Format used by MOSEK, a software package for solving mathematical optimization problems. It is a human-readable text format designed to represent linear, conic, and mixed-integer optimization problems. The format is indentation-based, similar to YAML or Python code, with sections defined by header lines followed by indented content. It supports comments with '#', name strings (plain or quoted), expressions for objectives and constraints, and various domain types for conic optimization.
- List of all the properties of this file format intrinsic to its file system:
- Indentation-based structure (sections and subsections defined by increasing indentation levels; blank lines ignored for indentation).
- Line comments starting with '#' (anything after '#' on a line is ignored).
- Name strings: Plain names (alphanumeric with limited special characters) or quoted names (with escape sequences for special characters).
- Expressions: Sums of terms, where terms are linear (optional coefficient + variable name) or matrix inner products ('<' sum of matrices ';' matrix variable '>').
- Task section: Mandatory first section with task name and arbitrary body text (e.g., comments or meta-info).
- Objective section: Optional name, sense (Minimize or Maximize), and expression.
- Constraints section: Named or unnamed constraints with bounds ([lower;upper], [fixed], [lower;+inf], [-inf;upper]) or conic domains, followed by expressions (inline or indented).
- Conic domains: QUAD(N) or SOC(N) for second-order cone, RQUAD(N) or RSOC(N) for rotated second-order cone, PEXP for primal exponential, PPOW(N,P) or PPOW(N;ALPHA) for primal power, PGEOMEAN(N) for primal geometric mean, SVECPSD(N) for vectorized semidefinite, and dual versions (DEXP, DPOW, DGEOMEAN); linear domains FREE(N), POSITIVE(N), NEGATIVE(N), ZERO(N).
- Variables section: Named variables with linear bounds ([lower;upper], [fixed], [lower;+inf], [-inf;upper]) or PSD dimension [PSD(D)].
- Integer section: List of variable names that are integer-constrained.
- SymmetricMatrixes section: Named matrices with type SYMMAT(D) and lower-triangular nonzeros listed as (row, col, value).
- Solutions section: Subsections for solutions (interior, basic, integer), with problem status (unknown, feasible, infeasible, illposed, infeasible_or_unbounded), solution status (unknown, feasible, optimal, infeas_cert, illposed_cert), objective values, and per-variable/constraint statuses (unknown, super_basic, at_lower, at_upper, fixed, infinite) with primal/dual values.
- Two direct download links for files of format .PTF:
- https://docs.mosek.com/11.0/cmdtools/_src_files/lo1.ptf (linear optimization example; copy the text content from the documentation if the direct file link redirects or fails).
- https://docs.mosek.com/11.0/cmdtools/_src_files/cqo1.ptf (conic quadratic optimization example; copy the text content from the documentation if the direct file link redirects or fails).
Note: These links point to MOSEK documentation resources where the .PTF examples are provided. If the browser shows the text, save it as a .ptf file. No public direct binary .ptf files were found, but these text examples conform to the format.
- Ghost blog embedded html javascript that allows a user to drag n drop a file of format .PTF and it will dump to screen all these properties.
Drag and Drop .PTF File to Parse Properties
This HTML can be embedded in a Ghost blog post or used standalone. It parses the .PTF file, extracts sections and key properties (e.g., objective sense, constraint domains, variable bounds), and dumps them as JSON to the screen.
- Python class that can open any file of format .PTF and decode read and write and print to console all the properties from the above list.
import json
class PTFHandler:
def __init__(self, filepath):
self.filepath = filepath
self.properties = {
'sections': {}
}
def read(self):
with open(self.filepath, 'r') as f:
lines = f.readlines()
self.parse(lines)
def parse(self, lines):
current_section = None
for line in lines:
line = line.strip()
if not line or line.startswith('#'):
continue
if line.startswith('Task') or line.startswith('Objective') or line.startswith('Constraints') or line.startswith('Variables') or line.startswith('Integer') or line.startswith('SymmetricMatrixes') or line.startswith('Solutions'):
parts = line.split(maxsplit=1)
current_section = parts[0].strip('"')
self.properties['sections'][current_section] = {'name': parts[1] if len(parts) > 1 else '', 'content': []}
elif current_section:
self.properties['sections'][current_section]['content'].append(line)
self.parse_line(current_section, line)
def parse_line(self, section, line):
if section == 'Objective':
if 'Minimize' in line or 'Maximize' in line:
self.properties['sections'][section]['sense'] = line
elif section == 'Constraints':
if '[' in line and ']' in line:
parts = line.split('[')
name = parts[0].strip().strip("'")
rest = '[' + parts[1]
domain = rest.split(']')[0] + ']'
expression = rest.split(']')[1].strip()
if 'constraints' not in self.properties['sections'][section]:
self.properties['sections'][section]['constraints'] = []
self.properties['sections'][section]['constraints'].append({'name': name, 'domain': domain, 'expression': expression})
elif section == 'Variables':
if '[' in line and ']' in line:
parts = line.split('[')
name = parts[0].strip()
bounds = '[' + parts[1]
if 'variables' not in self.properties['sections'][section]:
self.properties['sections'][section]['variables'] = []
self.properties['sections'][section]['variables'].append({'name': name, 'bounds': bounds})
# Add parsing for other sections similarly
def print_properties(self):
print(json.dumps(self.properties, indent=4))
def write(self, new_filepath=None):
filepath = new_filepath or self.filepath
with open(filepath, 'w') as f:
for section, data in self.properties['sections'].items():
f.write(f"{section} {data['name']}\n")
for line in data['content']:
f.write(f" {line}\n")
# Example usage
if __name__ == '__main__':
handler = PTFHandler('example.ptf')
handler.read()
handler.print_properties()
handler.write('output.ptf')
This class reads the .PTF file, parses the properties into a dictionary, prints them as JSON to console, and can write a basic reconstruction to a new file.
- Java class that can open any file of format .PTF and decode read and write and print to console all the properties from the above list.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.ArrayList;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class PTFHandler {
private String filepath;
private Map<String, Object> properties = new HashMap<>();
public PTFHandler(String filepath) {
this.filepath = filepath;
properties.put("sections", new HashMap<String, Map<String, Object>>());
}
@SuppressWarnings("unchecked")
public void read() throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(filepath))) {
String line;
String currentSection = null;
Map<String, Map<String, Object>> sections = (Map<String, Map<String, Object>>) properties.get("sections");
while (line = br.readLine() != null) {
line = line.trim();
if (line.isEmpty() || line.startsWith("#")) continue;
if (line.matches("^\"?(Task|Objective|Constraints|Variables|Integer|SymmetricMatrixes|Solutions)\"?.*")) {
String[] parts = line.split("\\s+", 2);
currentSection = parts[0].replace("\"", "");
Map<String, Object> sectionData = new HashMap<>();
sectionData.put("name", parts.length > 1 ? parts[1] : "");
sectionData.put("content", new ArrayList<String>());
sections.put(currentSection, sectionData);
} else if (currentSection != null) {
Map<String, Object> sectionData = sections.get(currentSection);
((ArrayList<String>) sectionData.get("content")).add(line);
parseLine(currentSection, line, sectionData);
}
}
}
}
private void parseLine(String section, String line, Map<String, Object> sectionData) {
if (section.equals("Objective")) {
if (line.contains("Minimize") || line.contains("Maximize")) {
sectionData.put("sense", line);
}
} else if (section.equals("Constraints")) {
if (line.contains("[" ) && line.contains("]")) {
String[] parts = line.split("\\[", 2);
String name = parts[0].trim().replace("'", "");
String rest = "[" + parts[1];
String domain = rest.split("\\]")[0] + "]";
String expression = rest.split("\\]")[1].trim();
if (!sectionData.containsKey("constraints")) {
sectionData.put("constraints", new ArrayList<Map<String, String>>());
}
Map<String, String> constMap = new HashMap<>();
constMap.put("name", name);
constMap.put("domain", domain);
constMap.put("expression", expression);
((ArrayList<Map<String, String>>) sectionData.get("constraints")).add(constMap);
}
} else if (section.equals("Variables")) {
if (line.contains("[") && line.contains("]")) {
String[] parts = line.split("\\[", 2);
String name = parts[0].trim();
String bounds = "[" + parts[1];
if (!sectionData.containsKey("variables")) {
sectionData.put("variables", new ArrayList<Map<String, String>>());
}
Map<String, String> varMap = new HashMap<>();
varMap.put("name", name);
varMap.put("bounds", bounds);
((ArrayList<Map<String, String>>) sectionData.get("variables")).add(varMap);
}
} // Add for other sections
}
public void printProperties() {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
System.out.println(gson.toJson(properties));
}
@SuppressWarnings("unchecked")
public void write(String newFilepath) throws IOException {
try (FileWriter fw = new FileWriter(newFilepath == null ? filepath : newFilepath)) {
Map<String, Map<String, Object>> sections = (Map<String, Map<String, Object>>) properties.get("sections");
for (Map.Entry<String, Map<String, Object>> entry : sections.entrySet()) {
fw.write(entry.getKey() + " " + entry.getValue().get("name") + "\n");
ArrayList<String> content = (ArrayList<String>) entry.getValue().get("content");
for (String l : content) {
fw.write(" " + l + "\n");
}
}
}
}
public static void main(String[] args) throws IOException {
PTFHandler handler = new PTFHandler("example.ptf");
handler.read();
handler.printProperties();
handler.write("output.ptf");
}
}
This class uses Gson for JSON printing (assume dependency added). It reads, parses, prints, and writes similarly to the Python version.
- Javascript class that can open any file of format .PTF and decode read and write and print to console all the properties from the above list.
Note: For browser JS, "open" uses FileReader; for Node.js, use fs. This is for Node.js to print to console.
const fs = require('fs');
class PTFHandler {
constructor(filepath) {
this.filepath = filepath;
this.properties = {
sections: {}
};
}
read() {
const content = fs.readFileSync(this.filepath, 'utf8');
const lines = content.split('\n');
let currentSection = null;
for (let line of lines) {
line = line.trim();
if (!line || line.startsWith('#')) continue;
if (line.match(/^"?(Task|Objective|Constraints|Variables|Integer|SymmetricMatrixes|Solutions)"?.*/)) {
const parts = line.split(/\s+(?![^"]*"(?:(?:[^"]*"){2})*[^"]*$)/);
currentSection = parts[0].replace(/"/g, '');
this.properties.sections[currentSection] = { name: parts[1] || '', content: [] };
} else if (currentSection) {
this.properties.sections[currentSection].content.push(line);
this.parseLine(currentSection, line);
}
}
}
parseLine(section, line) {
if (section === 'Objective') {
if (line.match(/Minimize|Maximize/)) {
this.properties.sections[section].sense = line;
}
} else if (section === 'Constraints') {
const match = line.match(/'?(.*?)'?\s*\[(.*?)\]\s*(.*)/);
if (match) {
this.properties.sections[section].constraints = this.properties.sections[section].constraints || [];
this.properties.sections[section].constraints.push({ name: match[1], domain: '[' + match[2] + ']', expression: match[3] });
}
} else if (section === 'Variables') {
const match = line.match(/(\w+)\s*\[(.*?)\]/);
if (match) {
this.properties.sections[section].variables = this.properties.sections[section].variables || [];
this.properties.sections[section].variables.push({ name: match[1], bounds: '[' + match[2] + ']' });
}
} // Add for other sections
}
printProperties() {
console.log(JSON.stringify(this.properties, null, 2));
}
write(newFilepath = this.filepath) {
let output = '';
for (const [section, data] of Object.entries(this.properties.sections)) {
output += `${section} ${data.name}\n`;
for (const line of data.content) {
output += ` ${line}\n`;
}
}
fs.writeFileSync(newFilepath, output);
}
}
// Example usage
const handler = new PTFHandler('example.ptf');
handler.read();
handler.printProperties();
handler.write('output.ptf');
- C class that can open any file of format .PTF and decode read and write and print to console all the properties from the above list.
Note: C doesn't have "classes" like C++, so using struct with functions. For simplicity, a basic implementation without full JSON printing (uses printf).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE 1024
#define MAX_SECTIONS 10
typedef struct {
char name[64];
char content[100][MAX_LINE];
int content_count;
// For simplicity, not parsing sub-properties fully
} Section;
typedef struct {
char filepath[256];
Section sections[MAX_SECTIONS];
int section_count;
} PTFHandler;
void init_ptf(PTFHandler *handler, const char *filepath) {
strncpy(handler->filepath, filepath, 255);
handler->section_count = 0;
}
void read_ptf(PTFHandler *handler) {
FILE *fp = fopen(handler->filepath, "r");
if (!fp) {
printf("Error opening file\n");
return;
}
char line[MAX_LINE];
int current = -1;
while (fgets(line, MAX_LINE, fp)) {
char *trimmed = line;
while (*trimmed == ' ') trimmed++; // Simple trim
if (strlen(trimmed) == 0 || trimmed[0] == '#') continue;
if (strstr(trimmed, "Task") == trimmed || strstr(trimmed, "Objective") == trimmed || strstr(trimmed, "Constraints") == trimmed ||
strstr(trimmed, "Variables") == trimmed || strstr(trimmed, "Integer") == trimmed || strstr(trimmed, "SymmetricMatrixes") == trimmed ||
strstr(trimmed, "Solutions") == trimmed) {
current = handler->section_count++;
sscanf(trimmed, "%s %[^\n]", handler->sections[current].name, trimmed); // Rough parse
handler->sections[current].content_count = 0;
} else if (current >= 0) {
strncpy(handler->sections[current].content[handler->sections[current].content_count++], trimmed, MAX_LINE - 1);
// Parse further if needed
}
}
fclose(fp);
}
void print_properties(PTFHandler *handler) {
printf("{\n \"sections\": {\n");
for (int i = 0; i < handler->section_count; i++) {
printf(" \"%s\": {\n \"content\": [\n", handler->sections[i].name);
for (int j = 0; j < handler->sections[i].content_count; j++) {
printf(" \"%s\",\n", handler->sections[i].content[j]);
}
printf(" ]\n },\n");
}
printf(" }\n}\n");
}
void write_ptf(PTFHandler *handler, const char *new_filepath) {
FILE *fp = fopen(new_filepath ? new_filepath : handler->filepath, "w");
if (!fp) return;
for (int i = 0; i < handler->section_count; i++) {
fprintf(fp, "%s\n", handler->sections[i].name);
for (int j = 0; j < handler->sections[i].content_count; j++) {
fprintf(fp, " %s\n", handler->sections[i].content[j]);
}
}
fclose(fp);
}
int main() {
PTFHandler handler;
init_ptf(&handler, "example.ptf");
read_ptf(&handler);
print_properties(&handler);
write_ptf(&handler, "output.ptf");
return 0;
}
This C implementation is basic, parsing sections and content, printing a JSON-like structure to console, and writing back. More advanced parsing can be added for sub-properties.