2015-01-25 9 views
0

나는 추론에 의해 배운 "규칙"을 생성하는 데 사용되는 자바 해시지도가 있습니다. 예를 들어 입력이 같을 수 있습니다해시지도, 중복을 제거하지만 원래 발생 횟수도 저장할 수 있습니다. 자바

'prevents'('scurvy','vitamin C'). 
'contains'('vitamin C','orange'). 
'contains'('vitamin C','sauerkraut'). 
'isa'('fruit','orange'). 
'improves'('health','fruit'). 

출력은 다음과 같습니다 나는 동일한의 여러 인스턴스가 모든 것을 아주 잘 작동하는 작은 테스트를 들면하지만 내 실제 데이터 세트의

prevents(scurvy, orange). 
prevents(scurvy, sauerkraut). 
improves(health, orange). 

규칙. 나는 어떻게 든 각 규칙에 대한 발생 횟수를 저장하고 그것이 보이는 시간의 횟수와 함께 파일에 기록하려고합니다. 그 규칙이 좋은 규칙 일 가능성에 대해 순전 한 신뢰 측정 일 수 있다고 생각하기 때문에 . 이 시점에서

나는 다음과 같은 문장을 저장 :

public class Sentence { 
private String verb; 
private String object; 
private String subject; 
public Sentence(String verb, String object, String subject){ 
this.verb = verb; 
this.object = object; 
this.subject = subject; 
} 
public String getVerb(){ return verb; } 
public String getObject(){ return object; } 
public String getSubject(){ return subject; } 
public String toString(){ 
return verb + "(" + object + ", " + subject + ")"; 
} 
} 

해시 맵 구조 : 규칙을 결정

public class Ontology { 
private List<Sentence> sentences = new ArrayList<>(); 
/* 
* The following maps store the relation of a string occurring 
* as a subject or object, respectively, to the list of Sentence 
* ordinals where they occur. 
*/ 
private Map<String,List<Integer>> subject2index = new HashMap<>(); 
private Map<String,List<Integer>> object2index = new HashMap<>(); 
/* 
* This set contains strings that occur as both, 
* subject and object. This is useful for determining strings 
* acting as an in-between connecting two relations. 
*/ 
private Set<String> joints = new HashSet<>(); 
public void addSentence(Sentence s){ 
// add Sentence to the list of all Sentences 
sentences.add(s); 
// add the Subject of the Sentence to the map mapping strings 
// occurring as a subject to the ordinal of this Sentence 
List<Integer> subind = subject2index.get(s.getSubject()); 
if(subind == null){ 
    subind = new ArrayList<>(); 
    subject2index.put(s.getSubject(), subind); 
} 
subind.add(sentences.size() - 1); 
// add the Object of the Sentence to the map mapping strings 
// occurring as an object to the ordinal of this Sentence 
List<Integer> objind = object2index.get(s.getObject()); 
if(objind == null){ 
    objind = new ArrayList<>(); 
    object2index.put(s.getObject(), objind); 
} 
objind.add(sentences.size() - 1); 
// determine whether we've found a "joining" string 
if(subject2index.containsKey(s.getObject())){ 
    joints.add(s.getObject()); 
} 
if(object2index.containsKey(s.getSubject())){ 
    joints.add(s.getSubject()); 
} 
} 
public Collection<String> getJoints(){ 
return joints; 
} 
public List<Integer> getSubjectIndices(String subject){ 
return subject2index.get(subject); 
} 
public List<Integer> getObjectIndices(String object){ 
return object2index.get(object); 
} 
public Sentence getSentence(int index){ 
return sentences.get(index); 
} 
} 

마지막으로 코드 :

public static void main(String[] args) throws IOException { 
Ontology ontology = new Ontology(); 
BufferedReader br = new BufferedReader(new FileReader("file.txt")); 
Pattern p = Pattern.compile("'(.*?)'\\('(.*?)','(.*?)'\\)"); 
String line; 
while ((line = br.readLine()) != null) { 
    Matcher m = p.matcher(line); 
    if(m.matches()) { 
     String verb = m.group(1); 
     String object = m.group(2); 
     String subject = m.group(3); 
     ontology.addSentence(new Sentence(verb, object, subject)); 
    } 
} 

for(String joint: ontology.getJoints()){ 
    for(Integer subind: ontology.getSubjectIndices(joint)){ 
     Sentence xaS = ontology.getSentence(subind); 
     for(Integer obind: ontology.getObjectIndices(joint)){ 
      Sentence yOb = ontology.getSentence(obind); 
      Sentence s = new Sentence(xaS.getVerb(), 
             xaS.getObject(), 
             yOb.getSubject()); 
      System.out.println(s); 
     } 
    } 
} 
} 

가 있는가 하나의 인스턴스 만 유지하면서이 해시 맵에서 중복을 제거하는 빠르고 효율적인 방법 고유 한 각 규칙에 대해 그리고 동시에 새로운 색인을 우리가 원래지도에서 관찰 한 규칙의 동일한 인스턴스의 수와 연관 시키는가?

문장을 처리 한 후에 중복 '규칙'을 제거하고 싶습니다. 그러나 각 규칙이 발생한 빈도를 세고 고유 한 규칙과 관련된 값으로 저장하면됩니다.

답변

1

데이터 모델에 대한 몇 가지 변경 사항을 제안합니다. 다음과 같이 아주 쉽게 Map에 문장이 발생 횟수를 저장할 수 있습니다 :이 Sentence에 대한 equalshashCode 메소드를 구현에 의존

Map<Sentence, Integer> sentenceCount = new HashMap<>(); 

합니다. Sentence을 키로 사용하여 중복을 자동으로 제거합니다. 그 다음에

당신은 새로운 문장을 추가 할 수 있습니다 : 당신이 sentenceCount.keySet()를 사용하여 문장의 집합을 얻을 수 있기 때문에

public addSentence(Sentence sentence) { 
    if (!sentenceCount.containsKey(sentence)) 
     sentenceCount.put(sentence, 0); 
    sentenceCount.put(sentence, sentenceCount.get(sentence) + 1); 
} 

은 이제 더 이상 sentences 목록이 필요합니다.

제목과 개체에서 문장으로 맵이 필요한 경우 색인을 사용하지 않는 것이 좋습니다. 오류가 발생하기 쉬운 방법입니다. 대신 나는 당신이 그 (것)들에게 직접지도를 만들 제안 :

Map<String, Set<Sentence>> subjectMap; 
Map<String, Set<Sentence>> objectMap; 
당신은 찾을 이것을 사용할 수 있습니다

은, 말하자면, 횟수는 특정 주제가 나타납니다

당신은 구아바를 사용할 수있는 경우
subjectMap.get("subject").stream().mapToInt(sentenceCount::get).sum(); 
+0

흠, 문장은 아니고 규칙을 저장하고 있지만 작동 할 수 있다고 생각합니다. 그러나 한 가지 문제는 규칙의 잠재적 추가가 이미 존재하기 때문에 거절되는 횟수를 추적하는 방법입니다. 지도? 해당 번호를 연결된 규칙에 연결하는 방법은 무엇입니까? –

+0

정확히'sentenceCount' 맵의 목적입니다. 열쇠는 문장입니다 (아마 당신이 말한 것처럼 규칙이어야합니다). 그리고 값은 그것이 발생한 횟수입니다. – sprinter

+0

OP에서 addSentence를 OP로 대체해야한다고 생각하는 것처럼 보입니다.하지만 OP addSentence에서도 실제로 찾고있는 규칙이 "규칙"을 배우는 시스템입니다. (비타민 C, 오렌지)를 포함하는 입력 데이터로부터의 추론은, 출력을 방지 할 것입니다 (괴혈병, 오렌지) –

0

, 당신 Multiset의 구현을 사용할 수 있습니다. 사용자 가이드의 예제는 요구 사항과 비슷하게 들립니다.